[seahorse] Port SeahorsePassphrase to Vala



commit 1e3684cfcd41b74712f377440aaaee8c55bbb9af
Author: Niels De Graef <nielsdegraef gmail com>
Date:   Mon Oct 2 08:18:59 2017 +0200

    Port SeahorsePassphrase to Vala

 common/Makefile.am                 |    1 +
 common/passphrase-prompt.vala      |  231 +++++++++++++++++++++++++++
 libseahorse/Makefile.am            |    1 -
 libseahorse/seahorse-interaction.c |   11 +-
 libseahorse/seahorse-passphrase.c  |  304 ------------------------------------
 libseahorse/seahorse-passphrase.h  |   38 -----
 pgp/seahorse-gpgme-generate.c      |    9 +-
 pgp/seahorse-gpgme-keyring.c       |    9 +-
 po/POTFILES.in                     |    2 +-
 ssh/Makefile.am                    |    2 +-
 ssh/seahorse-ssh-askpass.c         |   10 +-
 11 files changed, 253 insertions(+), 365 deletions(-)
---
diff --git a/common/Makefile.am b/common/Makefile.am
index a2cc1e1..29443d8 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -12,6 +12,7 @@ common_VALA = \
        common/exporter.vala \
        common/icons.vala \
        common/lockable.vala \
+       common/passphrase-prompt.vala \
        common/place.vala \
        common/registry.vala \
        common/types.vala \
