[seahorse] pkcs11: Support for creating certificate requests



commit 6daebac736c3fe3a8173443eca26f17bff0d427c
Author: Stef Walter <stefw collabora co uk>
Date:   Tue Nov 22 07:41:18 2011 +0100

    pkcs11: Support for creating certificate requests
    
     * Add an action button in the key properties window

 pkcs11/Makefile.am                  |    4 +-
 pkcs11/seahorse-pkcs11-properties.c |   92 ++++++++-
 pkcs11/seahorse-pkcs11-request.c    |  379 +++++++++++++++++++++++++++++++++++
 pkcs11/seahorse-pkcs11-request.h    |   34 +++
 pkcs11/seahorse-pkcs11-request.xml  |  114 +++++++++++
 5 files changed, 615 insertions(+), 8 deletions(-)
---
diff --git a/pkcs11/Makefile.am b/pkcs11/Makefile.am
index 75da6a2..6406266 100644
--- a/pkcs11/Makefile.am
+++ b/pkcs11/Makefile.am
@@ -23,6 +23,7 @@ libseahorse_pkcs11_la_SOURCES = \
 	seahorse-pkcs11-generate.c seahorse-pkcs11-generate.h \
 	seahorse-pkcs11-operations.c seahorse-pkcs11-operations.h \
 	seahorse-pkcs11-properties.c seahorse-pkcs11-properties.h \
+	seahorse-pkcs11-request.c seahorse-pkcs11-request.h \
 	seahorse-pkcs11.c seahorse-pkcs11.h \
 	seahorse-private-key.c seahorse-private-key.h \
 	seahorse-token.c seahorse-token.h
@@ -32,7 +33,8 @@ libseahorse_pkcs11_la_LIBADD = \
 	$(GCR_LIBS)
 
 ui_DATA = \
-	seahorse-pkcs11-generate.xml
+	seahorse-pkcs11-generate.xml \
+	seahorse-pkcs11-request.xml
 
 EXTRA_DIST = \
 	$(ui_DATA)
diff --git a/pkcs11/seahorse-pkcs11-properties.c b/pkcs11/seahorse-pkcs11-properties.c
index 540b6c8..409baa7 100644
--- a/pkcs11/seahorse-pkcs11-properties.c
+++ b/pkcs11/seahorse-pkcs11-properties.c
@@ -24,8 +24,10 @@
 #include "seahorse-certificate.h"
 #include "seahorse-pkcs11-properties.h"
 #include "seahorse-pkcs11-operations.h"
+#include "seahorse-pkcs11-request.h"
 #include "seahorse-private-key.h"
 
+#include "seahorse-action.h"
 #include "seahorse-delete-dialog.h"
 #include "seahorse-progress.h"
 #include "seahorse-util.h"
@@ -38,7 +40,7 @@ static const gchar *UI_STRING =
 "		<toolitem action='export-object'/>"
 "		<toolitem action='delete-object'/>"
 "		<separator name='MiddleSeparator' expand='true'/>"
-"		<toolitem action='extra-action'/>"
+"		<toolitem action='request-certificate'/>"
 "	</toolbar>"
 "</ui>";
 
@@ -53,6 +55,8 @@ struct _SeahorsePkcs11Properties {
 	GtkBox *content;
 	GcrViewer *viewer;
 	GObject *object;
+	GCancellable *cancellable;
+	GckObject *request_key;
 	GtkUIManager *ui_manager;
 	GtkActionGroup *actions;
 };
@@ -75,6 +79,8 @@ seahorse_pkcs11_properties_init (SeahorsePkcs11Properties *self)
 {
 	GtkWidget *viewer;
 
+	self->cancellable = g_cancellable_new ();
+
 	gtk_window_set_default_size (GTK_WINDOW (self), 400, 400);
 
 	self->content = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 0));
@@ -229,20 +235,21 @@ on_delete_objects (GtkAction *action,
 }
 
 static void
-on_extra_action (GtkAction *action,
-                 gpointer user_data)
+on_request_certificate (GtkAction *action,
+                        gpointer user_data)
 {
-
+	SeahorsePkcs11Properties *self = SEAHORSE_PKCS11_PROPERTIES (user_data);
+	g_return_if_fail (self->request_key != NULL);
+	seahorse_pkcs11_request_prompt (GTK_WINDOW (self), self->request_key);
 }
 
