[seahorse/wip/nielsdg/cleanup-sign-dialog] pgp: Use gpgme_op_create_subkey()



commit 80d7188bbc69716212b6b232f15e1b86208bdd9e
Author: Niels De Graef <nielsdegraef gmail com>
Date:   Wed Feb 12 18:19:16 2020 +0100

    pgp: Use gpgme_op_create_subkey()
    
    Rather than calling `gpgme_op_edit()`, let's directly use the API
    provided by GPGME. We can then also easily provide an async variant so
    we don't block the UI when the subkey is being made.

 pgp/seahorse-gpgme-add-subkey.c   |  73 ++++++-------
 pgp/seahorse-gpgme-add-subkey.h   |  11 +-
 pgp/seahorse-gpgme-add-subkey.ui  |   1 -
 pgp/seahorse-gpgme-key-op.c       | 222 ++++++++++++--------------------------
 pgp/seahorse-gpgme-key-op.h       |  54 +++-------
 pgp/seahorse-gpgme.c              |  26 +++++
 pgp/seahorse-gpgme.h              |  36 ++++++-
 pgp/seahorse-pgp-key-properties.c |  33 +++++-
 8 files changed, 219 insertions(+), 237 deletions(-)
---
diff --git a/pgp/seahorse-gpgme-add-subkey.c b/pgp/seahorse-gpgme-add-subkey.c
index 246ee63e..824fb972 100644
--- a/pgp/seahorse-gpgme-add-subkey.c
+++ b/pgp/seahorse-gpgme-add-subkey.c
@@ -108,54 +108,52 @@ on_gpgme_add_subkey_never_expires_toggled (GtkToggleButton *togglebutton,
                               !gtk_toggle_button_get_active (togglebutton));
 }
 
-static void
-on_gpgme_add_subkey_ok_clicked (GtkButton *button,
-                                gpointer user_data)
+SeahorseKeyEncType
+seahorse_gpgme_add_subkey_get_active_type (SeahorseGpgmeAddSubkey *self)
 {
-    SeahorseGpgmeAddSubkey *self = SEAHORSE_GPGME_ADD_SUBKEY (user_data);
-    SeahorseKeyEncType real_type;
-    int type;
-    guint length;
-    time_t expires;
-    gpgme_error_t err;
     GtkTreeIter iter;
+    int type;
+
+    g_return_val_if_fail (SEAHORSE_GPGME_IS_ADD_SUBKEY (self), 0);
 
     gtk_combo_box_get_active_iter (GTK_COMBO_BOX (self->type_combo), &iter);
     gtk_tree_model_get (self->types_model, &iter,
                         COMBO_INT, &type,
                         -1);
 
-    length = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (self->length_spinner));
-
-    if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->never_expires_check)))
-        expires = 0;
-    else {
-        egg_datetime_get_as_time_t (EGG_DATETIME (self->expires_datetime),
-                                    &expires);
-   }
-
     switch (type) {
         case 0:
-            real_type = DSA;
-            break;
+            return DSA;
         case 1:
-            real_type = ELGAMAL;
-            break;
+            return ELGAMAL;
         case 2:
-            real_type = RSA_SIGN;
-            break;
+            return RSA_SIGN;
         default:
-            real_type = RSA_ENCRYPT;
-            break;
+            return RSA_ENCRYPT;
     }
+}
+
+gulong
+seahorse_gpgme_add_subkey_get_expires (SeahorseGpgmeAddSubkey *self)
+{
+    time_t expires;
+
+    g_return_val_if_fail (SEAHORSE_GPGME_IS_ADD_SUBKEY (self), 0);
 
-    gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
-    err = seahorse_gpgme_key_op_add_subkey (SEAHORSE_GPGME_KEY (self->key),
-                                            real_type, length, expires);
-    gtk_widget_set_sensitive (GTK_WIDGET (self), TRUE);
+    if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->never_expires_check)))
+        return 0;
+
+    egg_datetime_get_as_time_t (EGG_DATETIME (self->expires_datetime),
+                                &expires);
+    return expires;
+}
+
+guint
+seahorse_gpgme_add_subkey_get_keysize (SeahorseGpgmeAddSubkey *self)
+{
+    g_return_val_if_fail (SEAHORSE_GPGME_IS_ADD_SUBKEY (self), 0);
 
-    if (!GPG_IS_OK (err))
-        seahorse_gpgme_handle_error (err, _("Couldn’t add subkey"));
+    return gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (self->length_spinner));
 }
 
 static void
