From ab2f253ca7ff65462c3f429cdeb9e58798f7091d Mon Sep 17 00:00:00 2001 From: Niels De Graef Date: Sun, 26 Jun 2022 20:22:06 +0200 Subject: [PATCH] hkp: Port to libsoup3 --- meson.build | 2 +- pgp/seahorse-hkp-source.c | 436 +++++++++++++++++--------------------- 2 files changed, 198 insertions(+), 240 deletions(-) diff --git a/meson.build b/meson.build index ec83e64f..0e3c7b16 100644 --- a/meson.build +++ b/meson.build @@ -78,7 +78,7 @@ endif if get_option('hkp-support') add_project_arguments('-D', 'WITH_HKP', language: 'vala') endif -libsoup = dependency('libsoup-2.4', version: '>= 2.33.92', required: get_option('hkp-support')) +libsoup = dependency('libsoup-3.0', required: get_option('hkp-support')) avahi_client = dependency('avahi-client', required: get_option('key-sharing')) avahi_glib = dependency('avahi-glib', version: '>= 0.6', required: get_option('key-sharing')) diff --git a/pgp/seahorse-hkp-source.c b/pgp/seahorse-hkp-source.c index 515e0da4..1e906f90 100644 --- a/pgp/seahorse-hkp-source.c +++ b/pgp/seahorse-hkp-source.c @@ -51,11 +51,6 @@ #define PGP_KEY_BEGIN "-----BEGIN PGP PUBLIC KEY BLOCK-----" #define PGP_KEY_END "-----END PGP PUBLIC KEY BLOCK-----" -#define SOUP_MESSAGE_IS_ERROR(msg) \ - (SOUP_STATUS_IS_TRANSPORT_ERROR((msg)->status_code) || \ - SOUP_STATUS_IS_CLIENT_ERROR((msg)->status_code) || \ - SOUP_STATUS_IS_SERVER_ERROR((msg)->status_code)) - G_DEFINE_QUARK (seahorse-hkp-error, seahorse_hkp_error); struct _SeahorseHKPSource { @@ -64,33 +59,48 @@ struct _SeahorseHKPSource { G_DEFINE_TYPE (SeahorseHKPSource, seahorse_hkp_source, SEAHORSE_TYPE_SERVER_SOURCE); -/** - * self: The SeahorseSource to use as server for the uri - * path: The path to add to the SOUP uri - * - * Returns: A #SoupUri with server, port and paths - */ -static SoupURI* -get_http_server_uri (SeahorseHKPSource *self, const char *path) +/* Helper method */ +static GUri * +get_http_server_uri (SeahorseHKPSource *self, + const char *path, + GHashTable *query_hash) { - g_autoptr(SoupURI) uri = NULL; - g_autofree char *conf_uri = NULL; - - conf_uri = seahorse_place_get_uri (SEAHORSE_PLACE (self)); - g_return_val_if_fail (conf_uri != NULL, NULL); - - if (strncasecmp (conf_uri, "hkp:", 4) == 0) { - g_autofree char *t = g_strdup_printf ("http:%s", conf_uri + 4); - uri = soup_uri_new (t); - } else if (strncasecmp (conf_uri, "hkps:", 5) == 0) { - g_autofree char *t = g_strdup_printf ("https:%s", conf_uri + 5); - uri = soup_uri_new (t); + g_autofree char *uri = NULL; + gboolean parsed; + g_autofree char *scheme = NULL; + g_autofree char *host = NULL; + int port; + g_autoptr(GError) error = NULL; + g_autofree char *query = NULL; + + /* Take the (user-)configured URI */ + uri = seahorse_place_get_uri (SEAHORSE_PLACE (self)); + g_return_val_if_fail (uri != NULL, NULL); + + /* NOTE: seahorse_hkp_is_valid_uri already checked certain fields */ + parsed = g_uri_split (uri, G_URI_FLAGS_NONE, + &scheme, NULL, &host, &port, NULL, NULL, NULL, + &error); + if (!parsed) { + g_warning ("Bad URL for HKP server '%s': %s", uri, error->message); + return NULL; } - soup_uri_set_path (uri, path); + /* Fixup the scheme if needed */ + if (g_strcmp0 (scheme, "hkp") == 0) { + g_free (scheme); + scheme = g_strdup ("http"); + } else if (g_strcmp0 (scheme, "hkps") == 0) { + g_free (scheme); + scheme = g_strdup ("https"); + } - g_debug ("HTTP Server URI: %s", soup_uri_to_string(uri, FALSE)); - return g_steal_pointer (&uri); + /* We assume people won't use a query (and validate that earlier also) */ + if (query_hash != NULL) + query = soup_form_encode_hash (query_hash); + + return g_uri_build (G_URI_FLAGS_NONE, + scheme, NULL, host, port, path, query, NULL); } static SoupSession * @@ -99,7 +109,7 @@ create_hkp_soup_session (void) SoupSession *session; #ifdef WITH_DEBUG g_autoptr(SoupLogger) logger = NULL; - const gchar *env; + const char *env; #endif session = soup_session_new (); @@ -107,7 +117,7 @@ create_hkp_soup_session (void) #ifdef WITH_DEBUG env = g_getenv ("G_MESSAGES_DEBUG"); if (env && strstr (env, "seahorse")) { - logger = soup_logger_new (SOUP_LOGGER_LOG_BODY, -1); + logger = soup_logger_new (SOUP_LOGGER_LOG_BODY); soup_session_add_feature (session, SOUP_SESSION_FEATURE (logger)); } #endif @@ -127,10 +137,10 @@ create_hkp_soup_session (void) * **/ static void -dehtmlize (gchar *line) +dehtmlize (char *line) { int parsedindex = 0; - gchar *parsed = line; + char *parsed = line; g_return_if_fail (line); @@ -230,10 +240,8 @@ parse_hkp_flags (char *flags) GList * seahorse_hkp_parse_lookup_response (const char *response) { - /* - * Use The OpenPGP HTTP Keyserver Protocol (HKP) to search and get keys - * https://tools.ietf.org/html/draft-shaw-openpgp-hkp-00#section-5 - */ + /* Use The OpenPGP HTTP Keyserver Protocol (HKP) to search and get keys + * https://tools.ietf.org/html/draft-shaw-openpgp-hkp-00#section-5 */ g_auto(GStrv) lines = NULL; SeahorsePgpKey *key = NULL; GList *keys = NULL; @@ -377,7 +385,7 @@ seahorse_hkp_parse_lookup_response (const char *response) seahorse_pgp_key_realize (SEAHORSE_PGP_KEY (k->data)); if (key_total != 0 && key_total != key_count) { - g_message ("HKP Parse; Warning: Issue during HKP parsing, only %d keys were parsed out of %d", key_count, key_total); + g_warning ("HKP Parse: Could only parse %d keys out of %d", key_count, key_total); } else { g_debug ("HKP Parse: %d keys parsed successfully", key_count); } @@ -441,10 +449,7 @@ get_send_result (const char *response) static gboolean detect_key (const char *text, int len, const char **start, const char **end) { - const gchar *t; - - if (len == -1) - len = strlen (text); + const char *t; /* Find the first of the headers */ if ((t = g_strstr_len (text, len, PGP_KEY_BEGIN)) == NULL) @@ -461,55 +466,9 @@ detect_key (const char *text, int len, const char **start, const char **end) return TRUE; } -static gboolean -hkp_message_propagate_error (SeahorseHKPSource *self, - SoupMessage *message, - GError **error) -{ - g_autofree char *uri = NULL; - g_autofree char *text = NULL; - - if (!SOUP_MESSAGE_IS_ERROR (message)) - return FALSE; - - if (message->status_code == SOUP_STATUS_CANCELLED) { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED, - _("The operation was cancelled")); - return TRUE; - } - - uri = seahorse_place_get_uri (SEAHORSE_PLACE (self)); - - /* Make the body lower case, and no tags */ - text = g_strndup (message->response_body->data, message->response_body->length); - if (text != NULL) { - char *text_lower; - - dehtmlize (text); - text_lower = g_ascii_strdown (text, -1); - g_free (text); - text = text_lower; - } - - if (text && strstr (text, "no keys")) - return FALSE; /* not found is not an error */ - - if (text && strstr (text, "too many")) { - g_set_error (error, HKP_ERROR_DOMAIN, 0, - _("Search was not specific enough. Server “%s” found too many keys."), - uri); - } else { - g_set_error (error, HKP_ERROR_DOMAIN, message->status_code, - _("Couldn’t communicate with server “%s”: %s"), - uri, message->reason_phrase); - } - - return TRUE; -} - static void on_session_cancelled (GCancellable *cancellable, - gpointer user_data) + void *user_data) { SoupSession *session = user_data; soup_session_abort (session); @@ -517,49 +476,54 @@ on_session_cancelled (GCancellable *cancellable, typedef struct { SeahorseHKPSource *source; - GCancellable *cancellable; - gulong cancelled_sig; SoupSession *session; + SoupMessage *message; + GString *response; int requests; GcrSimpleCollection *results; -} source_search_closure; +} SearchClosure; static void -source_search_free (gpointer data) +source_search_free (void *data) { - source_search_closure *closure = data; - g_object_unref (closure->source); - g_cancellable_disconnect (closure->cancellable, closure->cancelled_sig); - g_clear_object (&closure->cancellable); - g_object_unref (closure->session); + SearchClosure *closure = data; + g_clear_object (&closure->source); + g_clear_object (&closure->message); + if (closure->response != NULL) + g_string_free (closure->response, TRUE); + g_clear_object (&closure->session); g_clear_object (&closure->results); g_free (closure); } static void -on_search_message_complete (SoupSession *session, - SoupMessage *message, - gpointer user_data) +on_search_message_complete (GObject *object, + GAsyncResult *result, + void *user_data) { + SoupSession *session = SOUP_SESSION (object); g_autoptr(GTask) task = G_TASK (user_data); - source_search_closure *closure = g_task_get_task_data (task); + SearchClosure *closure = g_task_get_task_data (task); + GCancellable *cancellable = g_task_get_cancellable (task); + g_autoptr(GBytes) response = NULL; g_autoptr(GError) error = NULL; - GList *keys, *l; + g_autolist(SeahorsePgpKey) keys = NULL; - seahorse_progress_end (closure->cancellable, message); + seahorse_progress_end (cancellable, closure->message); - if (hkp_message_propagate_error (closure->source, message, &error)) { + response = soup_session_send_and_read_finish (session, result, &error); + if (response == NULL) { g_task_return_error (task, g_steal_pointer (&error)); return; } - keys = seahorse_hkp_parse_lookup_response (message->response_body->data); - for (l = keys; l; l = g_list_next (l)) { + closure->response = g_string_new_len (g_bytes_get_data (response, NULL), + g_bytes_get_size (response)); + keys = seahorse_hkp_parse_lookup_response (closure->response->str); + for (GList *l = keys; l; l = g_list_next (l)) { g_object_set (l->data, "place", closure->source, NULL); gcr_simple_collection_add (closure->results, l->data); } - g_list_free_full (keys, g_object_unref); - g_task_return_boolean (task, TRUE); } @@ -589,24 +553,19 @@ seahorse_hkp_source_search_async (SeahorseServerSource *source, void *user_data) { SeahorseHKPSource *self = SEAHORSE_HKP_SOURCE (source); - source_search_closure *closure; + SearchClosure *closure; g_autoptr(GTask) task = NULL; g_autoptr(GHashTable) form = NULL; - SoupMessage *message; - g_autoptr(SoupURI) uri = NULL; + g_autoptr(GUri) uri = NULL; g_autofree char *uri_str = NULL; task = g_task_new (source, cancellable, callback, user_data); - closure = g_new0 (source_search_closure, 1); + closure = g_new0 (SearchClosure, 1); closure->source = g_object_ref (self); - closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL; closure->session = create_hkp_soup_session (); closure->results = g_object_ref (results); g_task_set_task_data (task, closure, source_search_free); - uri = get_http_server_uri (self, "/pks/lookup"); - g_return_if_fail (uri); - form = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_insert (form, "op", "index"); g_hash_table_insert (form, "options", "mr"); @@ -622,22 +581,27 @@ seahorse_hkp_source_search_async (SeahorseServerSource *source, g_hash_table_insert (form, "fingerprint", "on"); - soup_uri_set_query_from_form (uri, form); - message = soup_message_new_from_uri ("GET", uri); + uri = get_http_server_uri (self, "/pks/lookup", form); + g_return_if_fail (uri); + + closure->message = soup_message_new_from_uri ("GET", uri); - seahorse_progress_prep_and_begin (cancellable, message, NULL); + seahorse_progress_prep_and_begin (cancellable, closure->message, NULL); - uri_str = soup_uri_to_string (uri, TRUE); + uri_str = g_uri_to_string_partial (uri, G_URI_HIDE_PASSWORD); g_debug ("Sending HKP search query to '%s'", uri_str); - soup_session_queue_message (closure->session, g_steal_pointer (&message), - on_search_message_complete, - g_steal_pointer (&task)); + soup_session_send_and_read_async (closure->session, + closure->message, + G_PRIORITY_DEFAULT, + cancellable, + on_search_message_complete, + g_steal_pointer (&task)); if (cancellable) - closure->cancelled_sig = g_cancellable_connect (cancellable, - G_CALLBACK (on_session_cancelled), - closure->session, NULL); + g_cancellable_connect (cancellable, + G_CALLBACK (on_session_cancelled), + closure->session, NULL); } static gboolean @@ -654,45 +618,51 @@ seahorse_hkp_source_search_finish (SeahorseServerSource *source, typedef struct { SeahorseHKPSource *source; GInputStream *input; - GCancellable *cancellable; - gulong cancelled_sig; SoupSession *session; + SoupMessage *message; int requests; -} source_import_closure; +} ImportClosure; static void -source_import_free (gpointer data) +source_import_free (void *data) { - source_import_closure *closure = data; + ImportClosure *closure = data; g_object_unref (closure->source); g_object_unref (closure->input); - g_cancellable_disconnect (closure->cancellable, closure->cancelled_sig); - g_clear_object (&closure->cancellable); + g_object_unref (closure->message); g_object_unref (closure->session); g_free (closure); } static void -on_import_message_complete (SoupSession *session, - SoupMessage *message, - gpointer user_data) +on_import_message_complete (GObject *object, + GAsyncResult *result, + void *user_data) { + SoupSession *session = SOUP_SESSION (object); g_autoptr(GTask) task = G_TASK (user_data); - source_import_closure *closure = g_task_get_task_data (task); + ImportClosure *closure = g_task_get_task_data (task); + GCancellable *cancellable = g_task_get_cancellable (task); + g_autoptr(GBytes) response = NULL; + g_autoptr(GString) response_str = NULL; g_autoptr(GError) error = NULL; - g_autofree gchar *errmsg = NULL; + g_autofree char *errmsg = NULL; g_assert (closure->requests > 0); - seahorse_progress_end (closure->cancellable, GUINT_TO_POINTER (closure->requests)); + seahorse_progress_end (cancellable, GUINT_TO_POINTER (closure->requests)); closure->requests--; - if (hkp_message_propagate_error (closure->source, message, &error)) { + response = soup_session_send_and_read_finish (session, result, &error); + if (!response) { g_task_return_error (task, g_steal_pointer (&error)); return; } - if ((errmsg = get_send_result (message->response_body->data)) != NULL) { - g_task_return_new_error (task, HKP_ERROR_DOMAIN, message->status_code, + response_str = g_string_new_len (g_bytes_get_data (response, NULL), + g_bytes_get_size (response)); + if ((errmsg = get_send_result (response_str->str)) != NULL) { + g_task_return_new_error (task, HKP_ERROR_DOMAIN, + soup_message_get_status (closure->message), "%s", errmsg); return; } @@ -709,24 +679,22 @@ seahorse_hkp_source_import_async (SeahorseServerSource *source, GInputStream *input, GCancellable *cancellable, GAsyncReadyCallback callback, - gpointer user_data) + void *user_data) { SeahorseHKPSource *self = SEAHORSE_HKP_SOURCE (source); g_autoptr(GTask) task = NULL; - source_import_closure *closure; - g_autoptr(GList) keydata = NULL; - g_autoptr(GHashTable) form = NULL; - g_autoptr(SoupURI) uri = NULL; - GList *l; + ImportClosure *closure; + g_autoptr(GPtrArray) keydata = NULL; + g_autoptr(GUri) uri = NULL; task = g_task_new (source, cancellable, callback, user_data); - closure = g_new0 (source_import_closure, 1); - closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + closure = g_new0 (ImportClosure, 1); closure->input = g_object_ref (input); closure->source = g_object_ref (self); closure->session = create_hkp_soup_session (); g_task_set_task_data (task, closure, source_import_free); + keydata = g_ptr_array_new_with_free_func (g_free); for (;;) { g_autoptr(GString) buf = g_string_sized_new (2048); guint len; @@ -737,53 +705,46 @@ seahorse_hkp_source_import_async (SeahorseServerSource *source, if (len <= 0) break; - keydata = g_list_prepend (keydata, - g_string_free (g_steal_pointer (&buf), FALSE)); + g_ptr_array_add (keydata, g_string_free (g_steal_pointer (&buf), FALSE)); } - if (g_list_length (keydata) == 0) { + if (keydata->len == 0) { g_task_return_pointer (task, NULL, NULL); return; } /* Figure out the URI we're sending to */ - uri = get_http_server_uri (self, "/pks/add"); + uri = get_http_server_uri (self, "/pks/add", NULL); g_return_if_fail (uri); - /* New operation and away we go */ - keydata = g_list_reverse (keydata); - - form = g_hash_table_new (g_str_hash, g_str_equal); - for (l = keydata; l; l = g_list_next (l)) { - g_autoptr(SoupMessage) message = NULL; - gchar *key; - - g_assert (l->data != NULL); - g_hash_table_remove_all (form); + for (unsigned int i = 0; i < keydata->len; i++) { + const char *keytext = g_ptr_array_index (keydata, i); + g_autofree char *key = NULL; + g_autoptr(GBytes) bytes = NULL; - g_hash_table_insert (form, "keytext", l->data); - key = soup_form_encode_urlencoded (form); + closure->message = soup_message_new_from_uri ("POST", uri); - message = soup_message_new_from_uri ("POST", uri); - soup_message_set_request (message, "application/x-www-form-urlencoded", - SOUP_MEMORY_TAKE, key, strlen (key)); + key = soup_form_encode ("keytext", keytext, NULL); + bytes = g_bytes_new_static (key, strlen (key)); + soup_message_set_request_body_from_bytes (closure->message, + "application/x-www-form-urlencoded", + bytes); - soup_session_queue_message (closure->session, - g_steal_pointer (&message), - on_import_message_complete, - g_object_ref (task)); + soup_session_send_and_read_async (closure->session, + closure->message, + G_PRIORITY_DEFAULT, + cancellable, + on_import_message_complete, + g_steal_pointer (&task)); closure->requests++; seahorse_progress_prep_and_begin (cancellable, GUINT_TO_POINTER (closure->requests), NULL); } if (cancellable) - closure->cancelled_sig = g_cancellable_connect (cancellable, - G_CALLBACK (on_session_cancelled), - closure->session, NULL); - - for (l = keydata; l != NULL; l = g_list_next (l)) - g_free (l->data); + g_cancellable_connect (cancellable, + G_CALLBACK (on_session_cancelled), + closure->session, NULL); } static GList * @@ -801,46 +762,46 @@ typedef struct { SeahorseHKPSource *source; GString *data; gsize data_len; - GCancellable *cancellable; - gulong cancelled_sig; SoupSession *session; + SoupMessage *message; int requests; } ExportClosure; static void -export_closure_free (gpointer data) +export_closure_free (void *data) { ExportClosure *closure = data; - g_object_unref (closure->source); + g_clear_object (&closure->source); if (closure->data) g_string_free (closure->data, TRUE); - g_cancellable_disconnect (closure->cancellable, closure->cancelled_sig); - g_clear_object (&closure->cancellable); - g_object_unref (closure->session); + g_clear_object (&closure->message); + g_clear_object (&closure->session); g_free (closure); } static void -on_export_message_complete (SoupSession *session, - SoupMessage *message, - gpointer user_data) +on_export_message_complete (GObject *object, + GAsyncResult *result, + void *user_data) { + SoupSession *session = SOUP_SESSION (object); g_autoptr(GTask) task = G_TASK (user_data); ExportClosure *closure = g_task_get_task_data (task); + GCancellable *cancellable = g_task_get_cancellable (task); + g_autoptr(GBytes) response = NULL; g_autoptr(GError) error = NULL; - const gchar *start, *end, *text; - guint len; + const char *start, *end, *text; + size_t len; - seahorse_progress_end (closure->cancellable, message); + seahorse_progress_end (cancellable, closure->message); - if (hkp_message_propagate_error (closure->source, message, &error)) { + response = soup_session_send_and_read_finish (session, result, &error); + if (response == NULL) { g_task_return_error (task, g_steal_pointer (&error)); return; } - end = text = message->response_body->data; - len = message->response_body->length; - + end = text = g_bytes_get_data (response, &len); for (;;) { len -= end - text; text = end; @@ -865,23 +826,20 @@ on_export_message_complete (SoupSession *session, static void seahorse_hkp_source_export_async (SeahorseServerSource *source, - const gchar **keyids, + const char **keyids, GCancellable *cancellable, GAsyncReadyCallback callback, - gpointer user_data) + void *user_data) { SeahorseHKPSource *self = SEAHORSE_HKP_SOURCE (source); ExportClosure *closure; g_autoptr(GTask) task = NULL; - SoupURI *uri; - g_autoptr(GHashTable) form = NULL; task = g_task_new (self, cancellable, callback, user_data); closure = g_new0 (ExportClosure, 1); closure->source = g_object_ref (self); closure->data = g_string_sized_new (1024); closure->session = create_hkp_soup_session (); - closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL; g_task_set_task_data (task, closure, export_closure_free); if (!keyids || !keyids[0]) { @@ -889,17 +847,15 @@ seahorse_hkp_source_export_async (SeahorseServerSource *source, return; } - uri = get_http_server_uri (self, "/pks/lookup"); - g_return_if_fail (uri); - form = g_hash_table_new (g_str_hash, g_str_equal); for (int i = 0; keyids[i] != NULL; i++) { const char *fpr = keyids[i]; size_t len; g_autofree char *hexfpr = NULL; - SoupMessage *message; + g_autoptr(GHashTable) form = NULL; + g_autoptr(GUri) uri = NULL; - g_hash_table_remove_all (form); + form = g_hash_table_new (g_str_hash, g_str_equal); /* Get the key id and limit it to 16 characters */ len = strlen (fpr); @@ -912,25 +868,30 @@ seahorse_hkp_source_export_async (SeahorseServerSource *source, /* The get key URI */ g_hash_table_insert (form, "op", "get"); g_hash_table_insert (form, "search", (char *)hexfpr); - soup_uri_set_query_from_form (uri, form); - message = soup_message_new_from_uri ("GET", uri); + uri = get_http_server_uri (self, "/pks/lookup", form); + g_return_if_fail (uri); - soup_session_queue_message (closure->session, message, - on_export_message_complete, - g_object_ref (task)); + closure->message = soup_message_new_from_uri ("GET", uri); + + soup_session_send_and_read_async (closure->session, + closure->message, + G_PRIORITY_DEFAULT, + cancellable, + on_export_message_complete, + g_steal_pointer (&task)); closure->requests++; - seahorse_progress_prep_and_begin (cancellable, message, NULL); + seahorse_progress_prep_and_begin (cancellable, closure->message, NULL); } if (cancellable) - closure->cancelled_sig = g_cancellable_connect (cancellable, - G_CALLBACK (on_session_cancelled), - closure->session, NULL); + g_cancellable_connect (cancellable, + G_CALLBACK (on_session_cancelled), + closure->session, NULL); } -static gpointer +static void * seahorse_hkp_source_export_finish (SeahorseServerSource *source, GAsyncResult *result, gsize *size, @@ -987,35 +948,32 @@ seahorse_hkp_source_new (const char *uri) * Returns: Whether the passed uri is valid for an HKP key source */ gboolean -seahorse_hkp_is_valid_uri (const gchar *uri) +seahorse_hkp_is_valid_uri (const char *uri) { - SoupURI *soup; - gboolean ret = FALSE; + g_autoptr(GUri) parsed = NULL; + const char *scheme; g_return_val_if_fail (uri && uri[0], FALSE); - /* Replace 'hkp' with 'http' at the beginning of the URI */ - if (strncasecmp (uri, "hkp:", 4) == 0) { - g_autofree char *t = g_strdup_printf ("http:%s", uri + 4); - soup = soup_uri_new (t); - /* Not 'hkp', but maybe 'http' */ - } else if (strncasecmp (uri, "hkps:", 5) == 0) { - g_autofree char *t = g_strdup_printf ("https:%s", uri + 5); - soup = soup_uri_new (t); - } else { - soup = soup_uri_new (uri); - } + parsed = g_uri_parse (uri, G_URI_FLAGS_NONE, NULL); + if (!parsed) + return FALSE; - if (soup) { - /* Must be http or https, have a host. No querystring, user, path, passwd etc... */ - if ((soup->scheme == SOUP_URI_SCHEME_HTTP || soup->scheme == SOUP_URI_SCHEME_HTTPS) && - !soup->user && !soup->password && !soup->query && !soup->fragment && - soup->host && soup->host[0] && g_str_equal (soup->path ? soup->path : "/", "/")) - ret = TRUE; - soup_uri_free (soup); - } + scheme = g_uri_get_scheme (parsed); + if (g_strcmp0 (scheme, "hkp") && g_strcmp0 (scheme, "hkps") && + g_strcmp0 (scheme, "http") && g_strcmp0 (scheme, "https")) + return FALSE; + + if (g_uri_get_host (parsed) == NULL) + return FALSE; + if (g_uri_get_userinfo (parsed) != NULL && g_uri_get_userinfo (parsed)[0] != '\0') + return FALSE; + if (g_uri_get_path (parsed) != NULL && g_uri_get_path (parsed)[0] != '\0') + return FALSE; + if (g_uri_get_query (parsed) != NULL) + return FALSE; - return ret; + return TRUE; } #endif /* WITH_HKP */ -- GitLab