-
 static const GtkActionEntry UI_ACTIONS[] = {
 	{ "export-object", GTK_STOCK_SAVE_AS, N_("_Export"), "",
 	  N_("Export the certificate"), G_CALLBACK (on_export_certificate) },
 	{ "delete-object", GTK_STOCK_DELETE, N_("_Delete"), "<Ctrl>Delete",
 	  N_("Delete this certificate or key"), G_CALLBACK (on_delete_objects) },
-	{ "extra-action", NULL, N_("Extra _Action"), NULL,
-	  N_("An extra action on the certificate"), G_CALLBACK (on_extra_action) },
+	{ "request-certificate", NULL, N_("Request _Certificate"), NULL,
+	  N_("Create a certificate request file for this key"), G_CALLBACK (on_request_certificate) },
 };
 
 static void
@@ -264,17 +271,72 @@ on_ui_manager_add_widget (GtkUIManager *manager,
 	gtk_widget_show (widget);
 }
 
+typedef struct {
+	SeahorsePkcs11Properties *properties;
+	GckObject *private_key;
+} CapableClosure;
+
+static void
+on_certificate_request_capable (GObject *source,
+                                GAsyncResult *result,
+                                gpointer user_data)
+{
+	CapableClosure *closure = user_data;
+	SeahorsePkcs11Properties *self = closure->properties;
+	GError *error = NULL;
+	GtkAction *request;
+
+	if (gcr_certificate_request_capable_finish (result, &error)) {
+		request = gtk_action_group_get_action (self->actions, "request-certificate");
+		gtk_action_set_visible (request, TRUE);
+		g_clear_object (&self->request_key);
+		self->request_key = g_object_ref (closure->private_key);
+
+	} else if (error != NULL) {
+		g_message ("couldn't check capabilities of private key: %s", error->message);
+		g_clear_error (&error);
+	}
+
+	g_object_unref (closure->properties);
+	g_object_unref (closure->private_key);
+	g_slice_free (CapableClosure, closure);
+}
+
+static void
+check_certificate_request_capable (SeahorsePkcs11Properties *self,
+                                   GObject *object)
+{
+	CapableClosure *closure;
+
+	if (!SEAHORSE_IS_PRIVATE_KEY (object))
+		return;
+
+	closure = g_slice_new (CapableClosure);
+	closure->properties = g_object_ref (self);
+	closure->private_key = g_object_ref (object);
+
+	gcr_certificate_request_capable_async (closure->private_key,
+	                                       self->cancellable,
+	                                       on_certificate_request_capable,
+	                                       closure);
+}
+
 static void
 seahorse_pkcs11_properties_constructed (GObject *obj)
 {
 	SeahorsePkcs11Properties *self = SEAHORSE_PKCS11_PROPERTIES (obj);
 	GObject *partner = NULL;
 	GError *error = NULL;
+	GtkAction *request;
 
 	G_OBJECT_CLASS (seahorse_pkcs11_properties_parent_class)->constructed (obj);
 
 	self->actions = gtk_action_group_new ("Pkcs11Actions");
 	gtk_action_group_add_actions (self->actions, UI_ACTIONS, G_N_ELEMENTS (UI_ACTIONS), self);
+	gtk_action_group_set_translation_domain (self->actions, GETTEXT_PACKAGE);
+	request = gtk_action_group_get_action (self->actions, "request-certificate");
+	gtk_action_set_is_important (request, TRUE);
+	gtk_action_set_visible (request, FALSE);
 
 	self->ui_manager = gtk_ui_manager_new ();
 	gtk_ui_manager_insert_action_group (self->ui_manager, self->actions, 0);
@@ -294,10 +356,13 @@ seahorse_pkcs11_properties_constructed (GObject *obj)
 	on_object_label_changed (self->object, NULL, self);
 
 	add_renderer_for_object (self, self->object);
+	check_certificate_request_capable (self, self->object);
 
 	g_object_get (self->object, "partner", &partner, NULL);
 	if (partner != NULL) {
 		add_renderer_for_object (self, partner);
+		check_certificate_request_capable (self, partner);
+
 		g_object_unref (partner);
 	}
 
@@ -342,10 +407,22 @@ seahorse_pkcs11_properties_get_property (GObject *obj,
 }
 
 static void
+seahorse_pkcs11_properties_dispose (GObject *obj)
+{
+	SeahorsePkcs11Properties *self = SEAHORSE_PKCS11_PROPERTIES (obj);
+
+	g_cancellable_cancel (self->cancellable);
+
+	G_OBJECT_CLASS (seahorse_pkcs11_properties_parent_class)->dispose (obj);
+}
+
+static void
 seahorse_pkcs11_properties_finalize (GObject *obj)
 {
 	SeahorsePkcs11Properties *self = SEAHORSE_PKCS11_PROPERTIES (obj);
 
+	g_object_unref (self->cancellable);
+	g_clear_object (&self->request_key);
 	g_object_unref (self->actions);
 	g_object_unref (self->ui_manager);
 
@@ -369,6 +446,7 @@ seahorse_pkcs11_properties_class_init (SeahorsePkcs11PropertiesClass *klass)
 	gobject_class->constructed = seahorse_pkcs11_properties_constructed;
 	gobject_class->set_property = seahorse_pkcs11_properties_set_property;
 	gobject_class->get_property = seahorse_pkcs11_properties_get_property;
+	gobject_class->dispose = seahorse_pkcs11_properties_dispose;
 	gobject_class->finalize = seahorse_pkcs11_properties_finalize;
 
 	g_object_class_install_property (gobject_class, PROP_OBJECT,
diff --git a/pkcs11/seahorse-pkcs11-request.c b/pkcs11/seahorse-pkcs11-request.c
new file mode 100644
index 0000000..a333bf2
--- /dev/null
+++ b/pkcs11/seahorse-pkcs11-request.c
@@ -0,0 +1,379 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2008 Stefan Walter
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "seahorse-pkcs11-request.h"
+#include "seahorse-token.h"
+
+#include "seahorse-action.h"
+#include "seahorse-progress.h"
+#include "seahorse-interaction.h"
+#include "seahorse-registry.h"
+#include "seahorse-util.h"
+
+#include <glib/gi18n.h>
+
+#include <gcr/gcr.h>
+
+#include <gck/gck.h>
+#include <gck/pkcs11.h>
+
+GType   seahorse_pkcs11_request_get_type           (void) G_GNUC_CONST;
+
+#define SEAHORSE_TYPE_PKCS11_REQUEST               (seahorse_pkcs11_request_get_type ())
+#define SEAHORSE_PKCS11_REQUEST(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_PKCS11_REQUEST, SeahorsePkcs11Request))
+#define SEAHORSE_IS_PKCS11_REQUEST(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_PKCS11_REQUEST))
+#define SEAHORSE_PKCS11_REQUEST_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_PKCS11_REQUEST, SeahorsePkcs11RequestClass))
+#define SEAHORSE_IS_PKCS11_REQUEST_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_PKCS11_REQUEST))
+#define SEAHORSE_PKCS11_REQUEST_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_PKCS11_REQUEST, SeahorsePkcs11RequestClass))
+
+typedef struct _SeahorsePkcs11Request SeahorsePkcs11Request;
+typedef struct _SeahorsePkcs11RequestClass SeahorsePkcs11RequestClass;
+
+struct _SeahorsePkcs11Request {
+	GtkDialog dialog;
+
+	GtkEntry *name_entry;
+	GckObject *private_key;
+
+	guchar *encoded;
+	gsize n_encoded;
+};
+
+struct _SeahorsePkcs11RequestClass {
+	GtkDialogClass dialog_class;
+};
+
+enum {
+	PROP_0,
+	PROP_PRIVATE_KEY
+};
+
+G_DEFINE_TYPE (SeahorsePkcs11Request, seahorse_pkcs11_request, GTK_TYPE_DIALOG);
+
+enum {
+	MECHANISM_LABEL,
+	MECHANISM_TYPE,
+	MECHANISM_N_COLS
+};
+
+static void
+seahorse_pkcs11_request_init (SeahorsePkcs11Request *self)
+{
+
+}
+
+static void
+update_response (SeahorsePkcs11Request *self)
+{
+	const gchar *name = gtk_entry_get_text (self->name_entry);
+	gtk_dialog_set_response_sensitive (GTK_DIALOG (self), GTK_RESPONSE_OK, !g_str_equal (name, ""));
+}
+
+static void
+on_request_file_written (GObject *source,
+                         GAsyncResult *result,
+                         gpointer user_data)
+{
+	SeahorsePkcs11Request *self = SEAHORSE_PKCS11_REQUEST (user_data);
+	GError *error = NULL;
+	GtkWindow *parent;
+
+	parent = gtk_window_get_transient_for (GTK_WINDOW (self));
+	if (!g_file_replace_contents_finish (G_FILE (source), result, NULL, &error))
+		seahorse_util_handle_error (&error, parent, _("Couldn't save certificate request"));
+
+	g_object_unref (self);
+}
+
+static const gchar *BAD_FILENAME_CHARS = "/\\<>|?*";
+
+static void
+save_certificate_request (SeahorsePkcs11Request *self,
+                          GcrCertificateRequest *req,
+                          GtkWindow *parent)
+{
+	GtkFileChooser *chooser;
+	GtkFileFilter *pem_filter;
+	GtkFileFilter *der_filter;
+	GtkWidget *dialog;
+	gchar *filename;
+	gboolean textual;
+	gchar *label;
+	GFile *file;
+	gint response;
+
+	parent = gtk_window_get_transient_for (GTK_WINDOW (self));
+	dialog = gtk_file_chooser_dialog_new (_("Save certificate request"),
+	                                      parent, GTK_FILE_CHOOSER_ACTION_SAVE,
+	                                      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+	                                      GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+	                                      NULL);
+
+	chooser = GTK_FILE_CHOOSER (dialog);
+	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
+	gtk_file_chooser_set_local_only (chooser, FALSE);
+
+	der_filter = gtk_file_filter_new ();
+	gtk_file_filter_set_name (der_filter, _("Certificate request"));
+	gtk_file_filter_add_mime_type (der_filter, "application/pkcs10");
+	gtk_file_filter_add_pattern (der_filter, "*.p10");
+	gtk_file_filter_add_pattern (der_filter, "*.csr");
+	gtk_file_chooser_add_filter (chooser, der_filter);
+	gtk_file_chooser_set_filter (chooser, der_filter);
+
+	pem_filter = gtk_file_filter_new ();
+	gtk_file_filter_set_name (pem_filter, _("PEM encoded request"));
+	gtk_file_filter_add_mime_type (pem_filter, "application/pkcs10+pem");
+	gtk_file_filter_add_pattern (pem_filter, "*.pem");
+	gtk_file_chooser_add_filter (chooser, pem_filter);
+
+	label = NULL;
+	g_object_get (self->private_key, "label", &label, NULL);
+	if (!label || g_str_equal (label, ""))
+		label = g_strdup ("Certificate Request");
+	filename = g_strconcat (label, ".csr", NULL);
+	g_strdelimit (filename, BAD_FILENAME_CHARS, '_');
+	gtk_file_chooser_set_current_name (chooser, filename);
+	g_free (label);
+	g_free (filename);
+
+	gtk_file_chooser_set_do_overwrite_confirmation (chooser, TRUE);
+
+	response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+	if (response == GTK_RESPONSE_ACCEPT) {
+
+		g_free (self->encoded);
+		textual = gtk_file_chooser_get_filter (chooser) == pem_filter;
+		self->encoded = gcr_certificate_request_encode (req, textual, &self->n_encoded);
+		g_return_if_fail (self->encoded != NULL);
+
+		file = gtk_file_chooser_get_file (chooser);
+		g_file_replace_contents_async (file, (const gchar *)self->encoded,
+		                               self->n_encoded, NULL, FALSE,
+		                               G_FILE_CREATE_NONE, NULL,
+		                               on_request_file_written, g_object_ref (self));
+		g_object_unref (file);
+	}
+
+	gtk_widget_destroy (dialog);
+}
+
+static void
+complete_request (SeahorsePkcs11Request *self,
+                  GcrCertificateRequest *req,
+                  GError **error)
+{
+	GtkWindow *parent;
+
+	g_assert (error != NULL);
+
+	parent = gtk_window_get_transient_for (GTK_WINDOW (self));
+	if (*error != NULL)
+		seahorse_util_handle_error (error, parent, _("Couldn't create certificate request"));
+	else
+		save_certificate_request (self, req, parent);
+}
+
+static void
+on_request_complete (GObject *source,
+                     GAsyncResult *result,
+                     gpointer user_data)
+{
+	SeahorsePkcs11Request *self = SEAHORSE_PKCS11_REQUEST (user_data);
+	GcrCertificateRequest *req = GCR_CERTIFICATE_REQUEST (source);
+	GError *error = NULL;
+
+	gcr_certificate_request_complete_finish (req, result, &error);
+	complete_request (self, req, &error);
+
+	g_object_unref (self);
+}
+
+static void
+on_name_entry_changed (GtkEditable *editable,
+                       gpointer user_data)
+{
+	SeahorsePkcs11Request *self = SEAHORSE_PKCS11_REQUEST (user_data);
+	update_response (self);
+}
+
+static void
+seahorse_pkcs11_request_constructed (GObject *obj)
+{
+	SeahorsePkcs11Request *self = SEAHORSE_PKCS11_REQUEST (obj);
+	GtkBuilder *builder;
+	const gchar *path;
+	GError *error = NULL;
+	GtkWidget *content;
+	GtkWidget *widget;
+
+	G_OBJECT_CLASS (seahorse_pkcs11_request_parent_class)->constructed (obj);
+
+	builder = gtk_builder_new ();
+	path = SEAHORSE_UIDIR "seahorse-pkcs11-request.xml";
+	gtk_builder_add_from_file (builder, path, &error);
+	if (error != NULL) {
+		g_warning ("couldn't load ui file: %s", path);
+		g_clear_error (&error);
+		g_object_unref (builder);
+		return;
+	}
+
+	gtk_window_set_resizable (GTK_WINDOW (self), FALSE);
+	content = gtk_dialog_get_content_area (GTK_DIALOG (self));
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "pkcs11-request"));
+	gtk_container_add (GTK_CONTAINER (content), widget);
+	gtk_widget_show (widget);
+
+	self->name_entry = GTK_ENTRY (gtk_builder_get_object (builder, "request-name"));
+	g_signal_connect (self->name_entry, "changed", G_CALLBACK (on_name_entry_changed), self);
+
+	/* The buttons */
+	gtk_dialog_add_buttons (GTK_DIALOG (self),
+	                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+	                        _("Create"), GTK_RESPONSE_OK,
+	                        NULL);
+	gtk_dialog_set_default_response (GTK_DIALOG (self), GTK_RESPONSE_OK);
+
+	update_response (self);
+	g_object_unref (builder);
+
+	g_return_if_fail (GCK_IS_OBJECT (self->private_key));
+}
+
+static void
+seahorse_pkcs11_request_set_property (GObject *obj,
+                                      guint prop_id,
+                                      const GValue *value,
+                                      GParamSpec *pspec)
+{
+	SeahorsePkcs11Request *self = SEAHORSE_PKCS11_REQUEST (obj);
+
+	switch (prop_id) {
+	case PROP_PRIVATE_KEY:
+		g_return_if_fail (self->private_key == NULL);
+		self->private_key = g_value_dup_object (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+seahorse_pkcs11_request_get_property (GObject *obj,
+                                      guint prop_id,
+                                      GValue *value,
+                                      GParamSpec *pspec)
+{
+	SeahorsePkcs11Request *self = SEAHORSE_PKCS11_REQUEST (obj);
+
+	switch (prop_id) {
+	case PROP_PRIVATE_KEY:
+		g_value_set_object (value, self->private_key);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+seahorse_pkcs11_request_finalize (GObject *obj)
+{
+	SeahorsePkcs11Request *self = SEAHORSE_PKCS11_REQUEST (obj);
+
+	g_clear_object (&self->private_key);
+	g_free (self->encoded);
+
+	G_OBJECT_CLASS (seahorse_pkcs11_request_parent_class)->finalize (obj);
+}
+
+static void
+seahorse_pkcs11_request_response (GtkDialog *dialog,
+                                  gint response_id)
+{
+	SeahorsePkcs11Request *self = SEAHORSE_PKCS11_REQUEST (dialog);
+	GcrCertificateRequest *req;
+	GTlsInteraction *interaction;
+	GckSession *session;
+	GtkWindow *parent;
+
+	if (response_id == GTK_RESPONSE_OK) {
+		g_return_if_fail (self->private_key != NULL);
+
+		parent = gtk_window_get_transient_for (GTK_WINDOW (self));
+		interaction = seahorse_interaction_new (parent);
+		session = gck_object_get_session (self->private_key);
+		gck_session_set_interaction (session, interaction);
+		g_object_unref (interaction);
+		g_object_unref (session);
+
+		req = gcr_certificate_request_prepare (GCR_CERTIFICATE_REQUEST_PKCS10,
+		                                       self->private_key);
+		gcr_certificate_request_set_cn (req, gtk_entry_get_text (self->name_entry));
+		gcr_certificate_request_complete_async (req, NULL,
+		                                        on_request_complete, g_object_ref (self));
+	}
+
+	gtk_widget_hide (GTK_WIDGET (dialog));
+}
+
+static void
+seahorse_pkcs11_request_class_init (SeahorsePkcs11RequestClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (klass);
+
+	gobject_class->get_property = seahorse_pkcs11_request_get_property;
+	gobject_class->set_property = seahorse_pkcs11_request_set_property;
+	gobject_class->constructed = seahorse_pkcs11_request_constructed;
+	gobject_class->finalize = seahorse_pkcs11_request_finalize;
+
+	dialog_class->response = seahorse_pkcs11_request_response;
+
+	g_object_class_install_property (gobject_class, PROP_PRIVATE_KEY,
+	            g_param_spec_object ("private-key", "Private key", "Private key",
+	                                 GCK_TYPE_OBJECT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+}
+
+void
+seahorse_pkcs11_request_prompt (GtkWindow *parent,
+                                GckObject *private_key)
+{
+	GtkDialog *dialog;
+
+	g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
+
+	dialog = g_object_new (SEAHORSE_TYPE_PKCS11_REQUEST,
+	                       "transient-for", parent,
+	                       "private-key", private_key,
+	                       NULL);
+	g_object_ref_sink (dialog);
+
+	gtk_dialog_run (dialog);
+
+	g_object_unref (dialog);
+}
diff --git a/pkcs11/seahorse-pkcs11-request.h b/pkcs11/seahorse-pkcs11-request.h
new file mode 100644
index 0000000..d3eb2f2
--- /dev/null
+++ b/pkcs11/seahorse-pkcs11-request.h
@@ -0,0 +1,34 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Stef Walter <stef collabora co uk>
+ */
+
+#ifndef __SEAHORSE_PKCS11_REQUEST_H__
+#define __SEAHORSE_PKCS11_REQUEST_H__
+
+#include <gtk/gtk.h>
+
+#include <gck/gck.h>
+
+void         seahorse_pkcs11_request_prompt      (GtkWindow *parent,
+                                                  GckObject *private_key);
+
+#endif /* __SEAHORSE_PKCS11_REQUEST_H__ */
diff --git a/pkcs11/seahorse-pkcs11-request.xml b/pkcs11/seahorse-pkcs11-request.xml
new file mode 100644
index 0000000..d9fed6e
--- /dev/null
+++ b/pkcs11/seahorse-pkcs11-request.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <object class="GtkHBox" id="pkcs11-request">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="border_width">7</property>
+    <property name="spacing">12</property>
+    <child>
+      <object class="GtkImage" id="key-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">application-certificate</property>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkVBox" id="vbox1">
+        <property name="visible">True</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">Create a certificate request file.</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkGrid" id="grid2">
+            <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="label1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="tooltip_text" translatable="yes">The common name (CN) placed in the certificate request.</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">Name (CN):</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="request-name">
+                <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="left_attach">1</property>
+                <property name="top_attach">0</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+  </object>
+</interface>



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