From c3a333256261545ffe1bd7088c6c54dcb9fb759b Mon Sep 17 00:00:00 2001 From: Jaroslav Rohel Date: Tue, 21 Apr 2020 08:56:01 +0200 Subject: [PATCH] Append ctx_baseurl prefix to gpg_url (RhBug:1708628) Sometime the gpg_url contains relative path to context baseurl. In that case the code appends baseurl prefix to gpg_url. The resulting URI is normalized (solved "//", ".", and "..") The new function rhsm_url_base_join() introduce similar results as utils.url_base_join() in subscription manager. --- rhsm/rhsm-utils.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/rhsm/rhsm-utils.c b/rhsm/rhsm-utils.c index 6708a43..ee3f296 100644 --- a/rhsm/rhsm-utils.c +++ b/rhsm/rhsm-utils.c @@ -181,6 +181,97 @@ rhsm_json_array_is_subset_of_hash_table (JsonArray *array, return TRUE; } +/* + * Join a baseurl (hostname) and url (full or relpath). + * + * If url is a full url, just return it. Otherwise combine + * it with base, skipping redundant seperators if needed. + * + * Simulate the behavior of subscription manager. + */ +static gchar * +rhsm_url_base_join (const gchar *base, + const gchar *url) +{ + /* handle special cases similar to subscription manager */ + if (!url || *url == '\0') + return g_strdup (""); + if (strstr (url, "://")) + return g_strdup (url); + if (!base || *base == '\0') + return g_strdup (url); + + /* parse URI, split to schema, host, and path */ + g_autofree gchar *schema = NULL; + g_autofree gchar *host = NULL; + g_autofree gchar *path = NULL; + gchar *tmp = strstr (base, ":"); + if (tmp) + schema = g_strndup (base, tmp - base); + if (schema) + { + if (tmp[1] == '/' && tmp[2] == '/') + { + gchar *tmp2 = strstr (tmp + 3, "/"); + if (tmp2) + { + host = g_strndup (tmp + 3, tmp2 - tmp - 3); + path = g_strdup (tmp2); + } + else + host = g_strdup (tmp + 3); + } + else + path = g_strdup (tmp + 1); + } + else + path = g_strdup (base); + + /* full_path is path from base + url */ + g_autofree gchar *full_path = NULL; + if (path) + full_path = g_strconcat (path, "/", url, NULL); + else + full_path = g_strconcat ("/", url, NULL); + + /* normalize full_path + * split to vector, copy vector but skip empty and "." items, + * for each ".." source item remove last item from destination + */ + g_auto(GStrv) src_split_path = g_strsplit (full_path, "/", -1); + guint src_len = g_strv_length (src_split_path); + g_autofree gchar **dest_split_path = g_new0 (gchar *, src_len + 1); + guint dest_len = 0; + for (guint src_idx = 0; src_idx < src_len; ++src_idx) + { + gchar *src = src_split_path[src_idx]; + if (*src == '\0' || strcmp (src, ".") == 0) + continue; + if (strcmp (src, "..") == 0) + { + if (dest_len > 0) + --dest_len; + continue; + } + dest_split_path[dest_len++] = src; + } + dest_split_path[dest_len] = NULL; + + /* construct destination path */ + g_autofree gchar *tmp_path = g_strjoinv ("/", dest_split_path); + g_autofree gchar *dest_path = NULL; + if (g_str_has_suffix (url, "/") || g_str_has_suffix (url, "/.") || g_str_has_suffix (url, "/..")) + dest_path = g_strconcat (tmp_path, "/", NULL); + else + dest_path = g_strdup (tmp_path); + + /* construct and return final URI */ + if (schema) + return g_strconcat (schema, "://", host ? host : "", "/", dest_path, NULL); + else + return g_strconcat ("/", dest_path, NULL); +} + /** * rhsm_utils_yum_repo_from_context: * @ctx: an #RHSMContext. @@ -275,7 +366,8 @@ rhsm_utils_yum_repo_from_context (RHSMContext *ctx) if (json_object_has_member (repo, "gpg_url")) { const gchar *gpg_url = json_object_get_string_member (repo, "gpg_url"); - g_key_file_set_string (repofile, id, "gpgkey", gpg_url); + g_autofree gchar *gpgkey = rhsm_url_base_join (ctx_baseurl, gpg_url); + g_key_file_set_string (repofile, id, "gpgkey", gpgkey); g_key_file_set_boolean (repofile, id, "gpgcheck", TRUE); } else -- libgit2 0.28.5