gnome-keyring [PATCH 2/9] ui: add a dialog that asks for PKCS#11 object PIN



---
 po/POTFILES.in               |   2 +
 ui/Makefile.am               |   2 +
 ui/gcr-token-login-dialog.c  | 250 +++++++++++++++++++++++++++++++++++++++++++
 ui/gcr-token-login-dialog.h  |  43 ++++++++
 ui/gcr-token-login-dialog.ui | 111 +++++++++++++++++++
 ui/gcr-ui.symbols            |   5 +
 ui/gcr.gresource.xml         |   1 +
 7 files changed, 414 insertions(+)
 create mode 100644 ui/gcr-token-login-dialog.c
 create mode 100644 ui/gcr-token-login-dialog.h
 create mode 100644 ui/gcr-token-login-dialog.ui

diff --git a/po/POTFILES.in b/po/POTFILES.in
index bb70c17..a57d084 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -32,6 +32,8 @@ ui/gcr-pkcs11-import-dialog.c
 ui/gcr-pkcs11-import-interaction.c
 ui/gcr-prompt-dialog.c
 ui/gcr-prompter.desktop.in.in
+ui/gcr-token-login-dialog.c
+[type: gettext/glade]ui/gcr-token-login-dialog.ui
 ui/gcr-certificate-exporter.c
 [type: gettext/glade]ui/gcr-unlock-options-widget.ui
 ui/gcr-unlock-renderer.c
diff --git a/ui/Makefile.am b/ui/Makefile.am
index c84ef8e..0b515ff 100644
--- a/ui/Makefile.am
+++ b/ui/Makefile.am
@@ -62,6 +62,7 @@ ui_HEADER_FILES = \
        ui/gcr-prompt-dialog.h \
        ui/gcr-renderer.h \
        ui/gcr-secure-entry-buffer.h \
+       ui/gcr-token-login-dialog.h \
        ui/gcr-tree-selector.h \
        ui/gcr-unlock-options-widget.h \
        ui/gcr-viewer.h \
@@ -107,6 +108,7 @@ ui_PRIVATE_FILES = \
        ui/gcr-live-search.c ui/gcr-live-search.h \
        ui/gcr-pkcs11-import-dialog.c ui/gcr-pkcs11-import-dialog.h \
        ui/gcr-pkcs11-import-interaction.c ui/gcr-pkcs11-import-interaction.h \
+       ui/gcr-token-login-dialog.c ui/gcr-token-login-dialog.h \
        ui/gcr-unlock-renderer.c ui/gcr-unlock-renderer.h \
        ui/gcr-viewer-window.c ui/gcr-viewer-window.h \
        $(NULL)
