[seahorse/nielsdg/ssh] ssh: Make Key.parse() a proper async method




commit f339233dc45e59d45e27486f6b9e57fae9fd8171
Author: Niels De Graef <nielsdegraef gmail com>
Date:   Tue May 24 09:08:21 2022 +0200

    ssh: Make Key.parse() a proper async method
    
    This allows us to make full use of the event loop to parse keys, and
    simplifies the code quite a bit.

 ssh/actions.vala             |  16 +-
 ssh/generate.vala            |  64 ++++----
 ssh/key.vala                 |  56 +++----
 ssh/seahorse-ssh-generate.ui | 351 +++++++++++++++++++------------------------
 ssh/source.vala              |  39 +++--
 5 files changed, 237 insertions(+), 289 deletions(-)
---
diff --git a/ssh/actions.vala b/ssh/actions.vala
index d2c37b1f..6aad1ee5 100644
--- a/ssh/actions.vala
+++ b/ssh/actions.vala
@@ -57,13 +57,19 @@ public class Seahorse.Ssh.Actions : ActionGroup {
     }
 
     private void on_ssh_generate_key(SimpleAction action, Variant? param) {
-        Generate generate_dialog = new Generate(Backend.instance.get_dot_ssh(),
-                                                this.catalog);
+        var dialog = new Generate(Backend.instance.get_dot_ssh(),
+                                  this.catalog);
 
-        int response = generate_dialog.run();
-        if (response == Gtk.ResponseType.ACCEPT)
+        if (dialog.run() != Gtk.ResponseType.ACCEPT) {
+            dialog.destroy();
+            return;
+        }
+
+        dialog.generate_key.begin ((obj, res) => {
+            dialog.generate_key.end (res);
+            dialog.destroy();
             this.catalog.activate_action("focus-place", "openssh");
-        generate_dialog.destroy();
+        });
     }
 
     private void on_ssh_upload(SimpleAction action, Variant? param) {
diff --git a/ssh/generate.vala b/ssh/generate.vala
index eb577a55..e797d779 100644
--- a/ssh/generate.vala
+++ b/ssh/generate.vala
@@ -24,7 +24,7 @@ public class Seahorse.Ssh.Generate : Gtk.Dialog {
     public const int DEFAULT_DSA_SIZE = 1024;
     public const int DEFAULT_RSA_SIZE = 2048;
 
-    private Source source;
+    public Ssh.Source source { get; construct set; }
 
     [GtkChild]
     private unowned Gtk.Grid details_grid;
@@ -33,17 +33,15 @@ public class Seahorse.Ssh.Generate : Gtk.Dialog {
     private unowned Gtk.Entry email_entry;
     [GtkChild]
     private unowned Gtk.ComboBoxText algorithm_combo_box;
-    [GtkChild]
-    private unowned Gtk.Button create_with_setup_button;
-    [GtkChild]
-    private unowned Gtk.Button create_no_setup_button;
 
     public Generate(Source src, Gtk.Window parent) {
-        this.transient_for = parent;
-        this.source = src;
+        GLib.Object (
+            source: src,
+            use_header_bar: 1,
+            transient_for: parent
+        );
 
-        this.create_no_setup_button.clicked.connect((b) => create_key(false));
-        this.create_with_setup_button.clicked.connect((b) => create_key(true));
+        this.source = src;
 
         this.key_length_chooser = new KeyLengthChooser();
         this.key_length_chooser.halign = Gtk.Align.START;
@@ -59,7 +57,13 @@ public class Seahorse.Ssh.Generate : Gtk.Dialog {
         this.key_length_chooser.algorithm = Algorithm.from_string(t);
     }
 
-    private void create_key(bool upload) {
+    /**
+     * Generate a key from the fields that were filled in.
+     *
+     * Note: make sure you don't destroy the window before this async method
+     * has finished
+     */
+    public async void generate_key() {
         // The email address
         string email = this.email_entry.text;
 
@@ -74,34 +78,22 @@ public class Seahorse.Ssh.Generate : Gtk.Dialog {
         string filename = this.source.new_filename_for_algorithm(type);
 
         // We start creation
-        Cancellable cancellable = new Cancellable();
-        GenerateOperation op = new GenerateOperation();
-        op.generate_async.begin(filename, email, type, bits, cancellable, (obj, res) => {
+        try {
+            debug("Generating %s key '%s' (file '%s')", t, email, filename);
+            GenerateOperation op = new GenerateOperation();
+            Cancellable cancellable = new Cancellable();
+            Seahorse.Progress.show(cancellable, _("Creating Secure Shell Key"), false);
+            yield op.generate_async(filename, email, type, bits, cancellable);
+
+            // We generated a key, but we still need to import it
             try {
-                op.generate_async.end(res);
-
-                // The result of the operation is the key we generated
-                source.add_key_from_filename.begin(filename, (obj, res) => {
-                    try {
-                        Key key = source.add_key_from_filename.end(res);
-
-                        if (upload && key != null) {
-                            List<Key> keys = new List<Key>();
-                            keys.append(key);
-                            Upload.prompt(keys, null);
-                        }
-                    } catch (GLib.Error e) {
-                        Seahorse.Util.show_error(null, _("Couldn’t load newly generated Secure Shell key"), 
e.message);
-                    }
-                });
+                debug("Importing generated key (file '%s')", filename);
+                Key key = yield source.add_key_from_filename(filename);
             } catch (GLib.Error e) {
-                Seahorse.Util.show_error(null, _("Couldn’t generate Secure Shell key"), e.message);
+                Seahorse.Util.show_error(null, _("Couldn’t load newly generated Secure Shell key"), 
e.message);
             }
-        });
-        Seahorse.Progress.show(cancellable, _("Creating Secure Shell Key"), false);
-
-        response(Gtk.ResponseType.ACCEPT);
-        destroy();
+        } catch (GLib.Error e) {
+            Seahorse.Util.show_error(null, _("Couldn’t generate Secure Shell key"), e.message);
+        }
     }
-
 }
diff --git a/ssh/key.vala b/ssh/key.vala
index da3ba01b..e2ebc30b 100644
--- a/ssh/key.vala
+++ b/ssh/key.vala
@@ -217,31 +217,31 @@ public class Seahorse.Ssh.Key : Seahorse.Object, Seahorse.Exportable, Seahorse.D
         }
     }
 
+    public struct KeyParseResult {
+        public KeyData[] public_keys;
+        public SecData[] secret_keys;
+    }
+
     /**
      * Parses a string into public/private keys.
      *
      * @param data The string that needs to be parsed.
-     * @param pub_handler Will be called anytime a public key has been parsed.
-     *                    If null, nothing will be done if a public key is parsed.
-     * @param priv_handler Will be called anytime a private key has been parsed.
-     *                     If null, nothing will be done if a private key is parsed.
      * @param cancellable Can be used to cancel the parsing.
      */
-    public static async void parse(string data,
-                                   PubParsedHandler? pub_handler,
-                                   PrivParsedHandler? priv_handler = null,
-                                   Cancellable? cancellable = null) throws GLib.Error {
-        if (data == null || data == "")
-            return;
+    public static async KeyParseResult parse(string data,
+                                             Cancellable? cancellable = null) throws GLib.Error {
+        return_if_fail (data != null || data != "");
+
+        var pubkeys = new GenericArray<KeyData>();
+        var seckeys = new GenericArray<SecData>();
 
         StringBuilder toParse = new StringBuilder(data.chug());
         while (toParse.str.length > 0) {
             // First of all, check for a private key, as it can span several lines
             if (SecData.contains_private_key(toParse.str)) {
                 try {
-                    SecData secdata = SecData.parse_data(toParse);
-                    if (priv_handler != null)
-                        priv_handler(secdata);
+                    var secdata = SecData.parse_data(toParse);
+                    seckeys.add(secdata);
                     continue;
                 } catch (GLib.Error e) {
                     warning(e.message);
@@ -262,41 +262,29 @@ public class Seahorse.Ssh.Key : Seahorse.Object, Seahorse.Exportable, Seahorse.D
             // See if we have a public key
             try {
                 KeyData keydata = KeyData.parse_line(line);
-                if (pub_handler != null)
-                    pub_handler(keydata);
+                pubkeys.add(keydata);
             } catch (GLib.Error e) {
                 warning(e.message);
             }
         }
+
+        var result = KeyParseResult();
+        result.public_keys = pubkeys.steal();
+        result.secret_keys = seckeys.steal();
+        return result;
     }
 
     /**
      * Parses the contents of the given file into public/private keys.
      *
      * @param data The file that will be parsed.
-     * @param pub_handler Will be called anytime a public key has been parsed.
-     *                    If null, nothing will be done if a public key is parsed.
-     * @param priv_handler Will be called anytime a private key has been parsed.
-     *                     If null, nothing will be done if a private key is parsed.
      * @param cancellable Can be used to cancel the parsing.
      */
-    public static async void parse_file(string filename,
-                                        PubParsedHandler? pub_handler,
-                                        PrivParsedHandler? priv_handler = null,
-                                        Cancellable? cancellable = null) throws GLib.Error {
+    public static async KeyParseResult parse_file(string filename,
+                                                  Cancellable? cancellable = null) throws GLib.Error {
         string contents;
         FileUtils.get_contents(filename, out contents);
 
-        yield parse(contents, pub_handler, priv_handler, cancellable);
+        return yield parse(contents, cancellable);
     }
-
-    /**
-     * Takes care of the public key that has been found in a string while parsing.
-     */
-    public delegate bool PubParsedHandler(KeyData data);
-
-    /**
-     * Takes care of the private key that has been found in a string while parsing.
-     */
-    public delegate bool PrivParsedHandler(SecData data);
 }
diff --git a/ssh/seahorse-ssh-generate.ui b/ssh/seahorse-ssh-generate.ui
index 09645877..a9db2c27 100644
--- a/ssh/seahorse-ssh-generate.ui
+++ b/ssh/seahorse-ssh-generate.ui
@@ -1,10 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
-  <requires lib="gtk+" version="3.22"/>
+  <requires lib="gtk+" version="3.24"/>
   <template class="SeahorseSshGenerate" parent="GtkDialog">
     <property name="modal">True</property>
-    <property name="resizable">False</property>
-    <property name="border_width">5</property>
+    <property name="border_width">18</property>
     <property name="title" translatable="yes">New Secure Shell Key</property>
     <child internal-child="vbox">
       <object class="GtkBox">
@@ -13,236 +12,202 @@
         <property name="orientation">vertical</property>
         <property name="spacing">2</property>
         <child>
-          <object class="GtkBox" id="hbox4">
+          <object class="GtkBox" id="vbox5">
             <property name="visible">True</property>
-            <property name="orientation">horizontal</property>
+            <property name="orientation">vertical</property>
             <property name="can_focus">False</property>
-            <property name="border_width">5</property>
             <property name="spacing">12</property>
             <child>
-              <object class="GtkImage" id="ssh-image">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="yalign">0</property>
-                <property name="pixel_size">48</property>
-                <property name="icon_name">gcr-key-pair</property>
-              </object>
-            </child>
-            <child>
-              <object class="GtkBox" id="vbox5">
+              <object class="GtkBox" id="vbox3">
                 <property name="visible">True</property>
                 <property name="orientation">vertical</property>
                 <property name="can_focus">False</property>
                 <property name="spacing">12</property>
                 <child>
-                  <object class="GtkBox" id="vbox3">
+                  <object class="GtkBox" id="hbox41">
                     <property name="visible">True</property>
-                    <property name="orientation">vertical</property>
+                    <property name="orientation">horizontal</property>
                     <property name="can_focus">False</property>
                     <property name="spacing">12</property>
                     <child>
-                      <object class="GtkBox" id="hbox41">
+                      <object class="GtkLabel" id="label45">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="xalign">0</property>
+                        <property name="yalign">0</property>
+                        <property name="label" translatable="yes">A Secure Shell (SSH) key lets you connect 
securely to other computers.</property>
+                        <property name="wrap">True</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkGrid" id="details_grid">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="row_spacing">6</property>
+                    <property name="column_spacing">12</property>
+                    <child>
+                      <object class="GtkLabel" id="email_label">
                         <property name="visible">True</property>
-                        <property name="orientation">horizontal</property>
                         <property name="can_focus">False</property>
-                        <property name="spacing">12</property>
-                        <child>
-                          <object class="GtkLabel" id="label45">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="xalign">0</property>
-                            <property name="yalign">0</property>
-                            <property name="label" translatable="yes">A Secure Shell (SSH) key lets you 
connect securely to other computers.</property>
-                            <property name="wrap">True</property>
-                          </object>
-                        </child>
+                        <property name="xalign">1</property>
+                        <property name="yalign">0</property>
+                        <property name="label" translatable="yes">_Description</property>
+                        <property name="use_markup">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">email_entry</property>
+                        <style>
+                          <class name="dim-label"/>
+                        </style>
                       </object>
                       <packing>
-                        <property name="expand">True</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
+                        <property name="top_attach">0</property>
+                        <property name="left_attach">0</property>
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkGrid" id="details_grid">
+                      <object class="GtkEntry" id="email_entry">
+                        <property name="width_request">180</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="invisible_char">●</property>
+                        <property name="activates_default">True</property>
+                        <property name="invisible_char_set">True</property>
+                      </object>
+                      <packing>
+                        <property name="top_attach">0</property>
+                        <property name="left_attach">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
-                        <property name="row_spacing">6</property>
-                        <property name="column_spacing">12</property>
-                        <child>
-                          <object class="GtkLabel" id="email_label">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="xalign">1</property>
-                            <property name="yalign">0</property>
-                            <property name="label" translatable="yes">_Description</property>
-                            <property name="use_markup">True</property>
-                            <property name="use_underline">True</property>
-                            <property name="mnemonic_widget">email_entry</property>
-                            <style>
-                              <class name="dim-label"/>
-                            </style>
-                          </object>
-                          <packing>
-                            <property name="top_attach">0</property>
-                            <property name="left_attach">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkEntry" id="email_entry">
-                            <property name="width_request">180</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="invisible_char">●</property>
-                            <property name="activates_default">True</property>
-                            <property name="invisible_char_set">True</property>
-                          </object>
-                          <packing>
-                            <property name="top_attach">0</property>
-                            <property name="left_attach">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="xalign">0</property>
-                            <property name="xpad">3</property>
-                            <property name="label" translatable="yes">Your email address, or a reminder of 
what this key is for.</property>
-                            <property name="wrap">True</property>
-                            <style>
-                              <class name="dim-label"/>
-                            </style>
-                          </object>
-                          <packing>
-                            <property name="left_attach">1</property>
-                            <property name="top_attach">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="label49">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="halign">end</property>
-                            <property name="label" translatable="yes">Encryption _Type</property>
-                            <property name="use_underline">True</property>
-                            <property name="mnemonic_widget">algorithm_combo_box</property>
-                            <style>
-                              <class name="dim-label"/>
-                            </style>
-                          </object>
-                          <packing>
-                            <property name="top_attach">2</property>
-                            <property name="left_attach">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkComboBoxText" id="algorithm_combo_box">
-                            <property name="visible">True</property>
-                            <property name="halign">start</property>
-                            <property name="can_focus">False</property>
-                            <property name="entry_text_column">0</property>
-                            <property name="id_column">1</property>
-                            <items>
-                              <item translatable="yes">RSA</item>
-                              <item translatable="yes">DSA</item>
-                              <item translatable="yes">ECDSA</item>
-                              <item translatable="yes">ED25519</item>
-                            </items>
-                            <signal name="changed" handler="on_algo_changed"/>
-                          </object>
-                          <packing>
-                            <property name="top_attach">2</property>
-                            <property name="left_attach">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="label50">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="halign">end</property>
-                            <property name="label" translatable="yes">Key _Strength (bits)</property>
-                            <property name="use_underline">True</property>
-                            <style>
-                              <class name="dim-label"/>
-                            </style>
-                          </object>
-                          <packing>
-                            <property name="top_attach">3</property>
-                            <property name="left_attach">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <!-- Key strength widget comes here -->
-                          <placeholder/>
-                        </child>
+                        <property name="xalign">0</property>
+                        <property name="xpad">3</property>
+                        <property name="label" translatable="yes">Your email address, or a reminder of what 
this key is for.</property>
+                        <property name="wrap">True</property>
+                        <style>
+                          <class name="dim-label"/>
+                        </style>
                       </object>
                       <packing>
-                        <property name="expand">True</property>
-                        <property name="fill">True</property>
-                        <property name="position">1</property>
+                        <property name="left_attach">1</property>
+                        <property name="top_attach">1</property>
                       </packing>
                     </child>
+                    <child>
+                      <object class="GtkLabel" id="label49">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="halign">end</property>
+                        <property name="label" translatable="yes">Encryption _Type</property>
+                        <property name="use_underline">True</property>
+                        <property name="mnemonic_widget">algorithm_combo_box</property>
+                        <style>
+                          <class name="dim-label"/>
+                        </style>
+                      </object>
+                      <packing>
+                        <property name="top_attach">2</property>
+                        <property name="left_attach">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkComboBoxText" id="algorithm_combo_box">
+                        <property name="visible">True</property>
+                        <property name="halign">start</property>
+                        <property name="can_focus">False</property>
+                        <property name="entry_text_column">0</property>
+                        <property name="id_column">1</property>
+                        <items>
+                          <item translatable="yes">RSA</item>
+                          <item translatable="yes">DSA</item>
+                          <item translatable="yes">ECDSA</item>
+                          <item translatable="yes">ED25519</item>
+                        </items>
+                        <signal name="changed" handler="on_algo_changed"/>
+                      </object>
+                      <packing>
+                        <property name="top_attach">2</property>
+                        <property name="left_attach">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="label50">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="halign">end</property>
+                        <property name="label" translatable="yes">Key _Strength (bits)</property>
+                        <property name="use_underline">True</property>
+                        <style>
+                          <class name="dim-label"/>
+                        </style>
+                      </object>
+                      <packing>
+                        <property name="top_attach">3</property>
+                        <property name="left_attach">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <!-- Key strength widget comes here -->
+                      <placeholder/>
+                    </child>
                   </object>
-                </child>
-                <child>
-                  <object class="GtkLabel">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="margin_top">24</property>
-                    <property name="xalign">0</property>
-                    <property name="max-width-chars">75</property>
-                    <property name="label" translatable="yes">If there is a computer you want to use this 
key with, you can set up that computer to recognize your new key.</property>
-                    <property name="wrap">True</property>
-                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
                 </child>
               </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_top">24</property>
+                <property name="xalign">0</property>
+                <property name="max-width-chars">75</property>
+                <property name="label" translatable="yes">If there is a computer you want to use this key 
with, you can set up that computer to recognize your new key.</property>
+                <property name="wrap">True</property>
+              </object>
             </child>
           </object>
           <packing>
-            <property name="expand">False</property>
+            <property name="expand">True</property>
             <property name="fill">True</property>
             <property name="position">1</property>
           </packing>
         </child>
       </object>
     </child>
-    <child internal-child="action_area">
-      <object class="GtkButtonBox" id="action_area">
+    <child type="action">
+      <object class="GtkButton" id="cancel_button">
+        <property name="label" translatable="yes">_Cancel</property>
         <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <child>
-          <object class="GtkButton" id="create_no_setup_button">
-            <property name="label" translatable="yes">_Just Create Key</property>
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="can_default">True</property>
-            <property name="receives_default">False</property>
-            <property name="use_underline">True</property>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkButton" id="create_with_setup_button">
-            <property name="label" translatable="yes">_Create and Set Up</property>
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="use_underline">True</property>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-          </packing>
-        </child>
+        <property name="receives_default">False</property>
+        <property name="use_underline">True</property>
+      </object>
+    </child>
+    <child type="action">
+      <object class="GtkButton" id="ok_button">
+        <property name="label" translatable="yes">_Generate</property>
+        <property name="visible">True</property>
+        <property name="can_default">True</property>
+        <property name="receives_default">False</property>
+        <property name="use_underline">True</property>
       </object>
     </child>
+    <action-widgets>
+      <action-widget response="cancel">cancel_button</action-widget>
+      <action-widget response="accept" default="true">ok_button</action-widget>
+    </action-widgets>
   </template>
 </interface>
diff --git a/ssh/source.vala b/ssh/source.vala
index bf366419..9226a371 100644
--- a/ssh/source.vala
+++ b/ssh/source.vala
@@ -229,10 +229,10 @@ public class Seahorse.Ssh.Source : GLib.Object, Gcr.Collection, Seahorse.Place {
                 && FileUtils.test(pubfile, FileTest.EXISTS)
                 && check_file_for_ssh(privfile)) {
             try {
-                yield Key.parse_file(pubfile, (keydata) => {
+                var result = yield Key.parse_file(pubfile);
+                foreach (unowned var keydata in result.public_keys) {
                     key = Source.add_key_from_parsed_data(this, keydata, pubfile, false, false, privfile);
-                    return true;
-                });
+                }
             } catch (GLib.Error e) {
                 throw new Error.GENERAL("Couldn't read SSH file: %s (%s)".printf(pubfile, e.message));
             }
@@ -280,17 +280,17 @@ public class Seahorse.Ssh.Source : GLib.Object, Gcr.Collection, Seahorse.Place {
 
         // Now load the authorized keys
         string pubfile = authorized_keys_path();
-        Key.parse_file.begin(pubfile, (keydata) => {
+        var result = yield Key.parse_file(pubfile);
+        foreach (unowned var keydata in result.public_keys) {
             Source.add_key_from_parsed_data(this, keydata, pubfile, true, true, null);
-            return true;
-        });
+        }
 
         // Load the "other keys" (public keys without authorization)
         pubfile = other_keys_path();
-        Key.parse_file.begin(pubfile, (keydata) => {
+        result = yield Key.parse_file(pubfile);
+        foreach (unowned var keydata in result.public_keys) {
             Source.add_key_from_parsed_data(this, keydata, pubfile, true, false, null);
-            return true;
-        });
+        }
 
         return true;
     }
@@ -331,7 +331,6 @@ public class Seahorse.Ssh.Source : GLib.Object, Gcr.Collection, Seahorse.Place {
         return key;
     }
 
-
     /**
      * Parse an inputstream into a list of keys and import those keys.
      */
@@ -342,17 +341,15 @@ public class Seahorse.Ssh.Source : GLib.Object, Gcr.Collection, Seahorse.Place {
         input.read_all(buffer, out bytes_read, cancellable);
 
         string fullpath = other_keys_path();
-        Source src = this;
-
-        Key.parse.begin((string) buffer,
-                        (keydata) => {
-                            import_public_async.begin(keydata, fullpath, cancellable);
-                            return true;
-                        },
-                        (secdata) => {
-                            new PrivateImportOperation().import_private_async.begin(src, secdata, null, 
cancellable);
-                            return true;
-                        });
+
+        var result = yield Key.parse((string) buffer, cancellable);
+        foreach (unowned var keydata in result.public_keys) {
+            yield import_public_async(keydata, fullpath, cancellable);
+        }
+        foreach (unowned var secdata in result.secret_keys) {
+            var op = new PrivateImportOperation();
+            yield op.import_private_async(this, secdata, null, cancellable);
+        }
 
         // TODO: The list of keys imported?
         return null;


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