diff --git a/common/passphrase-prompt.vala b/common/passphrase-prompt.vala
new file mode 100644
index 0000000..a3d163f
--- /dev/null
+++ b/common/passphrase-prompt.vala
@@ -0,0 +1,231 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2003 Jacob Perkins
+ * Copyright (C) 2004 - 2006 Stefan Walter
+ * Copyright (C) 2011 Collabora Ltd.
+ * Copyright (C) 2017 Niels De Graef
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+// TODO move these into a namespace or class
+public const int SEAHORSE_PASS_BAD = 0x00000001;
+public const int SEAHORSE_PASS_NEW = 0x01000000;
+
+public class Seahorse.PassphrasePrompt : Gtk.Dialog {
+    // gnome hig small space in pixels
+    private const int HIG_SMALL = 6;
+    // gnome hig large space in pixels
+    private const int HIG_LARGE = 12;
+
+    private Gtk.Entry secure_entry;
+    private Gtk.Entry? confirm_entry;
+    private Gtk.CheckButton? check_option;
+
+#if ! _DEBUG
+    private bool keyboard_grabbed;
+#endif
+
+    public PassphrasePrompt (string? title, string? description, string prompt, string? check, bool confirm) 
{
+        GLib.Object(
+            title: title,
+            modal: true,
+            icon_name: Gtk.Stock.DIALOG_AUTHENTICATION
+        );
+
+        Gtk.Box wvbox = new Gtk.Box(Gtk.Orientation.VERTICAL, HIG_LARGE * 2);
+        get_content_area().add(wvbox);
+        wvbox.set_border_width(HIG_LARGE);
+
+        Gtk.Box chbox = new Gtk.Box(Gtk.Orientation.HORIZONTAL, HIG_LARGE);
+        wvbox.pack_start (chbox, false, false);
+
+        // The image
+        Gtk.Image img = new Gtk.Image.from_stock(Gtk.Stock.DIALOG_AUTHENTICATION, Gtk.IconSize.DIALOG);
+        img.set_alignment(0.0f, 0.0f);
+        chbox.pack_start(img, false, false);
+
+        Gtk.Box box = new Gtk.Box(Gtk.Orientation.VERTICAL, HIG_SMALL);
+        chbox.pack_start (box);
+
+        // The description text
+        if (description != null) {
+            Gtk.Label desc_label = new Gtk.Label(utf8_validate (description));
+            desc_label.set_alignment(0.0f, 0.5f);
+            desc_label.set_line_wrap(true);
+            box.pack_start(desc_label, true, false);
+        }
+
+        Gtk.Grid grid = new Gtk.Grid();
+        grid.set_row_spacing(HIG_SMALL);
+        grid.set_column_spacing(HIG_LARGE);
+        box.pack_start(grid, false, false);
+
+        // The first entry (if we have one)
+        if (confirm) {
+            Gtk.Label prompt_label = new Gtk.Label(utf8_validate (prompt));
+            prompt_label.set_alignment(0.0f, 0.5f);
+            grid.attach(prompt_label, 0, 0);
+
+            this.confirm_entry = new Gtk.Entry.with_buffer(new Gcr.SecureEntryBuffer());
+            this.confirm_entry.set_visibility(false);
+            this.confirm_entry.set_size_request(200, -1);
+            this.confirm_entry.activate.connect(confirm_callback);
+            this.confirm_entry.changed.connect(entry_changed);
+            grid.attach(this.confirm_entry, 1, 0);
+            this.confirm_entry.grab_focus();
+        }
+
+        // The second and main entry
+        Gtk.Label confirm_label = new Gtk.Label(utf8_validate (confirm? _("Confirm:") : prompt));
+        confirm_label.set_alignment(0.0f, 0.5f);
+        grid.attach(confirm_label, 0, 1);
+
+        this.secure_entry = new Gtk.Entry.with_buffer(new Gcr.SecureEntryBuffer());
+        this.secure_entry.set_size_request(200, -1);
+        this.secure_entry.set_visibility(false);
+        this.secure_entry.activate.connect(() => {
+            if (get_widget_for_response(Gtk.ResponseType.ACCEPT).sensitive)
+                response(Gtk.ResponseType.ACCEPT);
+        });
+        grid.attach(secure_entry, 1, 1);
+        if (confirm)
+            this.secure_entry.changed.connect(entry_changed);
+        else
+            this.secure_entry.grab_focus();
+
+        // The checkbox
+        if (check != null) {
+            this.check_option = new Gtk.CheckButton.with_mnemonic(check);
+            grid.attach(this.check_option, 1, 2);
+        }
+
+        grid.show_all();
+
+        Gtk.Button cancel_button = new Gtk.Button.from_stock(Gtk.Stock.CANCEL);
+        add_action_widget(cancel_button, Gtk.ResponseType.REJECT);
+        cancel_button.set_can_default(true);
+
+        Gtk.Button ok_button = new Gtk.Button.from_stock(Gtk.Stock.OK);
+        add_action_widget(ok_button, Gtk.ResponseType.ACCEPT);
+        ok_button.set_can_default(true);
+        ok_button.grab_default();
+
+        // Signals
+        this.map_event.connect(grab_keyboard);
+        this.unmap_event.connect(ungrab_keyboard);
+        this.window_state_event.connect(window_state_changed);
+        this.key_press_event.connect(key_press);
+
+        set_position(Gtk.WindowPosition.CENTER);
+        set_resizable(false);
+        set_keep_above(true);
+        show_all();
+        get_window().focus(Gdk.CURRENT_TIME);
+
+        if (confirm)
+            entry_changed (null);
+    }
+
+    // Kept for backwards compatibility with the C code
+    public static PassphrasePrompt show_dialog(string? title, string? description, string? prompt,
+                                               string? check, bool confirm) {
+        return new PassphrasePrompt(title, description, prompt ?? _("Password:"), check, confirm);
+    }
+
+    public string get_text() {
+        return this.secure_entry.text;
+    }
+
+    public bool checked() {
+        return this.check_option.active;
+    }
+
+    // Convert passed text to utf-8 if not valid
+    private string? utf8_validate(string? text) {
+        if (text == null)
+            return null;
+
+        if (text.validate())
+            return text;
+
+        string? result = text.locale_to_utf8(-1, null, null);
+        if (result == null) {
+            // Convert unknown characters into "?"
+            char* p = (char*) text;
+
+            while (!((string)p).validate (-1, out p))
+                *p = '?';
+
+            result = text;
+        }
+        return result;
+    }
+
+    private bool key_press (Gtk.Widget widget, Gdk.EventKey event) {
+        // Close the dialog when hitting "Esc".
+        if (event.keyval == Gdk.Key.Escape) {
+            response(Gtk.ResponseType.REJECT);
+            return true;
+        }
+
+        return false;
+    }
+
+    private bool grab_keyboard (Gtk.Widget win, Gdk.Event event) {
+#if ! _DEBUG
+        if (!this.keyboard_grabbed)
+            if (Gdk.keyboard_grab(win.get_window(), false, event.get_time()) != 0)
+                message("could not grab keyboard");
+        this.keyboard_grabbed = true;
+#endif
+        return false;
+    }
+
+    /* ungrab_keyboard - remove grab */
+    private bool ungrab_keyboard (Gtk.Widget win, Gdk.Event event) {
+#if ! _DEBUG
+        if (this.keyboard_grabbed)
+            Gdk.keyboard_ungrab(event.get_time());
+        this.keyboard_grabbed = false;
+#endif
+        return false;
+    }
+
+    /* When enter is pressed in the confirm entry, move */
+    private void confirm_callback(Gtk.Widget widget) {
+        this.secure_entry.grab_focus();
+    }
+
+    private void entry_changed (Gtk.Editable? editable) {
+        set_response_sensitive(Gtk.ResponseType.ACCEPT,
+                               this.secure_entry.text == this.confirm_entry.text);
+    }
+
+    private bool window_state_changed (Gtk.Widget win, Gdk.EventWindowState event) {
+        Gdk.WindowState state = win.get_window().get_state();
+
+        if (Gdk.WindowState.WITHDRAWN in state ||
+            Gdk.WindowState.ICONIFIED in state ||
+            Gdk.WindowState.FULLSCREEN in state ||
+            Gdk.WindowState.MAXIMIZED in state)
+                ungrab_keyboard (win, event);
+        else
+            grab_keyboard (win, event);
+
+        return false;
+    }
+
+}
diff --git a/libseahorse/Makefile.am b/libseahorse/Makefile.am
index 3ff8e9b..d9b0fa9 100644
--- a/libseahorse/Makefile.am
+++ b/libseahorse/Makefile.am
@@ -41,7 +41,6 @@ libseahorse_a_SOURCES = \
        libseahorse/seahorse-object-list.c libseahorse/seahorse-object-list.h \
        libseahorse/seahorse-object-model.c libseahorse/seahorse-object-model.h \
        libseahorse/seahorse-object-widget.c libseahorse/seahorse-object-widget.h \