diff --git a/ui/gcr-token-login-dialog.c b/ui/gcr-token-login-dialog.c
new file mode 100644
index 0000000..2687757
--- /dev/null
+++ b/ui/gcr-token-login-dialog.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2016 Lubomir Rintel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gcr-token-login-dialog.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <gck/gck.h>
+
+/**
+ * SECTION:gcr-token-login-dialog
+ * @title: GcrTokenLoginDialog
+ * @short_description: The PKCS11 PIN Dialog
+ * @see_also: #GcrObjectChooserDialog
+ *
+ * #GcrTokenLoginDialog asks for the PKCS11 login pin.
+ * It enforces the PIN constrains (maximum & minimum length).
+ *
+ * Used by the #GcrObjectChooserDialog when the #GcrTokensSidebar indicates
+ * that the user requested the token to be logged in.
+ */
+
+struct _GcrTokenLoginDialogPrivate
+{
+       GckSlot *slot;
+       GckTokenInfo *info;
+
+       GtkEntry *pin_entry;
+       GtkCheckButton *remember;
+};
+
+G_DEFINE_TYPE_WITH_CODE (GcrTokenLoginDialog, gcr_token_login_dialog, GTK_TYPE_DIALOG,
+                         G_ADD_PRIVATE (GcrTokenLoginDialog));
+
+enum
+{
+       PROP_0,
+       PROP_TOKEN_SLOT,
+};
+
+/**
+ * gcr_token_login_dialog_get_pin_value:
+ * @self: The #GcrTokenLoginDialog
+ *
+ * Returns: the entered PIN
+ */
+
+const guchar *
+gcr_token_login_dialog_get_pin_value (GcrTokenLoginDialog *self)
+{
+       GcrTokenLoginDialogPrivate *priv = self->priv;
+       GtkEntryBuffer *buffer = gtk_entry_get_buffer (priv->pin_entry);
+
+       return (guchar *) gtk_entry_buffer_get_text (buffer);
+}
+
+/**
+ * gcr_token_login_dialog_get_pin_length:
+ * @self: The #GcrTokenLoginDialog
+ *
+ * Returns: the PIN length
+ */
+
+gulong
+gcr_token_login_dialog_get_pin_length (GcrTokenLoginDialog *self)
+{
+       GcrTokenLoginDialogPrivate *priv = self->priv;
+       GtkEntryBuffer *buffer = gtk_entry_get_buffer (priv->pin_entry);
+
+       return gtk_entry_buffer_get_bytes (buffer);
+}
+
+/**
+ * gcr_token_login_dialog_get_remember_pin:
+ * @self: The #GcrTokenLoginDialog
+ *
+ * Returns: %TRUE if the "Remember PIN" checkbox was checked
+ */
+
+gboolean
+gcr_token_login_dialog_get_remember_pin (GcrTokenLoginDialog *self)
+{
+       GcrTokenLoginDialogPrivate *priv = self->priv;
+
+       return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->remember));
+}
+
+static void
+get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+       GcrTokenLoginDialog *self = GCR_TOKEN_LOGIN_DIALOG (object);
+       GcrTokenLoginDialogPrivate *priv = self->priv;
+
+       switch (prop_id) {
+       case PROP_TOKEN_SLOT:
+               if (priv->slot)
+                       g_value_set_object (value, priv->slot);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+       }
+}
+
+static gboolean
+can_activate (GcrTokenLoginDialog *self)
+{
+       GcrTokenLoginDialogPrivate *priv = self->priv;
+       GtkEntryBuffer *buffer = gtk_entry_get_buffer (priv->pin_entry);
+       guint len = gtk_entry_buffer_get_length (buffer);
+
+       return len <= priv->info->max_pin_len && len >= priv->info->min_pin_len;
+}
+
+static void
+set_slot (GcrTokenLoginDialog *self, GckSlot *slot)
+{
+       GcrTokenLoginDialogPrivate *priv = self->priv;
+       gchar *title;
+
+       g_clear_object (&priv->slot);
+       if (priv->info)
+               gck_token_info_free (priv->info);
+
+       priv->slot = slot;
+       priv->info = gck_slot_get_token_info (slot);
+
+       title = g_strdup_printf (_("Enter %s PIN"), priv->info->label);
+       gtk_window_set_title (GTK_WINDOW (self), title);
+       g_free (title);
+
+       gtk_entry_set_max_length (priv->pin_entry, priv->info->max_pin_len);
+       gtk_dialog_set_response_sensitive (GTK_DIALOG (self), GTK_RESPONSE_ACCEPT,
+                                          can_activate (self));
+}
+
+
+static void
+set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+       GcrTokenLoginDialog *self = GCR_TOKEN_LOGIN_DIALOG (object);
+
+       switch (prop_id) {
+       case PROP_TOKEN_SLOT:
+               set_slot (self, g_value_dup_object (value));
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+       }
+}
+
+static void
+finalize (GObject *object)
+{
+       GcrTokenLoginDialog *self = GCR_TOKEN_LOGIN_DIALOG (object);
+       GcrTokenLoginDialogPrivate *priv = self->priv;
+
+       g_clear_object (&priv->slot);
+       if (priv->info) {
+               gck_token_info_free (priv->info);
+               priv->info = NULL;
+       }
+
+       G_OBJECT_CLASS (gcr_token_login_dialog_parent_class)->finalize (object);
+}
+
+static void
+pin_changed (GtkEditable *editable, gpointer user_data)
+{
+       gtk_dialog_set_response_sensitive (GTK_DIALOG (user_data), GTK_RESPONSE_ACCEPT,
+                                          can_activate (GCR_TOKEN_LOGIN_DIALOG (user_data)));
+}
+
+
+static void
+pin_activate (GtkEditable *editable, gpointer user_data)
+{
+       if (can_activate (GCR_TOKEN_LOGIN_DIALOG (user_data)))
+               gtk_dialog_response (GTK_DIALOG (user_data), GTK_RESPONSE_ACCEPT);
+}
+
+static void
+gcr_token_login_dialog_class_init (GcrTokenLoginDialogClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+       object_class->get_property = get_property;
+       object_class->set_property = set_property;
+       object_class->finalize = finalize;
+
+       /**
+        * GcrTokenLoginDialog::token-slot:
+        *
+        * Slot that contains the pin for which the dialog requests
+        * the PIN.
+        */
+       g_object_class_install_property (object_class, PROP_TOKEN_SLOT,
+               g_param_spec_object ("token-slot", "Slot", "Slot containing the Token",
+                                    GCK_TYPE_SLOT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+       gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/gcr/ui/gcr-token-login-dialog.ui");
+       gtk_widget_class_bind_template_child_private (widget_class, GcrTokenLoginDialog, pin_entry);
+       gtk_widget_class_bind_template_child_private (widget_class, GcrTokenLoginDialog, remember);
+       gtk_widget_class_bind_template_callback (widget_class, pin_changed);
+       gtk_widget_class_bind_template_callback (widget_class, pin_activate);
+}
+
+static void
+gcr_token_login_dialog_init (GcrTokenLoginDialog *self)
+{
+       self->priv = gcr_token_login_dialog_get_instance_private (self);
+
+       gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+/**
+ * gcr_token_login_dialog_new:
+ * @slot: Slot that contains the pin for which the dialog requests the PIN
+ *
+ * Creates the new PKCS11 login dialog.
+ *
+ * Returns: the newly created #GcrTokenLoginDialog
+ */
+GtkWidget *
+gcr_token_login_dialog_new (GckSlot *slot)
+{
+       return GTK_WIDGET (g_object_new (GCR_TYPE_TOKEN_LOGIN_DIALOG,
+"use-header-bar", TRUE,
+                          "token-slot", slot,
+                          NULL));
+#if 0
+GtkDialogFlags flags,
+                              "use-header-bar", !!(flags & GTK_DIALOG_USE_HEADER_BAR),
+                              "title", title,
+#endif
+}
diff --git a/ui/gcr-token-login-dialog.h b/ui/gcr-token-login-dialog.h
new file mode 100644
index 0000000..141f1d2
--- /dev/null
+++ b/ui/gcr-token-login-dialog.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 Lubomir Rintel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GCR_TOKEN_LOGIN_DIALOG_H__
+#define __GCR_TOKEN_LOGIN_DIALOG_H__
+
+#include <gtk/gtk.h>
+#include <gck/gck.h>
+
+typedef struct _GcrTokenLoginDialogPrivate GcrTokenLoginDialogPrivate;
+
+struct _GcrTokenLoginDialog
+{
+        GtkDialog parent_instance;
+        GcrTokenLoginDialogPrivate *priv;
+};
+
+#define GCR_TYPE_TOKEN_LOGIN_DIALOG gcr_token_login_dialog_get_type ()
+G_DECLARE_FINAL_TYPE (GcrTokenLoginDialog, gcr_token_login_dialog, GCR, TOKEN_LOGIN_DIALOG, GtkDialog)
+
+GtkWidget *gcr_token_login_dialog_new (GckSlot *slot);
+
+const guchar *gcr_token_login_dialog_get_pin_value (GcrTokenLoginDialog *self);
+
+gulong gcr_token_login_dialog_get_pin_length (GcrTokenLoginDialog *self);
+
+gboolean gcr_token_login_dialog_get_remember_pin (GcrTokenLoginDialog *self);
+
+#endif /* __GCR_TOKEN_LOGIN_DIALOG_H__ */
diff --git a/ui/gcr-token-login-dialog.ui b/ui/gcr-token-login-dialog.ui
new file mode 100644
index 0000000..df66b0b
--- /dev/null
+++ b/ui/gcr-token-login-dialog.ui
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <template class="GcrTokenLoginDialog" parent="GtkDialog">
+    <property name="can_focus">False</property>
+    <property name="type_hint">dialog</property>
+    <child internal-child="vbox">
+      <object class="GtkBox">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="cancel">
+                <property name="label" translatable="yes">_Cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="pack_type">end</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="login">
+                <property name="label" translatable="yes">_Login</property>
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_underline">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">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_left">12</property>
+            <property name="margin_right">12</property>
+            <property name="margin_top">12</property>
+            <property name="margin_bottom">12</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkEntry" id="pin_entry">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="visibility">False</property>
+                <property name="input_purpose">password</property>
+                <signal name="activate" handler="pin_activate" swapped="no"/>
+                <signal name="changed" handler="pin_changed" swapped="no"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="padding">6</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkCheckButton" id="remember">
+                <property name="label" translatable="yes">_Remember PIN</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="halign">start</property>
+                <property name="use_underline">True</property>
+                <property name="draw_indicator">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="padding">6</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-6">cancel</action-widget>
+      <action-widget response="-3">login</action-widget>
+    </action-widgets>
+  </template>
+</interface>
diff --git a/ui/gcr-ui.symbols b/ui/gcr-ui.symbols
index d258eb5..c7640e1 100644
--- a/ui/gcr-ui.symbols
+++ b/ui/gcr-ui.symbols
@@ -75,6 +75,11 @@ gcr_renderer_render_view
 gcr_renderer_set_attributes
 gcr_secure_entry_buffer_get_type
 gcr_secure_entry_buffer_new
+gcr_token_login_dialog_get_pin_length
+gcr_token_login_dialog_get_pin_value
+gcr_token_login_dialog_get_remember_pin
+gcr_token_login_dialog_get_type
+gcr_token_login_dialog_new
 gcr_tree_selector_get_collection
 gcr_tree_selector_get_columns
 gcr_tree_selector_get_selected
diff --git a/ui/gcr.gresource.xml b/ui/gcr.gresource.xml
index 3ab232d..9e98153 100644
--- a/ui/gcr.gresource.xml
+++ b/ui/gcr.gresource.xml
@@ -3,5 +3,6 @@
        <gresource prefix="/org/gnome/gcr/ui">
                <file preprocess="xml-stripblanks">gcr-pkcs11-import-dialog.ui</file>
                <file preprocess="xml-stripblanks">gcr-unlock-options-widget.ui</file>
+               <file preprocess="xml-stripblanks">gcr-token-login-dialog.ui</file>
        </gresource>
 </gresources>
-- 
2.9.3



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