[gnome-software: 1/2] appstream: implement parsing media_baseurl




commit fb0a79fc9d581e30d708bbfa635705f93777a20f
Author: Pablo Correa Gómez <ablocorrea hotmail com>
Date:   Sat Jan 15 22:51:10 2022 +0100

    appstream: implement parsing media_baseurl
    
    This property was not documented for XML data until quite
    recently: https://github.com/ximion/appstream/pull/371
    
    However, remote icons and screenshots generated with appstream-generator
    only contain urls relative to media_baseurl property. Fix all relative uris
    prepending the corresponding media_baseurl for those objects to be downloadable.

 lib/gs-appstream.c                 | 19 +++++++++++
 lib/gs-appstream.h                 |  2 ++
 plugins/core/gs-plugin-appstream.c | 64 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 85 insertions(+)
---
diff --git a/lib/gs-appstream.c b/lib/gs-appstream.c
index e7edc9bb5..0334447c4 100644
--- a/lib/gs-appstream.c
+++ b/lib/gs-appstream.c
@@ -1877,3 +1877,22 @@ gs_appstream_component_add_extra_info (XbBuilderNode *component)
                break;
        }
 }
+
+/* Resolve any media URIs which are actually relative
+ * paths against the media_baseurl property */
+void
+gs_appstream_component_fix_url (XbBuilderNode *component, const gchar *baseurl)
+{
+       const gchar *text = xb_builder_node_get_text (component);
+       g_autofree gchar *url = NULL;
+
+       if (text == NULL)
+               return;
+
+       if (g_str_has_prefix (text, "http:") ||
+           g_str_has_prefix (text, "https:"))
+               return;
+
+       url = g_strconcat (baseurl, "/", text, NULL);
+       xb_builder_node_set_text (component, url , -1);
+}
diff --git a/lib/gs-appstream.h b/lib/gs-appstream.h
index 5bddf9136..fbc68a1a4 100644
--- a/lib/gs-appstream.h
+++ b/lib/gs-appstream.h
@@ -72,5 +72,7 @@ void           gs_appstream_component_add_icon        (XbBuilderNode  *component,
                                                         const gchar    *str);
 void            gs_appstream_component_add_provide     (XbBuilderNode  *component,
                                                         const gchar    *str);
+void            gs_appstream_component_fix_url         (XbBuilderNode  *component,
+                                                        const gchar    *baseurl);
 
 G_END_DECLS
diff --git a/plugins/core/gs-plugin-appstream.c b/plugins/core/gs-plugin-appstream.c
index 36847e4ae..a00505d4a 100644
--- a/plugins/core/gs-plugin-appstream.c
+++ b/plugins/core/gs-plugin-appstream.c
@@ -148,6 +148,60 @@ gs_plugin_appstream_add_origin_keyword_cb (XbBuilderFixup *self,
        return TRUE;
 }
 
+static void
+gs_plugin_appstream_media_baseurl_free (gpointer user_data)
+{
+       g_string_free ((GString *) user_data, TRUE);
+}
+
+static gboolean
+gs_plugin_appstream_media_baseurl_cb (XbBuilderFixup *self,
+                                     XbBuilderNode *bn,
+                                     gpointer user_data,
+                                     GError **error)
+{
+       GString *baseurl = user_data;
+       if (g_strcmp0 (xb_builder_node_get_element (bn), "components") == 0) {
+               const gchar *url = xb_builder_node_get_attr (bn, "media_baseurl");
+               if (url == NULL) {
+                       g_string_truncate (baseurl, 0);
+                       return TRUE;
+               }
+               g_string_assign (baseurl, url);
+               return TRUE;
+       }
+
+       if (baseurl->len == 0)
+               return TRUE;
+
+       if (g_strcmp0 (xb_builder_node_get_element (bn), "icon") == 0) {
+               const gchar *type = xb_builder_node_get_attr (bn, "type");
+               if (g_strcmp0 (type, "remote") != 0)
+                       return TRUE;
+               gs_appstream_component_fix_url (bn, baseurl->str);
+       } else if (g_strcmp0 (xb_builder_node_get_element (bn), "screenshots") == 0) {
+               GPtrArray *screenshots = xb_builder_node_get_children (bn);
+               for (guint i = 0; i < screenshots->len; i++) {
+                       XbBuilderNode *screenshot = g_ptr_array_index (screenshots, i);
+                       GPtrArray *children = NULL;
+                       /* Type-check for security */
+                       if (g_strcmp0 (xb_builder_node_get_element (screenshot), "screenshot") != 0) {
+                               continue;
+                       }
+                       children = xb_builder_node_get_children (screenshot);
+                       for (guint j = 0; j < children->len; j++) {
+                               XbBuilderNode *child = g_ptr_array_index (children, j);
+                               const gchar *element = xb_builder_node_get_element (child);
+                               if (g_strcmp0 (element, "image") != 0 &&
+                                   g_strcmp0 (element, "video") != 0)
+                                       continue;
+                               gs_appstream_component_fix_url (child, baseurl->str);
+                       }
+               }
+       }
+       return TRUE;
+}
+
 static gboolean
 gs_plugin_appstream_load_appdata_fn (GsPluginAppstream  *self,
                                      XbBuilder          *builder,
@@ -413,6 +467,8 @@ gs_plugin_appstream_load_appstream_fn (GsPluginAppstream  *self,
 #if LIBXMLB_CHECK_VERSION(0,3,1)
        g_autoptr(XbBuilderFixup) fixup4 = NULL;
 #endif
+       g_autoptr(XbBuilderFixup) fixup5 = NULL;
+       GString *media_baseurl = g_string_new (NULL);
        g_autoptr(XbBuilderSource) source = xb_builder_source_new ();
 
        /* add support for DEP-11 files */
@@ -468,6 +524,14 @@ gs_plugin_appstream_load_appstream_fn (GsPluginAppstream  *self,
        xb_builder_source_add_fixup (source, fixup4);
 #endif
 
+       /* prepend media_baseurl to remote relative URLs */
+       fixup5 = xb_builder_fixup_new ("MediaBaseUrl",
+                                      gs_plugin_appstream_media_baseurl_cb,
+                                      media_baseurl,
+                                      gs_plugin_appstream_media_baseurl_free);
+       xb_builder_fixup_set_max_depth (fixup5, 3);
+       xb_builder_source_add_fixup (source, fixup5);
+
        /* success */
        xb_builder_import_source (builder, source);
        return TRUE;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]