[seahorse/nielsdg/soup3] hkp: Port to libsoup3




commit ab2f253ca7ff65462c3f429cdeb9e58798f7091d
Author: Niels De Graef <nielsdegraef gmail com>
Date:   Sun Jun 26 20:22:06 2022 +0200

    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 */


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