[Libosinfo] [libosinfo PATCH 6/7] tree: Use libsoup for http://, https://, and ftp:// requests

Fabiano Fidêncio fidencio at redhat.com
Thu Jun 27 12:56:12 UTC 2019


As osinfo_tree_create_from_location() handles non-local requests, it'd
end up relying on GVFS under the hood, which would cause this API to not
work when called from an app running as root.

In order to avoid this situation, let's rely on libsoup for this cases.

It's important to mention that glib minimum version has been bumped to
2.44 as that's the version where g_input_stream_read_all_async() has
been introuced.

https://gitlab.com/libosinfo/libosinfo/issues/30

Signed-off-by: Fabiano Fidêncio <fidencio at redhat.com>
---
 configure.ac          |   4 +-
 osinfo/libosinfo.syms |   2 +
 osinfo/osinfo_tree.c  | 104 ++++++++++++++++++++++++++++++------------
 osinfo/osinfo_tree.h  |  11 +++++
 4 files changed, 89 insertions(+), 32 deletions(-)

diff --git a/configure.ac b/configure.ac
index 02ea1df..0fde62c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -37,8 +37,8 @@ m4_if(m4_version_compare([2.61a.100],
 m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
 
 # Keep these two definitions in agreement.
-GLIB_MINIMUM_VERSION="2.38"
-GLIB_ENCODED_VERSION="GLIB_VERSION_2_38"
+GLIB_MINIMUM_VERSION="2.44"
+GLIB_ENCODED_VERSION="GLIB_VERSION_2_44"
 
 PKG_CHECK_MODULES([LIBXML], [libxml-2.0 >= 2.6.0])
 PKG_CHECK_MODULES([LIBXSLT], [libxslt >= 1.0.0])
diff --git a/osinfo/libosinfo.syms b/osinfo/libosinfo.syms
index 4e96f16..f0f7ae6 100644
--- a/osinfo/libosinfo.syms
+++ b/osinfo/libosinfo.syms
@@ -593,6 +593,8 @@ LIBOSINFO_1.6.0 {
 	osinfo_media_is_bootable;
 
 	osinfo_os_get_kernel_url_argument;
+
+	osinfo_tree_error_get_type;
 } LIBOSINFO_1.5.0;
 
 /* Symbols in next release...
diff --git a/osinfo/osinfo_tree.c b/osinfo/osinfo_tree.c
index 9996575..c551047 100644
--- a/osinfo/osinfo_tree.c
+++ b/osinfo/osinfo_tree.c
@@ -30,10 +30,14 @@
 #include <stdlib.h>
 #include <string.h>
 #include <glib/gi18n-lib.h>
+#include <libsoup/soup.h>
 
 typedef struct _CreateFromLocationAsyncData CreateFromLocationAsyncData;
 struct _CreateFromLocationAsyncData {
-    GFile *file;
+    SoupSession *session;
+    SoupMessage *message;
+
+    gchar *content;
     gchar *location;
     gchar *treeinfo;
 
@@ -42,7 +46,8 @@ struct _CreateFromLocationAsyncData {
 
 static void create_from_location_async_data_free(CreateFromLocationAsyncData *data)
 {
-    g_object_unref(data->file);
+    g_object_unref(data->session);
+    g_object_unref(data->message);
     g_object_unref(data->res);
 
     g_slice_free(CreateFromLocationAsyncData, data);
@@ -630,24 +635,57 @@ static void
 osinfo_tree_create_from_location_async_helper(CreateFromLocationAsyncData *data,
                                               const gchar *treeinfo);
 
+static void on_content_read(GObject *source,
+                            GAsyncResult *res,
+                            gpointer user_data)
+{
+    CreateFromLocationAsyncData *data;
+    gsize length = 0;
+    GError *error = NULL;
+    OsinfoTree *ret;
+
+    data = (CreateFromLocationAsyncData *)user_data;
+
+    if (!g_input_stream_read_all_finish(G_INPUT_STREAM(source),
+                                        res,
+                                        &length,
+                                        &error)) {
+        g_prefix_error(&error, _("Failed to load .treeinfo|treeinfo content: "));
+        g_task_return_error(data->res, error);
+        create_from_location_async_data_free(data);
+    }
+
+    if (!(ret = load_keyinfo(data->location,
+                             data->content,
+                             length,
+                             &error))) {
+        g_prefix_error(&error, _("Failed to process keyinfo file: "));
+        g_task_return_error(data->res, error);
+        goto cleanup;
+    }
+
+    g_task_return_pointer(data->res, ret, g_object_unref);
+
+ cleanup:
+    create_from_location_async_data_free(data);
+}
+
 static void on_location_read(GObject *source,
                              GAsyncResult *res,
                              gpointer user_data)
 {
     CreateFromLocationAsyncData *data;
     GError *error = NULL;
-    gchar *content = NULL;
-    gsize length = 0;
-    OsinfoTree *ret = NULL;
+    GInputStream *stream;
+    goffset content_size;
 
     data = (CreateFromLocationAsyncData *)user_data;
 
-    if (!g_file_load_contents_finish(G_FILE(source),
-                                     res,
-                                     &content,
-                                     &length,
-                                     NULL,
-                                     &error)) {
+    stream = soup_session_send_finish(SOUP_SESSION(source),
+                                      res,
+                                      &error);
+    if (stream == NULL ||
+        !SOUP_STATUS_IS_SUCCESSFUL(data->message->status_code)) {
         /* It means no ".treeinfo" file has been found. Try again, this time
          * looking for a "treeinfo" file. */
         if (g_str_equal(data->treeinfo, ".treeinfo")) {
@@ -655,26 +693,28 @@ static void on_location_read(GObject *source,
             return;
         }
 
+        if (error == NULL) {
+            g_set_error_literal(&error,
+                                OSINFO_TREE_ERROR,
+                                OSINFO_TREE_ERROR_NO_TREEINFO,
+                                soup_status_get_phrase(data->message->status_code));
+        }
         g_prefix_error(&error, _("Failed to load .treeinfo|treeinfo file: "));
         g_task_return_error(data->res, error);
         create_from_location_async_data_free(data);
         return;
     }
 
-    if (!(ret = load_keyinfo(data->location,
-                             content,
-                             length,
-                             &error))) {
-        g_prefix_error(&error, _("Failed to process keyinfo file: "));
-        g_task_return_error(data->res, error);
-        goto cleanup;
-    }
-
-    g_task_return_pointer(data->res, ret, g_object_unref);
+    content_size = soup_message_headers_get_content_length(data->message->response_headers);
+    data->content = g_malloc0(content_size);
 
- cleanup:
-    create_from_location_async_data_free(data);
-    g_free(content);
+    g_input_stream_read_all_async(stream,
+                                  data->content,
+                                  content_size,
+                                  g_task_get_priority(data->res),
+                                  g_task_get_cancellable(data->res),
+                                  on_content_read,
+                                  data);
 }
 
 static void
@@ -687,16 +727,20 @@ osinfo_tree_create_from_location_async_helper(CreateFromLocationAsyncData *data,
 
     location = g_strdup_printf("%s/%s", data->location, treeinfo);
 
-    g_clear_object(&data->file);
-    data->file = g_file_new_for_uri(location);
+    if (data->session == NULL)
+        data->session = soup_session_new();
+
+    g_clear_object(&data->message);
+    data->message = soup_message_new("GET", location);
 
     g_free(data->treeinfo);
     data->treeinfo = g_strdup(treeinfo);
 
-    g_file_load_contents_async(data->file,
-                               g_task_get_cancellable(data->res),
-                               on_location_read,
-                               data);
+    soup_session_send_async(data->session,
+                            data->message,
+                            g_task_get_cancellable(data->res),
+                            on_location_read,
+                            data);
     g_free(location);
 }
 
diff --git a/osinfo/osinfo_tree.h b/osinfo/osinfo_tree.h
index 661d06b..711c244 100644
--- a/osinfo/osinfo_tree.h
+++ b/osinfo/osinfo_tree.h
@@ -35,6 +35,17 @@ osinfo_tree_error_quark (void) G_GNUC_CONST;
 
 #define OSINFO_TREE_ERROR (osinfo_tree_error_quark ())
 
+/**
+ * OsinfoTreeError:
+ * @OSINFO_TREE_ERROR_NO_TREEINFO: No treeinfo found;
+ *
+ * #GError codes used for errors in the #OSINFO_TREE_ERROR domain, during
+ * reading the treeinfo from a URI.
+ */
+typedef enum {
+    OSINFO_TREE_ERROR_NO_TREEINFO
+} OsinfoTreeError;
+
 
 /*
  * Type macros.
-- 
2.21.0




More information about the Libosinfo mailing list