@@ -294,7 +292,6 @@ seahorse_gpgme_add_subkey_class_init (SeahorseGpgmeAddSubkeyClass *klass)
     gtk_widget_class_bind_template_child (widget_class, SeahorseGpgmeAddSubkey, never_expires_check);
     gtk_widget_class_bind_template_callback (widget_class, handler_gpgme_add_subkey_type_changed);
     gtk_widget_class_bind_template_callback (widget_class, on_gpgme_add_subkey_never_expires_toggled);
-    gtk_widget_class_bind_template_callback (widget_class, on_gpgme_add_subkey_ok_clicked);
 }
 
 /**
@@ -303,18 +300,18 @@ seahorse_gpgme_add_subkey_class_init (SeahorseGpgmeAddSubkeyClass *klass)
  *
  * Creates a new #SeahorseGpgmeAddSubkey dialog for adding a user ID to @skey.
  */
-GtkDialog *
+SeahorseGpgmeAddSubkey *
 seahorse_gpgme_add_subkey_new (SeahorseGpgmeKey *key, GtkWindow *parent)
 {
-       g_autoptr(SeahorseGpgmeAddSubkey) self = NULL;
+    g_autoptr(SeahorseGpgmeAddSubkey) self = NULL;
 
-       g_return_val_if_fail (SEAHORSE_GPGME_IS_KEY (key), NULL);
+    g_return_val_if_fail (SEAHORSE_GPGME_IS_KEY (key), NULL);
 
-       self = g_object_new (SEAHORSE_GPGME_TYPE_ADD_SUBKEY,
+    self = g_object_new (SEAHORSE_GPGME_TYPE_ADD_SUBKEY,
                          "key", key,
                          "transient-for", parent,
                          "use-header-bar", 1,
                          NULL);
 
-    return GTK_DIALOG (g_steal_pointer (&self));
+    return g_steal_pointer (&self);
 }
diff --git a/pgp/seahorse-gpgme-add-subkey.h b/pgp/seahorse-gpgme-add-subkey.h
index 9974834c..d1ab6437 100644
--- a/pgp/seahorse-gpgme-add-subkey.h
+++ b/pgp/seahorse-gpgme-add-subkey.h
@@ -21,6 +21,7 @@
 
 #include <gtk/gtk.h>
 
+#include "pgp/seahorse-gpgme.h"
 #include "pgp/seahorse-gpgme-key.h"
 #include "pgp/seahorse-gpgme-subkey.h"
 
@@ -29,5 +30,11 @@ G_DECLARE_FINAL_TYPE (SeahorseGpgmeAddSubkey, seahorse_gpgme_add_subkey,
                       SEAHORSE_GPGME, ADD_SUBKEY,
                       GtkDialog)
 
-GtkDialog*  seahorse_gpgme_add_subkey_new   (SeahorseGpgmeKey *pkey,
-                                             GtkWindow *parent);
+SeahorseGpgmeAddSubkey*  seahorse_gpgme_add_subkey_new               (SeahorseGpgmeKey *pkey,
+                                                                      GtkWindow *parent);
+
+SeahorseKeyEncType       seahorse_gpgme_add_subkey_get_active_type   (SeahorseGpgmeAddSubkey *self);
+
+guint                    seahorse_gpgme_add_subkey_get_keysize       (SeahorseGpgmeAddSubkey *self);
+
+gulong                   seahorse_gpgme_add_subkey_get_expires       (SeahorseGpgmeAddSubkey *self);
diff --git a/pgp/seahorse-gpgme-add-subkey.ui b/pgp/seahorse-gpgme-add-subkey.ui
index e6ee37d6..7b687e82 100644
--- a/pgp/seahorse-gpgme-add-subkey.ui
+++ b/pgp/seahorse-gpgme-add-subkey.ui
@@ -149,7 +149,6 @@
                 <property name="receives_default">False</property>
                 <property name="tooltip_text" translatable="yes">Generate a new subkey</property>
                 <property name="use_stock">True</property>
-                <signal name="clicked" handler="on_gpgme_add_subkey_ok_clicked"/>
               </object>
             </child>
           </object>
diff --git a/pgp/seahorse-gpgme-key-op.c b/pgp/seahorse-gpgme-key-op.c
index 6c7b96bd..1960ec39 100644
--- a/pgp/seahorse-gpgme-key-op.c
+++ b/pgp/seahorse-gpgme-key-op.c
@@ -1311,164 +1311,84 @@ seahorse_gpgme_key_op_add_uid_finish (SeahorseGpgmeKey *pkey,
     return g_task_propagate_boolean (G_TASK (result), error);
 }
 
-typedef enum {
-       ADD_KEY_START,
-       ADD_KEY_COMMAND,
-       ADD_KEY_TYPE,
-       ADD_KEY_LENGTH,
-       ADD_KEY_EXPIRES,
-       ADD_KEY_QUIT,
-       ADD_KEY_SAVE,
-       ADD_KEY_ERROR
-} AddKeyState;
+void
+seahorse_gpgme_key_op_add_subkey_async (SeahorseGpgmeKey *pkey,
+                                        SeahorseKeyEncType type,
+                                        guint length,
+                                        gulong expires,
+                                        GCancellable *cancellable,
+                                        GAsyncReadyCallback callback,
+                                        gpointer user_data)
+{
+    g_autoptr(GTask) task = NULL;
+    gpgme_ctx_t gctx;
+    gpgme_error_t gerr;
+    g_autoptr(GError) error = NULL;
+    gpgme_key_t key;
+    const char *algo;
+    g_autofree char *algo_full = NULL;
+    g_autoptr(GSource) gsource = NULL;
+    guint flags = 0;
 
-typedef struct {
-       guint               type;
-       guint               length;
-       time_t              expires;
-} SubkeyParm;
+    g_return_if_fail (SEAHORSE_GPGME_IS_KEY (pkey));
+    g_return_if_fail (seahorse_object_get_usage (SEAHORSE_OBJECT (pkey)) ==
+                          SEAHORSE_USAGE_PRIVATE_KEY);
 
-/* action helper for adding a subkey */
-static gpgme_error_t
-add_key_action (guint state, gpointer data, int fd)
-{
-       SubkeyParm *parm = (SubkeyParm*)data;
-       
-       switch (state) {
-               case ADD_KEY_COMMAND:
-            PRINT ((fd, "addkey"));
-                       break;
-               case ADD_KEY_TYPE:
-            PRINTF ((fd, "%d", parm->type));
-                       break;
-               case ADD_KEY_LENGTH:
-            PRINTF ((fd, "%d", parm->length));
-                       break;
-               /* Get exact date or 0 */
-               case ADD_KEY_EXPIRES:
-            PRINT ((fd, (parm->expires) ?
-                               seahorse_util_get_date_string (parm->expires) : "0"));
-                       break;
-               case ADD_KEY_QUIT:
-            PRINT ((fd, QUIT));
-                       break;
-               case ADD_KEY_SAVE:
-            PRINT ((fd, YES));
-                       break;
-               default:
-                       return GPG_E (GPG_ERR_GENERAL);
-       }
-       
-    PRINT ((fd, "\n"));
-       return GPG_OK;
-}
+    gctx = seahorse_gpgme_keyring_new_context (&gerr);
 
-/* transition helper for adding a subkey */
-static guint
-add_key_transit (guint current_state, gpgme_status_code_t status,
-                const gchar *args, gpointer data, gpgme_error_t *err)
-{
-       guint next_state;
+    task = g_task_new (pkey, cancellable, callback, user_data);
+    gpgme_set_progress_cb (gctx, on_key_op_progress, task);
+    g_task_set_task_data (task, gctx, (GDestroyNotify) gpgme_release);
 
-       switch (current_state) {
-               /* start, do command */
-               case ADD_KEY_START:
-                       if (status == GPGME_STATUS_GET_LINE && g_str_equal (args, PROMPT))
-                               next_state = ADD_KEY_COMMAND;
-                       else {
-                *err = GPG_E (GPG_ERR_GENERAL);
-                g_return_val_if_reached (ADD_KEY_ERROR);
-                       }
-                       break;
-               /* did command, do type */
-               case ADD_KEY_COMMAND:
-               case ADD_KEY_TYPE:
-               case ADD_KEY_LENGTH:
-               case ADD_KEY_EXPIRES:
-                       if (status == GPGME_STATUS_GET_LINE && g_str_equal (args, "keygen.algo"))
-                               next_state = ADD_KEY_TYPE;
-                       else if (status == GPGME_STATUS_GET_LINE && g_str_equal (args, "keygen.size"))
-                               next_state = ADD_KEY_LENGTH;
-                       else if (status == GPGME_STATUS_GET_LINE && g_str_equal (args, "keygen.valid"))
-                               next_state = ADD_KEY_EXPIRES;
-                       else if (status == GPGME_STATUS_GET_LINE && g_str_equal (args, PROMPT))
-                               next_state = ADD_KEY_QUIT;
-                       else {
-                *err = GPG_E (GPG_ERR_GENERAL);
-                return ADD_KEY_ERROR; /* Legitimate errors error here */
-                       }
-                       break;
-               /* quit, save */
-               case ADD_KEY_QUIT:
-                       if (status == GPGME_STATUS_GET_BOOL && g_str_equal (args, SAVE))
-                               next_state = ADD_KEY_SAVE;
-                       else {
-                *err = GPG_E (GPG_ERR_GENERAL);
-                g_return_val_if_reached (ADD_KEY_ERROR);
-                       }
-                       break;
-               /* error, quit */
-               case ADD_KEY_ERROR:
-                       if (status == GPGME_STATUS_GET_LINE && g_str_equal (args, PROMPT))
-                               next_state = ADD_KEY_QUIT;
-                       else
-                               next_state = ADD_KEY_ERROR;
-                       break;
-               default:
-            *err = GPG_E (GPG_ERR_GENERAL);
-            g_return_val_if_reached (ADD_KEY_ERROR);
-                       break;
-       }
-       
-       return next_state;
+    seahorse_progress_prep_and_begin (cancellable, task, NULL);
+    gsource = seahorse_gpgme_gsource_new (gctx, cancellable);
+    g_source_set_callback (gsource, (GSourceFunc)on_key_op_add_uid_complete,
+                           g_object_ref (task), g_object_unref);
+
+    /* Get the actual secret key */
+    key = seahorse_gpgme_key_get_private (pkey);
+
+    /* Get the algo string as GPG(ME) expects it */
+    algo = seahorse_gpgme_get_algo_string (type);
+    g_return_if_fail (algo);
+    algo_full = g_strdup_printf ("%s%u", algo, length);
+
+    /* 0 means "no expire" for us (GPGME picks a default otherwise) */
+    if (expires == 0)
+        flags |= GPGME_CREATE_NOEXPIRE;
+
+    /* Add usage flags */
+    switch (type) {
+        case RSA_SIGN:
+            flags |= GPGME_CREATE_SIGN;
+            break;
+        case RSA_ENCRYPT:
+            flags |= GPGME_CREATE_ENCR;
+            break;
+        default:
+            break;
+    }
+
+    if (gerr == 0)
+        gerr = gpgme_op_createsubkey_start (gctx, key, algo_full, 0, expires, flags);
+
+    if (seahorse_gpgme_propagate_error (gerr, &error)) {
+        g_task_return_error (task, g_steal_pointer (&error));
+        return;
+    }
+
+    g_source_attach (gsource, g_main_context_default ());
 }
 
-gpgme_error_t
-seahorse_gpgme_key_op_add_subkey (SeahorseGpgmeKey *pkey, const SeahorseKeyEncType type, 
-                                  const guint length, const time_t expires)
+gboolean
+seahorse_gpgme_key_op_add_subkey_finish (SeahorseGpgmeKey *pkey,
+                                         GAsyncResult *result,
+                                         GError **error)
 {
-       SeahorseEditParm *parms;
-       SubkeyParm *key_parm;
-       guint real_type;
-       SeahorseKeyTypeTable table;
-       gpgme_error_t gerr;
-       
-    g_return_val_if_fail (SEAHORSE_GPGME_IS_KEY (pkey), GPG_E (GPG_ERR_WRONG_KEY_USAGE));    
-    g_return_val_if_fail (seahorse_object_get_usage (SEAHORSE_OBJECT (pkey)) == SEAHORSE_USAGE_PRIVATE_KEY, 
GPG_E (GPG_ERR_WRONG_KEY_USAGE));
-       
-       gerr = seahorse_gpgme_get_keytype_table (&table);
-       g_return_val_if_fail (GPG_IS_OK (gerr), gerr);
-       
-       /* Check length range & type */
-       switch (type) {
-               case DSA:
-                       real_type = table->dsa_sign;
-                       g_return_val_if_fail (length >= DSA_MIN && length <= DSA_MAX, GPG_E 
(GPG_ERR_INV_VALUE));
-                       break;
-               case ELGAMAL:
-                       real_type = table->elgamal_enc;
-                       g_return_val_if_fail (length >= ELGAMAL_MIN && length <= LENGTH_MAX, GPG_E 
(GPG_ERR_INV_VALUE));
-                       break;
-               case RSA_SIGN: case RSA_ENCRYPT:
-                       if (type == RSA_SIGN)
-                               real_type = table->rsa_sign;
-                       else
-                               real_type = table->rsa_enc;
-                       g_return_val_if_fail (length >= RSA_MIN && length <= LENGTH_MAX, GPG_E 
(GPG_ERR_INV_VALUE));
-                       break;
-               default:
-                       g_return_val_if_reached (GPG_E (GPG_ERR_INV_VALUE));
-                       break;
-       }
-       
-       key_parm = g_new (SubkeyParm, 1);
-       key_parm->type = real_type;
-       key_parm->length = length;
-       key_parm->expires = expires;
-       
-       parms = seahorse_edit_parm_new (ADD_KEY_START, add_key_action, add_key_transit, key_parm);
-       
-       return edit_key (pkey, parms);
+    g_return_val_if_fail (g_task_is_valid (result, pkey), FALSE);
+
+    seahorse_gpgme_key_refresh (pkey);
+    return g_task_propagate_boolean (G_TASK (result), error);
 }
 
 typedef enum {
diff --git a/pgp/seahorse-gpgme-key-op.h b/pgp/seahorse-gpgme-key-op.h
index bcfdfbfb..3cecd996 100644
--- a/pgp/seahorse-gpgme-key-op.h
+++ b/pgp/seahorse-gpgme-key-op.h
@@ -29,43 +29,6 @@
 #include "pgp/seahorse-gpgme-uid.h"
 #include "pgp/seahorse-gpgme-photo.h"
 
-/*
- * Key type options.
- * We only support GPG version >=2.0.12 or >= 2.1.4
- */
-
-typedef enum {
-       RSA_RSA = 1,
-       DSA_ELGAMAL = 2,
-       DSA = 3,
-       RSA_SIGN = 4,
-       ELGAMAL = 5,
-       RSA_ENCRYPT = 6
-} SeahorseKeyEncType;
-
-/* Length ranges for key types */
-typedef enum {
-       /* Minimum length for #DSA. */
-       DSA_MIN = 768,
-       /* Maximum length for #DSA. */
-#if ( GPG_MAJOR == 2 &&   GPG_MINOR == 0 && GPG_MICRO < 12 ) || \
-    ( GPG_MAJOR == 1 && ( GPG_MINOR <  4 || GPG_MICRO < 10 ) )
-       DSA_MAX = 1024,
-#else
-       DSA_MAX = 3072,
-#endif
-       /* Minimum length for #ELGAMAL. Maximum length is #LENGTH_MAX. */
-       ELGAMAL_MIN = 768,
-       /* Minimum length of #RSA_SIGN and #RSA_ENCRYPT. Maximum length is
-        * #LENGTH_MAX.
-        */
-       RSA_MIN = 1024,
-       /* Maximum length for #ELGAMAL, #RSA_SIGN, and #RSA_ENCRYPT. */
-       LENGTH_MAX = 4096,
-       /* Default length for #ELGAMAL, #RSA_SIGN, #RSA_ENCRYPT, and #DSA. */
-       LENGTH_DEFAULT = 2048
-} SeahorseKeyLength;
-
 typedef enum {
        /* Unknown key check */
        SIGN_CHECK_NO_ANSWER,
@@ -170,11 +133,18 @@ gboolean          seahorse_gpgme_key_op_make_primary_finish (SeahorseGpgmeUid *u
                                                              GError **error);
 
 gpgme_error_t         seahorse_gpgme_key_op_del_uid          (SeahorseGpgmeUid *uid);
-                             
-gpgme_error_t         seahorse_gpgme_key_op_add_subkey       (SeahorseGpgmeKey *pkey,
-                                                              SeahorseKeyEncType type,
-                                                              guint length,
-                                                              time_t expires);
+
+void              seahorse_gpgme_key_op_add_subkey_async    (SeahorseGpgmeKey *pkey,
+                                                             SeahorseKeyEncType type,
+                                                             guint length,
+                                                             gulong expires,
+                                                             GCancellable *cancellable,
+                                                             GAsyncReadyCallback callback,
+                                                             gpointer user_data);
+
+gboolean          seahorse_gpgme_key_op_add_subkey_finish   (SeahorseGpgmeKey *pkey,
+                                                             GAsyncResult *result,
+                                                             GError **error);
 
 gpgme_error_t         seahorse_gpgme_key_op_del_subkey       (SeahorseGpgmeSubkey *subkey);
 
diff --git a/pgp/seahorse-gpgme.c b/pgp/seahorse-gpgme.c
index 5467f130..deed86e5 100644
--- a/pgp/seahorse-gpgme.c
+++ b/pgp/seahorse-gpgme.c
@@ -245,6 +245,32 @@ seahorse_gpgme_get_keytype_table (SeahorseKeyTypeTable *table)
        return gerr;
 }
 
+/**
+ * seahorse_gpgme_get_algo_string:
+ * @type: The algo type
+ *
+ * Returns: (transfer none): A string version of the algorithm, which can be
+ * used for GPGME functions like gpgme_op_create(sub)key.
+ */
+const char *
+seahorse_gpgme_get_algo_string (SeahorseKeyEncType type)
+{
+    switch (type) {
+        case DSA:
+            return "dsa";
+        case RSA_RSA:
+        case RSA_SIGN:
+        case RSA_ENCRYPT:
+            return "rsa";
+        case ELGAMAL:
+            return "elg";
+        default:
+            return NULL;
+    }
+
+    g_return_val_if_reached (NULL);
+}
+
 typedef struct _WatchData {
        GSource *gsource;
        gboolean registered;
diff --git a/pgp/seahorse-gpgme.h b/pgp/seahorse-gpgme.h
index a47e8dca..9c85212f 100644
--- a/pgp/seahorse-gpgme.h
+++ b/pgp/seahorse-gpgme.h
@@ -31,7 +31,7 @@
 typedef struct _SeahorseKeyTypeTable *SeahorseKeyTypeTable;
 
 struct _SeahorseKeyTypeTable {
-       int rsa_sign, rsa_enc, dsa_sign, elgamal_enc;
+    int rsa_sign, rsa_enc, dsa_sign, elgamal_enc;
 };
 
 /* TODO: I think these are extraneous and can be removed. In actuality OK == 0 */
@@ -59,3 +59,37 @@ gpgme_error_t      seahorse_gpgme_get_keytype_table (SeahorseKeyTypeTable *table
 
 GSource *          seahorse_gpgme_gsource_new       (gpgme_ctx_t gctx,
                                                      GCancellable *cancellable);
+
+typedef enum {
+    RSA_RSA = 1,
+    DSA_ELGAMAL = 2,
+    DSA = 3,
+    RSA_SIGN = 4,
+    ELGAMAL = 5,
+    RSA_ENCRYPT = 6
+} SeahorseKeyEncType;
+
+/* Length ranges for key types */
+typedef enum {
+    /* Minimum length for #DSA. */
+    DSA_MIN = 768,
+    /* Maximum length for #DSA. */
+#if ( GPG_MAJOR == 2 &&   GPG_MINOR == 0 && GPG_MICRO < 12 ) || \
+    ( GPG_MAJOR == 1 && ( GPG_MINOR <  4 || GPG_MICRO < 10 ) )
+    DSA_MAX = 1024,
+#else
+    DSA_MAX = 3072,
+#endif
+    /* Minimum length for #ELGAMAL. Maximum length is #LENGTH_MAX. */
+    ELGAMAL_MIN = 768,
+    /* Minimum length of #RSA_SIGN and #RSA_ENCRYPT. Maximum length is
+     * #LENGTH_MAX.
+     */
+    RSA_MIN = 1024,
+    /* Maximum length for #ELGAMAL, #RSA_SIGN, and #RSA_ENCRYPT. */
+    LENGTH_MAX = 4096,
+    /* Default length for #ELGAMAL, #RSA_SIGN, #RSA_ENCRYPT, and #DSA. */
+    LENGTH_DEFAULT = 2048
+} SeahorseKeyLength;
+
+const char *    seahorse_gpgme_get_algo_string (SeahorseKeyEncType type);
diff --git a/pgp/seahorse-pgp-key-properties.c b/pgp/seahorse-pgp-key-properties.c
index e03d532a..6696e754 100644
--- a/pgp/seahorse-pgp-key-properties.c
+++ b/pgp/seahorse-pgp-key-properties.c
@@ -939,17 +939,46 @@ details_subkey_selected (GtkTreeSelection *selection, SeahorsePgpKeyProperties *
     set_action_enabled (self, "subkeys.delete", subkey != NULL);
 }
 
+static void
+on_add_subkey_completed (GObject *object, GAsyncResult *res, gpointer user_data)
+{
+    SeahorsePgpKeyProperties *self = SEAHORSE_PGP_KEY_PROPERTIES (user_data);
+    g_autoptr(GError) error = NULL;
+
+    if (!seahorse_gpgme_key_op_add_subkey_finish (SEAHORSE_GPGME_KEY (self->key),
+                                                  res, &error)) {
+        seahorse_util_handle_error (&error, self, NULL);
+    }
+}
+
 static void
 on_subkeys_add (GSimpleAction *action, GVariant *param, gpointer user_data)
 {
     SeahorsePgpKeyProperties *self = SEAHORSE_PGP_KEY_PROPERTIES (user_data);
-    GtkDialog *dialog;
+    SeahorseGpgmeAddSubkey *dialog;
+    int response;
+    SeahorseKeyEncType type;
+    guint length;
+    gulong expires;
 
     g_return_if_fail (SEAHORSE_GPGME_IS_KEY (self->key));
 
     dialog = seahorse_gpgme_add_subkey_new (SEAHORSE_GPGME_KEY (self->key),
                                             GTK_WINDOW (self));
-    gtk_dialog_run (dialog);
+
+    response = gtk_dialog_run (GTK_DIALOG (dialog));
+    if (response != GTK_RESPONSE_OK) {
+        gtk_widget_destroy (GTK_WIDGET (dialog));
+        return;
+    }
+
+    length = seahorse_gpgme_add_subkey_get_keysize (dialog);
+    type = seahorse_gpgme_add_subkey_get_active_type (dialog);
+    expires = seahorse_gpgme_add_subkey_get_expires (dialog);
+    seahorse_gpgme_key_op_add_subkey_async (SEAHORSE_GPGME_KEY (self->key),
+                                            type, length, expires, NULL,
+                                            on_add_subkey_completed, self);
+
     gtk_widget_destroy (GTK_WIDGET (dialog));
 }
 


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