-       libseahorse/seahorse-passphrase.c libseahorse/seahorse-passphrase.h \
        libseahorse/seahorse-predicate.c libseahorse/seahorse-predicate.h \
        libseahorse/seahorse-prefs.c libseahorse/seahorse-prefs.h \
        libseahorse/seahorse-progress.c libseahorse/seahorse-progress.h \
diff --git a/libseahorse/seahorse-interaction.c b/libseahorse/seahorse-interaction.c
index 2c65ba5..086cb0b 100644
--- a/libseahorse/seahorse-interaction.c
+++ b/libseahorse/seahorse-interaction.c
@@ -21,8 +21,9 @@
 
 #include "config.h"
 
+#include "seahorse-common.h"
+
 #include "seahorse-interaction.h"
-#include "seahorse-passphrase.h"
 
 #include <glib/gi18n.h>
 #include <gcr/gcr.h>
@@ -106,23 +107,23 @@ seahorse_interaction_ask_password (GTlsInteraction *interaction,
 {
        SeahorseInteraction *self = SEAHORSE_INTERACTION (interaction);
        GTlsInteractionResult res;
-       GtkDialog *dialog;
+       SeahorsePassphrasePrompt *dialog;
        gchar *description;
        const gchar *pass;
        gsize length;
 
        description = calc_description (password);
 
-       dialog = seahorse_passphrase_prompt_show (NULL, description, NULL, NULL, FALSE);
+       dialog = seahorse_passphrase_prompt_show_dialog (NULL, description, NULL, NULL, FALSE);
 
        g_free (description);
 
        if (self->pv->parent)
                gtk_window_set_transient_for (GTK_WINDOW (dialog), self->pv->parent);
 
-       switch (gtk_dialog_run (dialog)) {
+       switch (gtk_dialog_run (GTK_DIALOG (dialog))) {
        case GTK_RESPONSE_ACCEPT:
-               pass = seahorse_passphrase_prompt_get (dialog);
+               pass = seahorse_passphrase_prompt_get_text (dialog);
                length = strlen (pass);
                g_tls_password_set_value_full (password,
                                               (guchar *)gcr_secure_memory_strdup (pass),
diff --git a/pgp/seahorse-gpgme-generate.c b/pgp/seahorse-gpgme-generate.c
index ad87d8b..71b3421 100644
--- a/pgp/seahorse-gpgme-generate.c
+++ b/pgp/seahorse-gpgme-generate.c
@@ -33,7 +33,6 @@
 
 #include "libegg/egg-datetime.h"
 
-#include "libseahorse/seahorse-passphrase.h"
 #include "libseahorse/seahorse-progress.h"
 #include "libseahorse/seahorse-util.h"
 #include "libseahorse/seahorse-widget.h"
@@ -207,15 +206,15 @@ seahorse_gpgme_generate_key (SeahorseGpgmeKeyring *keyring,
 {
        GCancellable *cancellable;
        const gchar *pass;
-       GtkDialog *dialog;
+       SeahorsePassphrasePrompt *dialog;
        const gchar *notice;
 
-       dialog = seahorse_passphrase_prompt_show (_("Passphrase for New PGP Key"),
+       dialog = seahorse_passphrase_prompt_show_dialog (_("Passphrase for New PGP Key"),
                                                  _("Enter the passphrase for your new key twice."),
                                                  NULL, NULL, TRUE);
        gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
-       if (gtk_dialog_run (dialog) == GTK_RESPONSE_ACCEPT) {
-               pass = seahorse_passphrase_prompt_get (dialog);
+       if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
+               pass = seahorse_passphrase_prompt_get_text (dialog);
                cancellable = g_cancellable_new ();
                seahorse_gpgme_key_op_generate_async (keyring, name, email, comment,
                                                      pass, type, bits, expires,
diff --git a/pgp/seahorse-gpgme-keyring.c b/pgp/seahorse-gpgme-keyring.c
index 73a2ed2..95aae0d 100644
--- a/pgp/seahorse-gpgme-keyring.c
+++ b/pgp/seahorse-gpgme-keyring.c
@@ -36,7 +36,6 @@
 
 #include "libseahorse/seahorse-progress.h"
 #include "libseahorse/seahorse-util.h"
-#include "libseahorse/seahorse-passphrase.h"
 
 #include <gcr/gcr.h>
 
@@ -69,7 +68,7 @@ static gpgme_error_t
 passphrase_get (gconstpointer dummy, const gchar *passphrase_hint,
                 const char* passphrase_info, int flags, int fd)
 {
-       GtkDialog *dialog;
+       SeahorsePassphrasePrompt *dialog;
        gpgme_error_t err;
        gchar **split_uid = NULL;
        gchar *label = NULL;
@@ -102,14 +101,14 @@ passphrase_get (gconstpointer dummy, const gchar *passphrase_hint,
 
        g_strfreev (split_uid);
 
-       dialog = seahorse_passphrase_prompt_show (_("Passphrase"), errmsg ? errmsg : label,
+       dialog = seahorse_passphrase_prompt_show_dialog (_("Passphrase"), errmsg ? errmsg : label,
                                                  NULL, NULL, confirm);
        g_free (label);
        g_free (errmsg);
 
-       switch (gtk_dialog_run (dialog)) {
+       switch (gtk_dialog_run (GTK_DIALOG (dialog))) {
        case GTK_RESPONSE_ACCEPT:
-               pass = seahorse_passphrase_prompt_get (dialog);
+               pass = seahorse_passphrase_prompt_get_text (dialog);
                seahorse_util_printf_fd (fd, "%s\n", pass);
                err = GPG_OK;
                break;
diff --git a/po/POTFILES.in b/po/POTFILES.in
index fc1b29d..1b35237 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -2,6 +2,7 @@
 # Please keep this file sorted alphabetically.
 common/catalog.vala
 common/exportable.vala
+common/passphrase-prompt.vala
 common/util.vala
 common/validity.vala
 data/seahorse.appdata.xml.in
@@ -23,7 +24,6 @@ libseahorse/seahorse-application.c
 libseahorse/seahorse-interaction.c
 libseahorse/seahorse-key-manager-store.c
 libseahorse/seahorse-object.c
-libseahorse/seahorse-passphrase.c
 libseahorse/seahorse-prefs.c
 libseahorse/seahorse-prefs.ui
 libseahorse/seahorse-progress.ui
diff --git a/ssh/Makefile.am b/ssh/Makefile.am
index 412a7a8..807aaaf 100644
--- a/ssh/Makefile.am
+++ b/ssh/Makefile.am
@@ -58,9 +58,9 @@ ui_files += \
 seahorselibexecbin_PROGRAMS += seahorse-ssh-askpass
 
 seahorse_ssh_askpass_SOURCES = \
-       libseahorse/seahorse-passphrase.c \
        ssh/seahorse-ssh-askpass.c
 seahorse_ssh_askpass_LDADD = \
+       libcommon.a \
        $(SEAHORSE_LIBS)
 
 -include $(top_srcdir)/git.mk
diff --git a/ssh/seahorse-ssh-askpass.c b/ssh/seahorse-ssh-askpass.c
index cccf59f..5ebeeb2 100644
--- a/ssh/seahorse-ssh-askpass.c
+++ b/ssh/seahorse-ssh-askpass.c
@@ -22,7 +22,7 @@
  
 #include "config.h"
 
-#include "libseahorse/seahorse-passphrase.h"
+#include "seahorse-common.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -40,7 +40,7 @@ int
 main (int argc, char* argv[])
 {
        GdkWindow *transient_for = NULL;
-       GtkDialog *dialog;
+       SeahorsePassphrasePrompt *dialog;
        const gchar *title;
        const gchar *argument;
        gchar *message;
@@ -114,7 +114,7 @@ main (int argc, char* argv[])
                g_free (lower);
        }
 
-       dialog = seahorse_passphrase_prompt_show (title, message, _("Password:"),
+       dialog = seahorse_passphrase_prompt_show_dialog (title, message, _("Password:"),
                                                  NULL, FALSE);
 
        g_free (message);
@@ -125,8 +125,8 @@ main (int argc, char* argv[])
        }
 
        result = 1;
-       if (gtk_dialog_run (dialog) == GTK_RESPONSE_ACCEPT) {
-               pass = seahorse_passphrase_prompt_get (dialog);
+       if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
+               pass = seahorse_passphrase_prompt_get_text (dialog);
                len = strlen (pass ? pass : "");
                if (write (1, pass, len) != len) {
                        g_warning ("couldn't write out password properly");


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