Codebase list libosinfo / e0e06c7
tree: Use libsoup for http:// & https:// requests 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@redhat.com> Reviewed-by: Cole Robinson <crobinso@redhat.com> Fabiano FidĂȘncio 4 years ago
4 changed file(s) with 106 addition(s) and 34 deletion(s). Raw diff Collapse all Expand all
3636 m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
3737
3838 # Keep these two definitions in agreement.
39 GLIB_MINIMUM_VERSION="2.38"
40 GLIB_ENCODED_VERSION="GLIB_VERSION_2_38"
39 GLIB_MINIMUM_VERSION="2.44"
40 GLIB_ENCODED_VERSION="GLIB_VERSION_2_44"
4141
4242 PKG_CHECK_MODULES([LIBXML], [libxml-2.0 >= 2.6.0])
4343 PKG_CHECK_MODULES([LIBXSLT], [libxslt >= 1.0.0])
604604 osinfo_media_is_bootable;
605605
606606 osinfo_os_get_kernel_url_argument;
607
608 osinfo_tree_error_get_type;
607609 } LIBOSINFO_1.5.0;
608610
609611 /* Symbols in next release...
2525 #include <config.h>
2626
2727 #include <osinfo/osinfo.h>
28 #include "osinfo_util_private.h"
2829 #include <gio/gio.h>
2930 #include <stdlib.h>
3031 #include <string.h>
3132 #include <glib/gi18n-lib.h>
33 #include <libsoup/soup.h>
3234
3335 typedef struct _CreateFromLocationAsyncData CreateFromLocationAsyncData;
3436 struct _CreateFromLocationAsyncData {
35 GFile *file;
37 SoupSession *session;
38 SoupMessage *message;
39
40 gchar *content;
3641 gchar *location;
3742 gchar *treeinfo;
3843
4146
4247 static void create_from_location_async_data_free(CreateFromLocationAsyncData *data)
4348 {
44 g_object_unref(data->file);
49 g_object_unref(data->session);
50 g_object_unref(data->message);
4551 g_object_unref(data->res);
4652
4753 g_slice_free(CreateFromLocationAsyncData, data);
475481 * @error: The location where to store any error, or %NULL
476482 *
477483 * Creates a new #OsinfoTree for installation tree at @location. The @location
478 * could be any URI that GIO can handle or a local path.
484 * could be a http:// or a https:// URI.
479485 *
480486 * NOTE: Currently this only works for trees with a .treeinfo file
481487 *
652658 osinfo_tree_create_from_location_async_helper(CreateFromLocationAsyncData *data,
653659 const gchar *treeinfo);
654660
661 static void on_content_read(GObject *source,
662 GAsyncResult *res,
663 gpointer user_data)
664 {
665 CreateFromLocationAsyncData *data;
666 gsize length = 0;
667 GError *error = NULL;
668 OsinfoTree *ret;
669
670 data = (CreateFromLocationAsyncData *)user_data;
671
672 if (!g_input_stream_read_all_finish(G_INPUT_STREAM(source),
673 res,
674 &length,
675 &error)) {
676 g_prefix_error(&error, _("Failed to load .treeinfo|treeinfo content: "));
677 g_task_return_error(data->res, error);
678 create_from_location_async_data_free(data);
679 }
680
681 if (!(ret = load_keyinfo(data->location,
682 data->content,
683 length,
684 &error))) {
685 g_prefix_error(&error, _("Failed to process keyinfo file: "));
686 g_task_return_error(data->res, error);
687 goto cleanup;
688 }
689
690 g_task_return_pointer(data->res, ret, g_object_unref);
691
692 cleanup:
693 create_from_location_async_data_free(data);
694 }
695
655696 static void on_location_read(GObject *source,
656697 GAsyncResult *res,
657698 gpointer user_data)
658699 {
659700 CreateFromLocationAsyncData *data;
660701 GError *error = NULL;
661 gchar *content = NULL;
662 gsize length = 0;
663 OsinfoTree *ret = NULL;
702 GInputStream *stream;
703 goffset content_size;
664704
665705 data = (CreateFromLocationAsyncData *)user_data;
666706
667 if (!g_file_load_contents_finish(G_FILE(source),
668 res,
669 &content,
670 &length,
671 NULL,
672 &error)) {
707 stream = soup_session_send_finish(SOUP_SESSION(source),
708 res,
709 &error);
710 if (stream == NULL ||
711 !SOUP_STATUS_IS_SUCCESSFUL(data->message->status_code)) {
673712 /* It means no ".treeinfo" file has been found. Try again, this time
674713 * looking for a "treeinfo" file. */
675714 if (g_str_equal(data->treeinfo, ".treeinfo")) {
677716 return;
678717 }
679718
719 if (error == NULL) {
720 g_set_error_literal(&error,
721 OSINFO_TREE_ERROR,
722 OSINFO_TREE_ERROR_NO_TREEINFO,
723 soup_status_get_phrase(data->message->status_code));
724 }
680725 g_prefix_error(&error, _("Failed to load .treeinfo|treeinfo file: "));
681726 g_task_return_error(data->res, error);
682727 create_from_location_async_data_free(data);
683728 return;
684729 }
685730
686 if (!(ret = load_keyinfo(data->location,
687 content,
688 length,
689 &error))) {
690 g_prefix_error(&error, _("Failed to process keyinfo file: "));
691 g_task_return_error(data->res, error);
692 goto cleanup;
693 }
694
695 g_task_return_pointer(data->res, ret, g_object_unref);
696
697 cleanup:
698 create_from_location_async_data_free(data);
699 g_free(content);
731 content_size = soup_message_headers_get_content_length(data->message->response_headers);
732 data->content = g_malloc0(content_size);
733
734 g_input_stream_read_all_async(stream,
735 data->content,
736 content_size,
737 g_task_get_priority(data->res),
738 g_task_get_cancellable(data->res),
739 on_content_read,
740 data);
700741 }
701742
702743 static void
707748
708749 g_return_if_fail(treeinfo != NULL);
709750
751 if (!osinfo_util_requires_soup(data->location)) {
752 GError *error = NULL;
753
754 g_set_error_literal(&error,
755 OSINFO_TREE_ERROR,
756 OSINFO_TREE_ERROR_NOT_SUPPORTED_PROTOCOL,
757 _("URL protocol is not supported"));
758
759 g_task_return_error(data->res, error);
760 }
761
710762 location = g_strdup_printf("%s/%s", data->location, treeinfo);
711763
712 g_clear_object(&data->file);
713 data->file = g_file_new_for_uri(location);
764 if (data->session == NULL)
765 data->session = soup_session_new();
766
767 g_clear_object(&data->message);
768 data->message = soup_message_new("GET", location);
714769
715770 g_free(data->treeinfo);
716771 data->treeinfo = g_strdup(treeinfo);
717772
718 g_file_load_contents_async(data->file,
719 g_task_get_cancellable(data->res),
720 on_location_read,
721 data);
773 soup_session_send_async(data->session,
774 data->message,
775 g_task_get_cancellable(data->res),
776 on_location_read,
777 data);
722778 g_free(location);
723779 }
724780
3333 osinfo_tree_error_quark (void) G_GNUC_CONST;
3434
3535 #define OSINFO_TREE_ERROR (osinfo_tree_error_quark ())
36
37 /**
38 * OsinfoTreeError:
39 * Since: 1.6.0
40 * @OSINFO_TREE_ERROR_NO_TREEINFO: No treeinfo found;
41 * @OSINFO_TREE_ERROR_NOT_SUPPORTED_PROTOCOL: The URL protocol is not supported.
42 *
43 * #GError codes used for errors in the #OSINFO_TREE_ERROR domain, during
44 * reading the treeinfo from a URI.
45 */
46 typedef enum {
47 OSINFO_TREE_ERROR_NO_TREEINFO,
48 OSINFO_TREE_ERROR_NOT_SUPPORTED_PROTOCOL
49 } OsinfoTreeError;
3650
3751
3852 /*