[gnome-keyring] gcr: Complete the PKCS#11 import dialog
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-keyring] gcr: Complete the PKCS#11 import dialog
- Date: Wed, 5 Oct 2011 08:20:05 +0000 (UTC)
commit 502a03e5c9e4bd1e43bea46620a4004c9005f7ba
Author: Stef Walter <stefw collabora co uk>
Date: Tue Oct 4 12:55:21 2011 +0200
gcr: Complete the PKCS#11 import dialog
* Add GcrImportInteraction interface which importers
* Hookup between non-GUI importers and import interaction
isn't yet completely thought out.
gcr/Makefile.am | 8 +-
gcr/gcr-deprecated.h | 1 -
gcr/gcr-dialog-util.c | 182 ++++++++++++++
gcr/gcr-dialog-util.h | 42 ++++
gcr/gcr-gnupg-importer.c | 14 +-
gcr/gcr-import-button.c | 12 +
gcr/gcr-import-dialog.c | 459 -----------------------------------
gcr/gcr-import-dialog.h | 82 -------
gcr/gcr-import-dialog.ui | 128 ----------
gcr/gcr-import-interaction.c | 178 ++++++++++++++
gcr/gcr-import-interaction.h | 89 +++++++
gcr/gcr-importer.c | 54 ++++-
gcr/gcr-importer.h | 45 ++--
gcr/gcr-parser.c | 1 -
gcr/gcr-pkcs11-import-dialog.c | 350 ++++++++++++++++++++++++++
gcr/gcr-pkcs11-import-dialog.h | 62 +++++
gcr/gcr-pkcs11-import-dialog.ui | 251 +++++++++++++++++++
gcr/gcr-pkcs11-import-interaction.c | 240 ++++++++++++++++++
gcr/gcr-pkcs11-import-interaction.h | 45 ++++
gcr/gcr-pkcs11-importer.c | 184 +++++++++++----
gcr/gcr-pkcs11-importer.h | 14 +-
21 files changed, 1686 insertions(+), 755 deletions(-)
---
diff --git a/gcr/Makefile.am b/gcr/Makefile.am
index be21651..3584bda 100644
--- a/gcr/Makefile.am
+++ b/gcr/Makefile.am
@@ -7,7 +7,7 @@ SUBDIRS = . icons tests
uidir = $(datadir)/gcr- GCR_MAJOR@/ui/
ui_DATA = \
- gcr-import-dialog.ui \
+ gcr-pkcs11-import-dialog.ui \
gcr-unlock-options-widget.ui
# ------------------------------------------------------------------
@@ -22,6 +22,7 @@ HEADER_BASE_FILES = \
gcr-deprecated-base.h \
gcr-icons.h \
gcr-importer.h \
+ gcr-import-interaction.h \
gcr-library.h \
gcr-parser.h \
gcr-pkcs11-certificate.h \
@@ -107,6 +108,7 @@ libgcr_base_ GCR_MAJOR@_la_SOURCES = \
gcr-gnupg-util.c gcr-gnupg-util.h \
gcr-icons.c gcr-icons.h \
gcr-importer.c gcr-importer.h \
+ gcr-import-interaction.c gcr-import-interaction.h \
gcr-internal.h \
gcr-library.c gcr-library.h \
gcr-memory.c \
@@ -137,6 +139,7 @@ libgcr_ GCR_MAJOR@_la_SOURCES = \
gcr-collection-model.c gcr-collection-model.h \
gcr-combo-selector.c gcr-combo-selector.h \
gcr-debug.c gcr-debug.h \
+ gcr-dialog-util.c gcr-dialog-util.h \
gcr-display-scrolled.c gcr-display-scrolled.h \
gcr-display-view.c gcr-display-view.h \
gcr-failure-renderer.c gcr-failure-renderer.h \
@@ -144,7 +147,6 @@ libgcr_ GCR_MAJOR@_la_SOURCES = \
gcr-gnupg-renderer.c gcr-gnupg-renderer.h \
gcr-gnupg-records.c gcr-gnupg-records.h \
gcr-import-button.c gcr-import-button.h \
- gcr-import-dialog.c gcr-import-dialog.h \
gcr-key-renderer.c gcr-key-renderer.h \
gcr-key-widget.c gcr-key-widget.h \
gcr-list-selector.c gcr-list-selector.h gcr-list-selector-private.h \
@@ -152,6 +154,8 @@ libgcr_ GCR_MAJOR@_la_SOURCES = \
gcr-memory.c \
gcr-memory-icon.c gcr-memory-icon.h \
gcr-menu-button.c gcr-menu-button.h \
+ gcr-pkcs11-import-interaction.c gcr-pkcs11-import-interaction.h \
+ gcr-pkcs11-import-dialog.c gcr-pkcs11-import-dialog.h \
gcr-record.c gcr-record.h \
gcr-renderer.c gcr-renderer.h \
gcr-tree-selector.c gcr-tree-selector.h \
diff --git a/gcr/gcr-deprecated.h b/gcr/gcr-deprecated.h
index 9a21af7..3447c84 100644
--- a/gcr/gcr-deprecated.h
+++ b/gcr/gcr-deprecated.h
@@ -34,7 +34,6 @@
#include "gcr-certificate-basics-widget.h"
#include "gcr-certificate-details-widget.h"
-#include "gcr-importer.h"
#include "gcr-viewer.h"
G_BEGIN_DECLS
diff --git a/gcr/gcr-dialog-util.c b/gcr/gcr-dialog-util.c
new file mode 100644
index 0000000..c142c35
--- /dev/null
+++ b/gcr/gcr-dialog-util.c
@@ -0,0 +1,182 @@
+/*
+ * gnome-keyring
+ *
+ * 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 <stefw collabora co uk>
+ */
+
+#include "config.h"
+
+#include "gcr-dialog-util.h"
+
+#include <string.h>
+
+typedef struct {
+ GtkDialog *dialog;
+ gint response_id;
+ gboolean was_modal;
+ gboolean destroyed;
+ gulong response_sig;
+ gulong unmap_sig;
+ gulong delete_sig;
+ gulong destroy_sig;
+} DialogRunClosure;
+
+static void
+dialog_run_closure_free (gpointer data)
+{
+ DialogRunClosure *closure = data;
+ g_object_unref (closure->dialog);
+ g_assert (closure->response_sig == 0);
+ g_assert (closure->unmap_sig == 0);
+ g_assert (closure->delete_sig == 0);
+ g_assert (closure->destroy_sig == 0);
+ g_free (closure);
+}
+
+static void
+complete_async_result (GSimpleAsyncResult *res)
+{
+ DialogRunClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+
+ g_object_ref (res);
+
+ if (!closure->destroyed) {
+ if (!closure->was_modal)
+ gtk_window_set_modal (GTK_WINDOW (closure->dialog), FALSE);
+
+ g_signal_handler_disconnect (closure->dialog, closure->response_sig);
+ closure->response_sig = 0;
+ g_signal_handler_disconnect (closure->dialog, closure->unmap_sig);
+ closure->unmap_sig = 0;
+ g_signal_handler_disconnect (closure->dialog, closure->delete_sig);
+ closure->delete_sig = 0;
+ g_signal_handler_disconnect (closure->dialog, closure->destroy_sig);
+ closure->destroy_sig = 0;
+ }
+
+ g_simple_async_result_complete (res);
+ g_object_unref (res);
+}
+
+static void
+on_dialog_unmap (GtkDialog *dialog,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+
+ complete_async_result (res);
+}
+
+static void
+on_dialog_response (GtkDialog *dialog,
+ gint response_id,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ DialogRunClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+
+ closure->response_id = response_id;
+ complete_async_result (res);
+}
+
+static gint
+on_dialog_delete (GtkDialog *dialog,
+ GdkEventAny *event,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ complete_async_result (res);
+ return TRUE; /* Do not destroy */
+}
+
+static void
+on_dialog_destroy (GtkDialog *dialog,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ DialogRunClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+
+ /* complete will be called by run_unmap_handler */
+ closure->destroyed = TRUE;
+}
+
+void
+_gcr_dialog_util_run_async (GtkDialog *dialog,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+ DialogRunClosure *closure;
+
+ g_return_if_fail (GTK_IS_DIALOG (dialog));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ res = g_simple_async_result_new (G_OBJECT (dialog), callback, user_data,
+ _gcr_dialog_util_run_async);
+ closure = g_new0 (DialogRunClosure, 1);
+
+ closure->dialog = g_object_ref (dialog);
+ closure->response_id = GTK_RESPONSE_NONE;
+ closure->was_modal = gtk_window_get_modal (GTK_WINDOW (dialog));
+ if (!closure->was_modal)
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+
+ if (!gtk_widget_get_visible (GTK_WIDGET (dialog)))
+ gtk_widget_show (GTK_WIDGET (dialog));
+
+ g_simple_async_result_set_op_res_gpointer (res, closure, dialog_run_closure_free);
+
+ closure->response_sig = g_signal_connect_data (dialog, "response",
+ G_CALLBACK (on_dialog_response),
+ g_object_ref (res),
+ (GClosureNotify)g_object_unref, 0);
+
+ closure->unmap_sig = g_signal_connect_data (dialog, "unmap",
+ G_CALLBACK (on_dialog_unmap),
+ g_object_ref (res),
+ (GClosureNotify)g_object_unref, 0);
+
+ closure->delete_sig = g_signal_connect_data (dialog, "delete-event",
+ G_CALLBACK (on_dialog_delete),
+ g_object_ref (res),
+ (GClosureNotify)g_object_unref, 0);
+
+ closure->destroy_sig = g_signal_connect_data (dialog, "destroy",
+ G_CALLBACK (on_dialog_destroy),
+ g_object_ref (res),
+ (GClosureNotify)g_object_unref, 0);
+
+ g_object_unref (res);
+}
+
+
+gint
+_gcr_dialog_util_run_finish (GtkDialog *dialog,
+ GAsyncResult *result)
+{
+ DialogRunClosure *closure;
+
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (dialog),
+ _gcr_dialog_util_run_async), GTK_RESPONSE_NONE);
+
+ closure = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+ return closure->response_id;
+}
diff --git a/gcr/gcr-dialog-util.h b/gcr/gcr-dialog-util.h
new file mode 100644
index 0000000..4be48fd
--- /dev/null
+++ b/gcr/gcr-dialog-util.h
@@ -0,0 +1,42 @@
+/*
+ * gnome-keyring
+ *
+ * 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 <stefw collabora co uk>
+ */
+
+#ifndef GCR_DIALOG_UTIL_H
+#define GCR_DIALOG_UTIL_H
+
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+void _gcr_dialog_util_run_async (GtkDialog *dialog,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gint _gcr_dialog_util_run_finish (GtkDialog *dialog,
+ GAsyncResult *result);
+
+G_END_DECLS
+
+#endif /* __GCR_TOKEN_MANAGER_H__ */
diff --git a/gcr/gcr-gnupg-importer.c b/gcr/gcr-gnupg-importer.c
index d9563a2..db0fd39 100644
--- a/gcr/gcr-gnupg-importer.c
+++ b/gcr/gcr-gnupg-importer.c
@@ -34,12 +34,14 @@ enum {
PROP_LABEL,
PROP_ICON,
PROP_IMPORTED,
- PROP_DIRECTORY
+ PROP_DIRECTORY,
+ PROP_INTERACTION
};
struct _GcrGnupgImporterPrivate {
GcrGnupgProcess *process;
GMemoryInputStream *packets;
+ GTlsInteraction *interaction;
GArray *imported;
};
@@ -66,6 +68,7 @@ _gcr_gnupg_importer_dispose (GObject *obj)
g_object_run_dispose (G_OBJECT (self->pv->process));
g_clear_object (&self->pv->process);
g_clear_object (&self->pv->packets);
+ g_clear_object (&self->pv->interaction);
G_OBJECT_CLASS (_gcr_gnupg_importer_parent_class)->dispose (obj);
}
@@ -140,6 +143,10 @@ _gcr_gnupg_importer_set_property (GObject *obj,
_gcr_gnupg_process_set_input_stream (self->pv->process, G_INPUT_STREAM (self->pv->packets));
g_signal_connect (self->pv->process, "status-record", G_CALLBACK (on_process_status_record), self);
break;
+ case PROP_INTERACTION:
+ g_clear_object (&self->pv->interaction);
+ self->pv->interaction = g_value_dup_object (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
break;
@@ -167,6 +174,9 @@ _gcr_gnupg_importer_get_property (GObject *obj,
case PROP_DIRECTORY:
g_value_set_string (value, _gcr_gnupg_process_get_directory (self->pv->process));
break;
+ case PROP_INTERACTION:
+ g_value_set_object (value, self->pv->interaction);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
break;
@@ -190,6 +200,8 @@ _gcr_gnupg_importer_class_init (GcrGnupgImporterClass *klass)
g_object_class_override_property (gobject_class, PROP_ICON, "icon");
+ g_object_class_override_property (gobject_class, PROP_INTERACTION, "interaction");
+
g_object_class_install_property (gobject_class, PROP_IMPORTED,
g_param_spec_boxed ("imported", "Imported", "Fingerprints of imported keys",
G_TYPE_STRV, G_PARAM_READABLE));
diff --git a/gcr/gcr-import-button.c b/gcr/gcr-import-button.c
index 79c9f5b..f517d9e 100644
--- a/gcr/gcr-import-button.c
+++ b/gcr/gcr-import-button.c
@@ -27,6 +27,7 @@
#include "gcr-internal.h"
#include "gcr-marshal.h"
#include "gcr-parser.h"
+#include "gcr-pkcs11-import-interaction.h"
#include <glib/gi18n-lib.h>
@@ -300,12 +301,23 @@ static void
begin_import (GcrImportButton *self,
GcrImporter *importer)
{
+ GTlsInteraction *interaction;
+ GtkWindow *window;
+
g_return_if_fail (self->pv->importing == FALSE);
self->pv->importing = TRUE;
g_free (self->pv->imported);
self->pv->imported = NULL;
+ /* TODO: Hack. Need to figure out how to pair these up... */
+ if (g_strcmp0 (G_OBJECT_TYPE_NAME (importer), "GcrPkcs11Importer") == 0) {
+ window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self)));
+ interaction = _gcr_pkcs11_import_interaction_new (window);
+ gcr_importer_set_interaction (importer, interaction);
+ g_object_unref (interaction);
+ }
+
gcr_importer_import_async (importer,
self->pv->cancellable,
on_import_complete,
diff --git a/gcr/gcr-import-interaction.c b/gcr/gcr-import-interaction.c
new file mode 100644
index 0000000..aee2048
--- /dev/null
+++ b/gcr/gcr-import-interaction.c
@@ -0,0 +1,178 @@
+/*
+ * gnome-keyring
+ *
+ * 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 <stefw collabora co uk>
+ */
+
+#include "config.h"
+
+#include "gcr-import-interaction.h"
+
+/**
+ * SECTION:gcr-importer
+ * @title: GcrImporter
+ * @short_description: Import certificates and keys
+ *
+ * An interface which allows importing of certificates and keys. Each
+ * #GcrImporter is registered with a set of PKCS\#11 attributes to match
+ * stuff that it can import.
+ *
+ * An importer gets passed a #GcrParser and accesses the currently parsed
+ * item. To create a set of importers that can import the currently parsed
+ * item in a #GcrParser, use gcr_importer_create_for_parsed(). The list of
+ * importers returned has the parsed item queued for import.
+ *
+ * To queue additional items with a importer use gcr_importer_queue_for_parsed().
+ * In addition you can try and queue an additional item with a set of importers
+ * using the gcr_importer_queue_and_filter_for_parsed().
+ *
+ * To start the import use gcr_importer_import() or the async variants.
+ */
+
+/**
+ * GcrImporter:
+ *
+ * Imports certificates and keys
+ */
+
+/**
+ * GcrImporterIface:
+ * @parent: parent interface
+ * @create_for_parsed: implementation of gcr_importer_create_for_parsed(), required
+ * @queue_for_parsed: implementation of gcr_importer_queue_for_parsed(), required
+ * @import_sync: optional implemantionon of gcr_importer_import()
+ * @import_async: implementation of gcr_importer_import_async(), required
+ * @import_finish: implementation of gcr_importer_import_finish()
+ *
+ * Interface implemented for a #GcrImporter.
+ */
+
+typedef GcrImportInteractionIface GcrImportInteractionInterface;
+
+G_DEFINE_INTERFACE (GcrImportInteraction, gcr_import_interaction, G_TYPE_TLS_INTERACTION);
+
+static void
+gcr_import_interaction_default_init (GcrImportInteractionIface *iface)
+{
+ static volatile gsize initialized = 0;
+
+ if (g_once_init_enter (&initialized)) {
+
+ /**
+ * GcrImportInteraction:importer:
+ *
+ * The importer being imported to
+ */
+ g_object_interface_install_property (iface,
+ g_param_spec_object ("importer", "Importer", "The imported imported to",
+ GCR_TYPE_IMPORTER, G_PARAM_READWRITE));
+
+ g_once_init_leave (&initialized, 1);
+ }
+}
+
+/**
+ * gcr_import_interaction_get_importer:
+ * @interaction: the interaction
+ *
+ * Get the importer that's using this interaction.
+ *
+ * Returns: (transfer full):
+ */
+GcrImporter *
+gcr_import_interaction_get_importer (GcrImportInteraction *interaction)
+{
+ GcrImporter *importer = NULL;
+
+ g_return_val_if_fail (GCR_IS_IMPORT_INTERACTION (interaction), NULL);
+
+ g_object_get (interaction, "importer", &importer, NULL);
+
+ if (importer != NULL)
+ g_object_unref (importer);
+
+ return importer;
+}
+
+/**
+ * gcr_import_interaction_set_importer:
+ * @interaction: the interaction
+ * @importer: (allow-none): the importer or %NULL
+ *
+ * Set the importer that's using this interaction.
+ */
+void
+gcr_import_interaction_set_importer (GcrImportInteraction *interaction,
+ GcrImporter *importer)
+{
+ g_return_if_fail (GCR_IS_IMPORT_INTERACTION (interaction));
+ g_object_set (interaction, "importer", importer, NULL);
+}
+
+GTlsInteractionResult
+gcr_import_interaction_supplement (GcrImportInteraction *interaction,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GcrImportInteractionIface *iface;
+
+ g_return_val_if_fail (GCR_IS_IMPORT_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), G_TLS_INTERACTION_UNHANDLED);
+ g_return_val_if_fail (error == NULL || *error == NULL, G_TLS_INTERACTION_UNHANDLED);
+
+ iface = GCR_IMPORT_INTERACTION_GET_INTERFACE (interaction);
+ g_return_val_if_fail (iface->supplement != NULL, G_TLS_INTERACTION_UNHANDLED);
+
+ return (iface->supplement) (interaction, cancellable, error);
+}
+
+void
+gcr_import_interaction_supplement_async (GcrImportInteraction *interaction,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GcrImportInteractionIface *iface;
+
+ g_return_if_fail (GCR_IS_IMPORT_INTERACTION (interaction));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ iface = GCR_IMPORT_INTERACTION_GET_INTERFACE (interaction);
+ g_return_if_fail (iface->supplement != NULL);
+
+ (iface->supplement_async) (interaction, cancellable, callback, user_data);
+}
+
+GTlsInteractionResult
+gcr_import_interaction_supplement_finish (GcrImportInteraction *interaction,
+ GAsyncResult *result,
+ GError **error)
+{
+ GcrImportInteractionIface *iface;
+
+ g_return_val_if_fail (GCR_IS_IMPORT_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), G_TLS_INTERACTION_UNHANDLED);
+ g_return_val_if_fail (error == NULL || *error == NULL, G_TLS_INTERACTION_UNHANDLED);
+
+ iface = GCR_IMPORT_INTERACTION_GET_INTERFACE (interaction);
+ g_return_val_if_fail (iface->supplement != NULL, G_TLS_INTERACTION_UNHANDLED);
+
+ return (iface->supplement_finish) (interaction, result, error);
+}
diff --git a/gcr/gcr-import-interaction.h b/gcr/gcr-import-interaction.h
new file mode 100644
index 0000000..79f5970
--- /dev/null
+++ b/gcr/gcr-import-interaction.h
@@ -0,0 +1,89 @@
+/*
+ * gnome-keyring
+ *
+ * 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 <stefw collabora co uk>
+ */
+
+#if !defined (__GCR_INSIDE_HEADER__) && !defined (GCR_COMPILATION)
+#error "Only <gcr/gcr.h> or <gcr/gcr-base.h> can be included directly."
+#endif
+
+#ifndef __GCR_IMPORT_INTERACTION_H__
+#define __GCR_IMPORT_INTERACTION_H__
+
+#include "gcr-importer.h"
+
+#include <glib-object.h>
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GCR_TYPE_IMPORT_INTERACTION (gcr_import_interaction_get_type ())
+#define GCR_IMPORT_INTERACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_IMPORT_INTERACTION, GcrImportInteraction))
+#define GCR_IS_IMPORT_INTERACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_IMPORT_INTERACTION))
+#define GCR_IMPORT_INTERACTION_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GCR_TYPE_IMPORT_INTERACTION, GcrImportInteractionIface))
+
+typedef struct _GcrImportInteraction GcrImportInteraction;
+typedef struct _GcrImportInteractionIface GcrImportInteractionIface;
+
+struct _GcrImportInteractionIface {
+ GTypeInterface parent;
+
+ GTlsInteractionResult (*supplement) (GcrImportInteraction *interaction,
+ GCancellable *cancellable,
+ GError **error);
+
+ void (*supplement_async) (GcrImportInteraction *interaction,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+ GTlsInteractionResult (*supplement_finish) (GcrImportInteraction *interaction,
+ GAsyncResult *result,
+ GError **error);
+
+ /*< private >*/
+ gpointer reserved[6];
+};
+
+GType gcr_import_interaction_get_type (void);
+
+GcrImporter * gcr_import_interaction_get_importer (GcrImportInteraction *interaction);
+
+void gcr_import_interaction_set_importer (GcrImportInteraction *interaction,
+ GcrImporter *importer);
+
+GTlsInteractionResult gcr_import_interaction_supplement (GcrImportInteraction *interaction,
+ GCancellable *cancellable,
+ GError **error);
+
+void gcr_import_interaction_supplement_async (GcrImportInteraction *interaction,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GTlsInteractionResult gcr_import_interaction_supplement_finish (GcrImportInteraction *interaction,
+ GAsyncResult *result,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __GCR_IMPORT_INTERACTION_H__ */
diff --git a/gcr/gcr-importer.c b/gcr/gcr-importer.c
index d67a96f..cb57285 100644
--- a/gcr/gcr-importer.c
+++ b/gcr/gcr-importer.c
@@ -23,7 +23,7 @@
#include "config.h"
-#include "gcr-base.h"
+#include "gcr-deprecated-base.h"
#include "gcr-importer.h"
#include "gcr-internal.h"
#include "gcr-marshal.h"
@@ -74,7 +74,7 @@
typedef GcrImporterIface GcrImporterInterface;
-G_DEFINE_INTERFACE (GcrImporter, gcr_importer, 0);
+G_DEFINE_INTERFACE (GcrImporter, gcr_importer, G_TYPE_OBJECT);
typedef struct _GcrRegistered {
GckAttributes *attrs;
@@ -109,6 +109,16 @@ gcr_importer_default_init (GcrImporterIface *iface)
g_param_spec_object ("icon", "Icon", "The icon for the importer",
G_TYPE_ICON, G_PARAM_READABLE));
+ /**
+ * GcrImporter:interaction:
+ *
+ * The interaction for the importer.
+ */
+ g_object_interface_install_property (iface,
+ g_param_spec_object ("interaction", "Interaction",
+ "Interaction for prompts",
+ G_TYPE_TLS_INTERACTION, G_PARAM_READWRITE));
+
g_once_init_leave (&initialized, 1);
}
}
@@ -466,6 +476,46 @@ gcr_importer_import_finish (GcrImporter *importer,
}
/**
+ * gcr_importer_get_interaction:
+ * @importer: the importer
+ *
+ * Get the interaction used to prompt the user when needed by this
+ * importer.
+ *
+ * Returns: (transfer none) (allow-none): the interaction or %NULL
+ */
+GTlsInteraction *
+gcr_importer_get_interaction (GcrImporter *importer)
+{
+ GTlsInteraction *interaction = NULL;
+
+ g_return_val_if_fail (GCR_IS_IMPORTER (importer), NULL);
+
+ g_object_get (importer, "interaction", &interaction, NULL);
+
+ if (interaction != NULL)
+ g_object_unref (interaction);
+
+ return interaction;
+}
+
+/**
+ * gcr_importer_set_interaction:
+ * @importer: the importer
+ * @interaction: the interaction used by the importer
+ *
+ * Set the interaction used to prompt the user when needed by this
+ * importer.
+ */
+void
+gcr_importer_set_interaction (GcrImporter *importer,
+ GTlsInteraction *interaction)
+{
+ g_return_if_fail (GCR_IS_IMPORTER (importer));
+ g_object_set (importer, "interaction", interaction, NULL);
+}
+
+/**
* gcr_importer_register_well_known:
*
* Register built-in PKCS\#11 and GnuPG importers.
diff --git a/gcr/gcr-importer.h b/gcr/gcr-importer.h
index e93395e..d915940 100644
--- a/gcr/gcr-importer.h
+++ b/gcr/gcr-importer.h
@@ -32,6 +32,8 @@
#include <glib-object.h>
+#include <gio/gio.h>
+
G_BEGIN_DECLS
#define GCR_TYPE_IMPORTER (gcr_importer_get_type ())
@@ -67,33 +69,38 @@ struct _GcrImporterIface {
gpointer reserved[14];
};
-GType gcr_importer_get_type (void);
+GType gcr_importer_get_type (void);
+
+GList * gcr_importer_create_for_parsed (GcrParsed *parsed);
+
+gboolean gcr_importer_queue_for_parsed (GcrImporter *importer,
+ GcrParsed *parsed);
-GList * gcr_importer_create_for_parsed (GcrParsed *parsed);
+GList * gcr_importer_queue_and_filter_for_parsed (GList *importers,
+ GcrParsed *parsed);
-gboolean gcr_importer_queue_for_parsed (GcrImporter *importer,
- GcrParsed *parsed);
+gboolean gcr_importer_import (GcrImporter *importer,
+ GCancellable *cancellable,
+ GError **error);
-GList * gcr_importer_queue_and_filter_for_parsed (GList *importers,
- GcrParsed *parsed);
+void gcr_importer_import_async (GcrImporter *importer,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
-gboolean gcr_importer_import (GcrImporter *importer,
- GCancellable *cancellable,
- GError **error);
+gboolean gcr_importer_import_finish (GcrImporter *importer,
+ GAsyncResult *result,
+ GError **error);
-void gcr_importer_import_async (GcrImporter *importer,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
+GTlsInteraction * gcr_importer_get_interaction (GcrImporter *importer);
-gboolean gcr_importer_import_finish (GcrImporter *importer,
- GAsyncResult *result,
- GError **error);
+void gcr_importer_set_interaction (GcrImporter *importer,
+ GTlsInteraction *interaction);
-void gcr_importer_register (GType importer_type,
- GckAttributes *attrs);
+void gcr_importer_register (GType importer_type,
+ GckAttributes *attrs);
-void gcr_importer_register_well_known (void);
+void gcr_importer_register_well_known (void);
G_END_DECLS
diff --git a/gcr/gcr-parser.c b/gcr/gcr-parser.c
index 916f4a5..ad97a6b 100644
--- a/gcr/gcr-parser.c
+++ b/gcr/gcr-parser.c
@@ -24,7 +24,6 @@
#include "gck/gck.h"
#include "gcr-internal.h"
-#include "gcr-importer.h"
#include "gcr-marshal.h"
#include "gcr-oids.h"
#include "gcr-openpgp.h"
diff --git a/gcr/gcr-pkcs11-import-dialog.c b/gcr/gcr-pkcs11-import-dialog.c
new file mode 100644
index 0000000..dce5ae1
--- /dev/null
+++ b/gcr/gcr-pkcs11-import-dialog.c
@@ -0,0 +1,350 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2008 Stefan Walter
+ *
+ * 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 "gcr-dialog-util.h"
+#include "gcr-pkcs11-import-dialog.h"
+
+#include "egg/egg-entry-buffer.h"
+#include "egg/egg-secure-memory.h"
+
+#include <gtk/gtk.h>
+
+#include <glib/gi18n-lib.h>
+
+EGG_SECURE_DECLARE (import_dialog);
+
+#define GCR_PKCS11_IMPORT_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCR_TYPE_PKCS11_IMPORT_DIALOG, GcrPkcs11ImportDialogClass))
+#define GCR_IS_PKCS11_IMPORT_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCR_TYPE_PKCS11_IMPORT_DIALOG))
+#define GCR_PKCS11_IMPORT_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCR_TYPE_PKCS11_IMPORT_DIALOG, GcrPkcs11ImportDialogClass))
+
+enum {
+ PROP_0,
+ PROP_IMPORTER
+};
+
+struct _GcrPkcs11ImportDialog {
+ GtkDialog parent;
+ GcrImporter *importer;
+ GtkBuilder *builder;
+ GtkWidget *password_area;
+ GtkLabel *token_label;
+ GtkImage *token_image;
+ GtkEntry *password_entry;
+ GtkEntry *label_entry;
+ gboolean label_changed;
+};
+
+typedef struct _GcrPkcs11ImportDialogClass GcrPkcs11ImportDialogClass;
+
+struct _GcrPkcs11ImportDialogClass {
+ GtkDialogClass parent;
+};
+
+G_DEFINE_TYPE (GcrPkcs11ImportDialog, _gcr_pkcs11_import_dialog, GTK_TYPE_DIALOG);
+
+static void
+on_label_changed (GtkEditable *editable,
+ gpointer user_data)
+{
+ GcrPkcs11ImportDialog *self = GCR_PKCS11_IMPORT_DIALOG (user_data);
+ self->label_changed = TRUE;
+}
+
+static GList *
+pkcs11_importer_get_queued (GcrImporter *importer)
+{
+ GList *queued = NULL;
+
+ /* TODO: This is ugly */
+
+ g_object_get (importer, "queued", &queued, NULL);
+
+ return queued;
+}
+
+static void
+_gcr_pkcs11_import_dialog_constructed (GObject *obj)
+{
+ GcrPkcs11ImportDialog *self = GCR_PKCS11_IMPORT_DIALOG (obj);
+ GError *error = NULL;
+ GtkEntryBuffer *buffer;
+ GtkWidget *widget;
+ GtkBox *contents;
+ GList *queued, *l;
+ gchar *label = NULL;
+ gchar *value;
+
+ G_OBJECT_CLASS (_gcr_pkcs11_import_dialog_parent_class)->constructed (obj);
+
+ if (!gtk_builder_add_from_file (self->builder, UIDIR "gcr-pkcs11-import-dialog.ui", &error)) {
+ g_warning ("couldn't load ui builder file: %s", error->message);
+ return;
+ }
+
+ /* Fill in the dialog from builder */
+ widget = GTK_WIDGET (gtk_builder_get_object (self->builder, "pkcs11-import-dialog"));
+ contents = GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self)));
+ gtk_box_pack_start (contents, widget, TRUE, TRUE, 0);
+
+ /* The password area */
+ self->password_area = GTK_WIDGET (gtk_builder_get_object (self->builder, "unlock-area"));
+ gtk_widget_hide (self->password_area);
+
+ /* Add a secure entry */
+ buffer = egg_entry_buffer_new ();
+ self->password_entry = GTK_ENTRY (gtk_builder_get_object (self->builder, "password-entry"));
+ gtk_entry_set_buffer (self->password_entry, buffer);
+ gtk_entry_set_activates_default (self->password_entry, TRUE);
+ g_object_unref (buffer);
+
+ self->token_label = GTK_LABEL (gtk_builder_get_object (self->builder, "token-description"));
+ self->token_image = GTK_IMAGE (gtk_builder_get_object (self->builder, "token-image"));
+
+ /* Setup the label */
+ self->label_entry = GTK_ENTRY (gtk_builder_get_object (self->builder, "label-entry"));
+ g_signal_connect (self->label_entry, "changed", G_CALLBACK (on_label_changed), self);
+ gtk_entry_set_activates_default (self->label_entry, TRUE);
+
+ queued = pkcs11_importer_get_queued (self->importer);
+ for (l = queued; l != NULL; l = g_list_next (l)) {
+ if (!gck_attributes_find_string (l->data, CKA_LABEL, &value))
+ value = NULL;
+ if (l == queued) {
+ label = value;
+ value = NULL;
+ } else if (g_strcmp0 (label, value) != 0) {
+ g_free (label);
+ label = NULL;
+ }
+ g_free (value);
+ }
+ g_list_free (queued);
+
+ if (label == NULL)
+ gtk_entry_set_placeholder_text (self->label_entry, _("Automatically chosen"));
+ else
+ gtk_entry_set_text (self->label_entry, label);
+ g_free (label);
+
+ /* Add our various buttons */
+ gtk_dialog_add_button (GTK_DIALOG (self), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ gtk_dialog_add_button (GTK_DIALOG (self), GTK_STOCK_OK, GTK_RESPONSE_OK);
+ gtk_dialog_set_default_response (GTK_DIALOG (self), GTK_RESPONSE_OK);
+
+ gtk_window_set_modal (GTK_WINDOW (self), TRUE);
+}
+
+static void
+_gcr_pkcs11_import_dialog_init (GcrPkcs11ImportDialog *self)
+{
+ self->builder = gtk_builder_new ();
+}
+
+static void
+_gcr_pkcs11_import_dialog_finalize (GObject *obj)
+{
+ GcrPkcs11ImportDialog *self = GCR_PKCS11_IMPORT_DIALOG (obj);
+
+ g_object_unref (self->builder);
+ g_clear_object (&self->importer);
+
+ G_OBJECT_CLASS (_gcr_pkcs11_import_dialog_parent_class)->finalize (obj);
+}
+
+static void
+_gcr_pkcs11_import_dialog_set_property (GObject *obj,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GcrPkcs11ImportDialog *self = GCR_PKCS11_IMPORT_DIALOG (obj);
+
+ switch (prop_id) {
+ case PROP_IMPORTER:
+ g_return_if_fail (self->importer == NULL);
+ self->importer = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+_gcr_pkcs11_import_dialog_get_property (GObject *obj,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GcrPkcs11ImportDialog *self = GCR_PKCS11_IMPORT_DIALOG (obj);
+
+ switch (prop_id) {
+ case PROP_IMPORTER:
+ g_value_set_object (value, self->importer);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+_gcr_pkcs11_import_dialog_class_init (GcrPkcs11ImportDialogClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->constructed = _gcr_pkcs11_import_dialog_constructed;
+ gobject_class->finalize = _gcr_pkcs11_import_dialog_finalize;
+ gobject_class->set_property = _gcr_pkcs11_import_dialog_set_property;
+ gobject_class->get_property = _gcr_pkcs11_import_dialog_get_property;
+
+ g_object_class_install_property (gobject_class, PROP_IMPORTER,
+ g_param_spec_object ("importer", "Importer", "The PKCS#11 importer",
+ GCR_TYPE_IMPORTER,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+GcrPkcs11ImportDialog *
+_gcr_pkcs11_import_dialog_new (GcrImporter *importer,
+ GtkWindow *parent)
+{
+ GcrPkcs11ImportDialog *dialog;
+
+ g_return_val_if_fail (GCR_IS_IMPORTER (importer), NULL);
+ g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), NULL);
+
+ dialog = g_object_new (GCR_TYPE_PKCS11_IMPORT_DIALOG,
+ "importer", importer,
+ "transient-for", parent,
+ NULL);
+
+ return g_object_ref_sink (dialog);
+}
+
+static void
+update_importer_labels (GcrPkcs11ImportDialog *self)
+{
+ const gchar *label;
+ GList *queued, *l;
+
+ label = gtk_entry_get_text (self->label_entry);
+ if (self->label_changed && label != NULL && label[0]) {
+ queued = pkcs11_importer_get_queued (self->importer);
+ for (l = queued; l != NULL; l = g_list_next (l))
+ gck_attributes_set_string (l->data, CKA_LABEL, label);
+ g_list_free (queued);
+ }
+}
+
+gboolean
+_gcr_pkcs11_import_dialog_run (GcrPkcs11ImportDialog *self)
+{
+ gboolean ret = FALSE;
+
+ g_return_val_if_fail (GCR_IS_PKCS11_IMPORT_DIALOG (self), FALSE);
+
+ if (gtk_dialog_run (GTK_DIALOG (self)) == GTK_RESPONSE_OK) {
+ update_importer_labels (self);
+ ret = TRUE;
+ }
+
+ gtk_widget_hide (GTK_WIDGET (self));
+
+ return ret;
+}
+
+void
+_gcr_pkcs11_import_dialog_run_async (GcrPkcs11ImportDialog *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (GCR_IS_PKCS11_IMPORT_DIALOG (self));
+
+ _gcr_dialog_util_run_async (GTK_DIALOG (self), cancellable, callback, user_data);
+}
+
+gboolean
+_gcr_pkcs11_import_dialog_run_finish (GcrPkcs11ImportDialog *self,
+ GAsyncResult *result)
+{
+ gint response;
+
+ g_return_val_if_fail (GCR_IS_PKCS11_IMPORT_DIALOG (self), FALSE);
+
+ response = _gcr_dialog_util_run_finish (GTK_DIALOG (self), result);
+
+ gtk_widget_hide (GTK_WIDGET (self));
+
+ if (response == GTK_RESPONSE_OK) {
+ update_importer_labels (self);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+GTlsInteractionResult
+_gcr_pkcs11_import_dialog_run_ask_password (GcrPkcs11ImportDialog *self,
+ GTlsPassword *password,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GckTokenInfo *token_info;
+ const gchar *value;
+ GckSlot *slot;
+ GIcon *icon;
+ gboolean ret;
+
+ g_return_val_if_fail (GCR_IS_PKCS11_IMPORT_DIALOG (self), G_TLS_INTERACTION_UNHANDLED);
+ g_return_val_if_fail (G_IS_TLS_PASSWORD (password), G_TLS_INTERACTION_UNHANDLED);
+ g_return_val_if_fail (error == NULL || *error == NULL, G_TLS_INTERACTION_UNHANDLED);
+
+ if (GCK_IS_PASSWORD (password)) {
+ slot = gck_password_get_token (GCK_PASSWORD (password));
+ token_info = gck_slot_get_token_info (slot);
+ icon = gcr_icon_for_token (token_info);
+ gtk_image_set_from_gicon (self->token_image, icon, GTK_ICON_SIZE_BUTTON);
+ gck_token_info_free (token_info);
+ g_object_unref (icon);
+ }
+
+ gtk_label_set_text (self->token_label, g_tls_password_get_description (password));
+
+ gtk_widget_show (self->password_area);
+
+ ret = _gcr_pkcs11_import_dialog_run (self);
+
+ gtk_widget_hide (self->password_area);
+
+ if (!ret) {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
+ _("The user cancelled the operation"));
+ return G_TLS_INTERACTION_FAILED;
+ }
+
+ value = gtk_entry_get_text (self->password_entry);
+ g_tls_password_set_value_full (password, egg_secure_strdup (value),
+ -1, egg_secure_free);
+ return G_TLS_INTERACTION_HANDLED;
+}
diff --git a/gcr/gcr-pkcs11-import-dialog.h b/gcr/gcr-pkcs11-import-dialog.h
new file mode 100644
index 0000000..7c20769
--- /dev/null
+++ b/gcr/gcr-pkcs11-import-dialog.h
@@ -0,0 +1,62 @@
+/*
+ * gnome-keyring
+ *
+ * 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.
+ *
+ * Author: Stef Walter <stefw collabora co uk>
+ */
+
+#ifndef __GCR_PKCS11_IMPORT_DIALOG_H__
+#define __GCR_PKCS11_IMPORT_DIALOG_H__
+
+#include "gcr.h"
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GCR_TYPE_PKCS11_IMPORT_DIALOG (_gcr_pkcs11_import_dialog_get_type ())
+#define GCR_PKCS11_IMPORT_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_PKCS11_IMPORT_DIALOG, GcrPkcs11ImportDialog))
+#define GCR_IS_PKCS11_IMPORT_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_PKCS11_IMPORT_DIALOG))
+
+typedef struct _GcrPkcs11ImportDialog GcrPkcs11ImportDialog;
+
+GType _gcr_pkcs11_import_dialog_get_type (void) G_GNUC_CONST;
+
+GcrPkcs11ImportDialog * _gcr_pkcs11_import_dialog_new (GcrImporter *importer,
+ GtkWindow *parent);
+
+gboolean _gcr_pkcs11_import_dialog_run (GcrPkcs11ImportDialog *self);
+
+void _gcr_pkcs11_import_dialog_run_async (GcrPkcs11ImportDialog *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean _gcr_pkcs11_import_dialog_run_finish (GcrPkcs11ImportDialog *self,
+ GAsyncResult *result);
+
+GTlsInteractionResult _gcr_pkcs11_import_dialog_run_ask_password (GcrPkcs11ImportDialog *self,
+ GTlsPassword *password,
+ GCancellable *cancellable,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __GCR_PKCS11_IMPORT_DIALOG_H__ */
diff --git a/gcr/gcr-pkcs11-import-dialog.ui b/gcr/gcr-pkcs11-import-dialog.ui
new file mode 100644
index 0000000..a565cf1
--- /dev/null
+++ b/gcr/gcr-pkcs11-import-dialog.ui
@@ -0,0 +1,251 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 2.12 -->
+ <object class="GtkVBox" id="pkcs11-import-dialog">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkFrame" id="unlock-area">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="password-description">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">In order to import, please enter the password.</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</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="GtkEntry" id="password-entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">â</property>
+ <property name="visibility">False</property>
+ <property name="width_chars">20</property>
+ <property name="invisible_char_set">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="password-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Password:</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="token-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Token:</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="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkImage" id="token-image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-missing-image</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="token-description">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Label</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </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>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes"><b>Unlock</b></property>
+ <property name="use_markup">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="GtkFrame" id="settings-area">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkGrid" id="grid1">
+ <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="label-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Label:</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="label-entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">â</property>
+ <property name="width_chars">20</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>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_bottom">6</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes"><b>Import settings</b></property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <object class="GtkSizeGroup" id="entry-size-group">
+ <property name="mode">GTK_SIZE_GROUP_HORIZONTAL</property>
+ <widgets>
+ <widget name="password-label"/>
+ <widget name="token-label"/>
+ <widget name="label-label"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/gcr/gcr-pkcs11-import-interaction.c b/gcr/gcr-pkcs11-import-interaction.c
new file mode 100644
index 0000000..3be7c94
--- /dev/null
+++ b/gcr/gcr-pkcs11-import-interaction.c
@@ -0,0 +1,240 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2008 Stefan Walter
+ *
+ * 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 "gcr-dialog-util.h"
+#include "gcr-import-interaction.h"
+#include "gcr-pkcs11-import-interaction.h"
+
+#include <glib/gi18n-lib.h>
+
+#define GCR_PKCS11_IMPORT_INTERACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCR_TYPE_PKCS11_IMPORT_INTERACTION, GcrPkcs11ImportInteractionClass))
+#define GCR_IS_PKCS11_IMPORT_INTERACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCR_TYPE_PKCS11_IMPORT_INTERACTION))
+#define GCR_PKCS11_IMPORT_INTERACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCR_TYPE_PKCS11_IMPORT_INTERACTION, GcrPkcs11ImportInteractionClass))
+
+enum {
+ PROP_0,
+ PROP_IMPORTER,
+ PROP_PARENT_WINDOW
+};
+
+typedef struct _GcrPkcs11ImportInteractionClass GcrPkcs11ImportInteractionClass;
+
+struct _GcrPkcs11ImportInteraction {
+ GTlsInteraction parent;
+ GcrImporter *importer;
+ gboolean dialog_shown;
+ GtkWindow *parent_window;
+ GcrPkcs11ImportDialog *dialog;
+};
+
+struct _GcrPkcs11ImportInteractionClass {
+ GTlsInteractionClass parent_class;
+};
+
+static void _gcr_pkcs11_import_interaction_iface_init (GcrImportInteractionIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE(GcrPkcs11ImportInteraction, _gcr_pkcs11_import_interaction, G_TYPE_TLS_INTERACTION,
+ G_IMPLEMENT_INTERFACE (GCR_TYPE_IMPORT_INTERACTION, _gcr_pkcs11_import_interaction_iface_init));
+
+static void
+_gcr_pkcs11_import_interaction_init (GcrPkcs11ImportInteraction *self)
+{
+
+}
+
+static void
+_gcr_pkcs11_import_interaction_dispose (GObject *obj)
+{
+ GcrPkcs11ImportInteraction *self = GCR_PKCS11_IMPORT_INTERACTION (obj);
+
+ g_clear_object (&self->dialog);
+
+ G_OBJECT_CLASS (_gcr_pkcs11_import_interaction_parent_class)->dispose (obj);
+}
+
+static void
+_gcr_pkcs11_import_interaction_set_property (GObject *obj,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GcrPkcs11ImportInteraction *self = GCR_PKCS11_IMPORT_INTERACTION (obj);
+
+ switch (prop_id) {
+ case PROP_IMPORTER:
+ g_clear_object (&self->dialog);
+ g_clear_object (&self->importer);
+ self->importer = g_value_dup_object (value);
+ self->dialog_shown = FALSE;
+ if (self->importer != NULL)
+ self->dialog = _gcr_pkcs11_import_dialog_new (self->importer, self->parent_window);
+ break;
+ case PROP_PARENT_WINDOW:
+ g_clear_object (&self->parent_window);
+ self->parent_window = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+_gcr_pkcs11_import_interaction_get_property (GObject *obj,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GcrPkcs11ImportInteraction *self = GCR_PKCS11_IMPORT_INTERACTION (obj);
+
+ switch (prop_id) {
+ case PROP_IMPORTER:
+ g_value_set_object (value, self->importer);
+ break;
+ case PROP_PARENT_WINDOW:
+ g_value_set_object (value, self->parent_window);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static GTlsInteractionResult
+_gcr_pkcs11_import_interaction_ask_password (GTlsInteraction *interaction,
+ GTlsPassword *password,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GcrPkcs11ImportInteraction *self = GCR_PKCS11_IMPORT_INTERACTION (interaction);
+
+ g_return_val_if_fail (self->dialog != NULL, G_TLS_INTERACTION_UNHANDLED);
+
+ self->dialog_shown = TRUE;
+ return _gcr_pkcs11_import_dialog_run_ask_password (self->dialog, password, cancellable, error);
+}
+
+static GTlsInteractionResult
+_gcr_pkcs11_import_interaction_supplement (GcrImportInteraction *interaction,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GcrPkcs11ImportInteraction *self = GCR_PKCS11_IMPORT_INTERACTION (interaction);
+
+ g_return_val_if_fail (self->dialog != NULL, G_TLS_INTERACTION_UNHANDLED);
+
+ if (self->dialog_shown)
+ return G_TLS_INTERACTION_HANDLED;
+
+ self->dialog_shown = TRUE;
+ if (_gcr_pkcs11_import_dialog_run (self->dialog)) {
+ return G_TLS_INTERACTION_HANDLED;
+
+ } else {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED, _("The user cancelled the operation"));
+ return G_TLS_INTERACTION_FAILED;
+ }
+}
+
+static void
+_gcr_pkcs11_import_interaction_supplement_async (GcrImportInteraction *interaction,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GcrPkcs11ImportInteraction *self = GCR_PKCS11_IMPORT_INTERACTION (interaction);
+ GSimpleAsyncResult *res;
+
+ g_return_if_fail (self->dialog != NULL);
+
+ /* If dialog was already shown, then short circuit */
+ if (self->dialog_shown) {
+ res = g_simple_async_result_new (G_OBJECT (interaction), callback, user_data,
+ _gcr_pkcs11_import_interaction_supplement_async);
+ g_simple_async_result_complete_in_idle (res);
+ g_object_unref (res);
+
+ } else {
+ self->dialog_shown = TRUE;
+ _gcr_pkcs11_import_dialog_run_async (self->dialog, cancellable, callback, user_data);
+ }
+}
+
+static GTlsInteractionResult
+_gcr_pkcs11_import_interaction_supplement_finish (GcrImportInteraction *interaction,
+ GAsyncResult *result,
+ GError **error)
+{
+ GcrPkcs11ImportInteraction *self = GCR_PKCS11_IMPORT_INTERACTION (interaction);
+
+ g_return_val_if_fail (self->dialog != NULL, G_TLS_INTERACTION_UNHANDLED);
+
+ /* If it was short circuited without a dialog */
+ if (g_simple_async_result_is_valid (result, G_OBJECT (interaction),
+ _gcr_pkcs11_import_interaction_supplement_async)) {
+ return G_TLS_INTERACTION_HANDLED;
+
+ } else if (_gcr_pkcs11_import_dialog_run_finish (self->dialog, result)) {
+ return G_TLS_INTERACTION_HANDLED;
+
+ } else {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED, _("The user cancelled the operation"));
+ return G_TLS_INTERACTION_FAILED;
+ }
+}
+
+static void
+_gcr_pkcs11_import_interaction_iface_init (GcrImportInteractionIface *iface)
+{
+ iface->supplement = _gcr_pkcs11_import_interaction_supplement;
+ iface->supplement_async = _gcr_pkcs11_import_interaction_supplement_async;
+ iface->supplement_finish = _gcr_pkcs11_import_interaction_supplement_finish;
+}
+
+static void
+_gcr_pkcs11_import_interaction_class_init (GcrPkcs11ImportInteractionClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GTlsInteractionClass *interaction_class = G_TLS_INTERACTION_CLASS (klass);
+
+ gobject_class->dispose = _gcr_pkcs11_import_interaction_dispose;
+ gobject_class->set_property = _gcr_pkcs11_import_interaction_set_property;
+ gobject_class->get_property = _gcr_pkcs11_import_interaction_get_property;
+
+ interaction_class->ask_password = _gcr_pkcs11_import_interaction_ask_password;
+
+ g_object_class_override_property (gobject_class, PROP_IMPORTER, "importer");
+
+ g_object_class_install_property (gobject_class, PROP_PARENT_WINDOW,
+ g_param_spec_object ("parent-window", "Parent Window", "Prompt Parent Window",
+ GTK_TYPE_WINDOW, G_PARAM_READWRITE));
+}
+
+GTlsInteraction *
+_gcr_pkcs11_import_interaction_new (GtkWindow *parent_window)
+{
+ g_return_val_if_fail (parent_window == NULL || GTK_IS_WINDOW (parent_window), NULL);
+ return g_object_new (GCR_TYPE_PKCS11_IMPORT_INTERACTION,
+ "parent-window", parent_window,
+ NULL);
+}
diff --git a/gcr/gcr-pkcs11-import-interaction.h b/gcr/gcr-pkcs11-import-interaction.h
new file mode 100644
index 0000000..97027ba
--- /dev/null
+++ b/gcr/gcr-pkcs11-import-interaction.h
@@ -0,0 +1,45 @@
+/*
+ * gnome-keyring
+ *
+ * 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 <stefw collabora co uk>
+ */
+
+#ifndef __GCR_PKCS11_IMPORT_INTERACTION_H__
+#define __GCR_PKCS11_IMPORT_INTERACTION_H__
+
+#include "gcr.h"
+
+#include "gcr-pkcs11-import-dialog.h"
+
+G_BEGIN_DECLS
+
+#define GCR_TYPE_PKCS11_IMPORT_INTERACTION (_gcr_pkcs11_import_interaction_get_type ())
+#define GCR_PKCS11_IMPORT_INTERACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_PKCS11_IMPORT_INTERACTION, GcrPkcs11ImportInteraction))
+#define GCR_IS_PKCS11_IMPORT_INTERACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_PKCS11_IMPORT_INTERACTION))
+
+typedef struct _GcrPkcs11ImportInteraction GcrPkcs11ImportInteraction;
+
+GType _gcr_pkcs11_import_interaction_get_type (void) G_GNUC_CONST;
+
+GTlsInteraction * _gcr_pkcs11_import_interaction_new (GtkWindow *parent_window);
+
+G_END_DECLS
+
+#endif /* __GCR_PKCS11_IMPORT_INTERACTION_H__ */
diff --git a/gcr/gcr-pkcs11-importer.c b/gcr/gcr-pkcs11-importer.c
index feb012c..b22b4d7 100644
--- a/gcr/gcr-pkcs11-importer.c
+++ b/gcr/gcr-pkcs11-importer.c
@@ -27,6 +27,7 @@
#include "gcr-base.h"
#include "gcr-internal.h"
#include "gcr-library.h"
+#include "gcr-import-interaction.h"
#include "gcr-internal.h"
#include "gcr-parser.h"
#include "gcr-pkcs11-importer.h"
@@ -39,18 +40,28 @@ enum {
PROP_0,
PROP_LABEL,
PROP_ICON,
+ PROP_INTERACTION,
PROP_SLOT,
- PROP_IMPORTED
+ PROP_IMPORTED,
+ PROP_QUEUED
};
-struct _GcrPkcs11ImporterPrivate {
+typedef struct _GcrPkcs11ImporterClass GcrPkcs11ImporterClass;
+
+struct _GcrPkcs11Importer {
+ GObject parent;
GckSlot *slot;
GList *objects;
GckSession *session;
GQueue queue;
+ GTlsInteraction *interaction;
gboolean any_private;
};
+struct _GcrPkcs11ImporterClass {
+ GObjectClass parent_class;
+};
+
typedef struct {
GcrPkcs11Importer *importer;
GCancellable *cancellable;
@@ -68,6 +79,9 @@ static void state_complete (GSimpleAsyncResult *res,
static void state_create_object (GSimpleAsyncResult *res,
gboolean async);
+static void state_supplement (GSimpleAsyncResult *res,
+ gboolean async);
+
static void state_open_session (GSimpleAsyncResult *res,
gboolean async);
@@ -111,6 +125,13 @@ static void
state_complete (GSimpleAsyncResult *res,
gboolean async)
{
+ GcrImporterData *data = g_simple_async_result_get_op_res_gpointer (res);
+ GcrPkcs11Importer *self = data->importer;
+
+ /* Disconnect from the interaction */
+ if (data->importer->interaction && GCR_IS_IMPORT_INTERACTION (self->interaction))
+ gcr_import_interaction_set_importer (GCR_IMPORT_INTERACTION (self->interaction), NULL);
+
g_simple_async_result_complete (res);
}
@@ -146,7 +167,7 @@ complete_create_object (GSimpleAsyncResult *res,
next_state (res, state_complete);
} else {
- self->pv->objects = g_list_append (self->pv->objects, object);
+ self->objects = g_list_append (self->objects, object);
next_state (res, state_create_object);
}
}
@@ -176,23 +197,23 @@ state_create_object (GSimpleAsyncResult *res,
GError *error = NULL;
/* No more objects */
- if (g_queue_is_empty (&self->pv->queue)) {
+ if (g_queue_is_empty (&self->queue)) {
next_state (res, state_complete);
} else {
/* Pop first one off the list */
- attrs = g_queue_pop_head (&self->pv->queue);
+ attrs = g_queue_pop_head (&self->queue);
g_assert (attrs != NULL);
gck_attributes_add_boolean (attrs, CKA_TOKEN, CK_TRUE);
if (async) {
- gck_session_create_object_async (self->pv->session, attrs,
+ gck_session_create_object_async (self->session, attrs,
data->cancellable, on_create_object,
g_object_ref (res));
} else {
- object = gck_session_create_object (self->pv->session, attrs,
+ object = gck_session_create_object (self->session, attrs,
data->cancellable, &error);
complete_create_object (res, object, error);
}
@@ -202,6 +223,61 @@ state_create_object (GSimpleAsyncResult *res,
}
/* ---------------------------------------------------------------------------------
+ * PROMPTING
+ */
+
+static void
+complete_supplement (GSimpleAsyncResult *res,
+ GError *error)
+{
+ if (error == NULL) {
+ next_state (res, state_create_object);
+ } else {
+ g_simple_async_result_take_error (res, error);
+ next_state (res, state_complete);
+ }
+}
+
+static void
+on_supplement_done (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ GcrImporterData *data = g_simple_async_result_get_op_res_gpointer (res);
+ GcrPkcs11Importer *self = data->importer;
+ GError *error = NULL;
+
+ gcr_import_interaction_supplement_finish (GCR_IMPORT_INTERACTION (self->interaction),
+ result, &error);
+ complete_supplement (res, error);
+ g_object_unref (res);
+}
+
+static void
+state_supplement (GSimpleAsyncResult *res,
+ gboolean async)
+{
+ GcrImporterData *data = g_simple_async_result_get_op_res_gpointer (res);
+ GcrPkcs11Importer *self = data->importer;
+ GError *error = NULL;
+
+ if (self->interaction == NULL || !GCR_IS_IMPORT_INTERACTION (self->interaction)) {
+ complete_supplement (res, NULL);
+
+ } else if (async) {
+ gcr_import_interaction_supplement_async (GCR_IMPORT_INTERACTION (self->interaction),
+ data->cancellable, on_supplement_done,
+ g_object_ref (res));
+
+ } else {
+ gcr_import_interaction_supplement (GCR_IMPORT_INTERACTION (self->interaction),
+ data->cancellable, &error);
+ complete_supplement (res, error);
+ }
+}
+
+/* ---------------------------------------------------------------------------------
* OPEN SESSION
*/
@@ -218,9 +294,9 @@ complete_open_session (GSimpleAsyncResult *res,
next_state (res, state_complete);
} else {
- g_clear_object (&self->pv->session);
- self->pv->session = session;
- next_state (res, state_create_object);
+ g_clear_object (&self->session);
+ self->session = session;
+ next_state (res, state_supplement);
}
}
@@ -244,19 +320,16 @@ state_open_session (GSimpleAsyncResult *res,
{
GcrImporterData *data = g_simple_async_result_get_op_res_gpointer (res);
GcrPkcs11Importer *self = data->importer;
- guint options = GCK_SESSION_READ_WRITE;
+ guint options = GCK_SESSION_READ_WRITE | GCK_SESSION_LOGIN_USER;
GckSession *session;
GError *error = NULL;
- if (self->pv->any_private)
- options |= GCK_SESSION_LOGIN_USER;
-
if (async) {
- gck_slot_open_session_async (self->pv->slot, options,
+ gck_slot_open_session_async (self->slot, options,
data->cancellable, on_open_session,
g_object_ref (res));
} else {
- session = gck_slot_open_session_full (self->pv->slot, options, 0,
+ session = gck_slot_open_session_full (self->slot, options, 0,
NULL, NULL, data->cancellable, &error);
complete_open_session (res, session, error);
}
@@ -265,8 +338,7 @@ state_open_session (GSimpleAsyncResult *res,
static void
_gcr_pkcs11_importer_init (GcrPkcs11Importer *self)
{
- self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_PKCS11_IMPORTER, GcrPkcs11ImporterPrivate);
- g_queue_init (&self->pv->queue);
+ g_queue_init (&self->queue);
}
static void
@@ -274,12 +346,13 @@ _gcr_pkcs11_importer_dispose (GObject *obj)
{
GcrPkcs11Importer *self = GCR_PKCS11_IMPORTER (obj);
- gck_list_unref_free (self->pv->objects);
- self->pv->objects = NULL;
- g_clear_object (&self->pv->session);
+ gck_list_unref_free (self->objects);
+ self->objects = NULL;
+ g_clear_object (&self->session);
+ g_clear_object (&self->interaction);
- while (!g_queue_is_empty (&self->pv->queue))
- gck_attributes_unref (g_queue_pop_head (&self->pv->queue));
+ while (!g_queue_is_empty (&self->queue))
+ gck_attributes_unref (g_queue_pop_head (&self->queue));
G_OBJECT_CLASS (_gcr_pkcs11_importer_parent_class)->dispose (obj);
}
@@ -289,7 +362,7 @@ _gcr_pkcs11_importer_finalize (GObject *obj)
{
GcrPkcs11Importer *self = GCR_PKCS11_IMPORTER (obj);
- g_clear_object (&self->pv->slot);
+ g_clear_object (&self->slot);
G_OBJECT_CLASS (_gcr_pkcs11_importer_parent_class)->finalize (obj);
}
@@ -304,8 +377,13 @@ _gcr_pkcs11_importer_set_property (GObject *obj,
switch (prop_id) {
case PROP_SLOT:
- self->pv->slot = g_value_dup_object (value);
- g_return_if_fail (self->pv->slot);
+ self->slot = g_value_dup_object (value);
+ g_return_if_fail (self->slot);
+ break;
+ case PROP_INTERACTION:
+ g_clear_object (&self->interaction);
+ self->interaction = g_value_dup_object (value);
+ g_object_notify (G_OBJECT (self), "interaction");
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
@@ -319,7 +397,7 @@ calculate_label (GcrPkcs11Importer *self)
GckTokenInfo *info;
gchar *result;
- info = gck_slot_get_token_info (self->pv->slot);
+ info = gck_slot_get_token_info (self->slot);
result = g_strdup (info->label);
gck_token_info_free (info);
@@ -334,7 +412,7 @@ calculate_icon (GcrPkcs11Importer *self,
GIcon *result;
if (token_info == NULL)
- info = token_info = gck_slot_get_token_info (self->pv->slot);
+ info = token_info = gck_slot_get_token_info (self->slot);
result = gcr_icon_for_token (token_info);
gck_token_info_free (info);
@@ -360,7 +438,13 @@ _gcr_pkcs11_importer_get_property (GObject *obj,
g_value_set_object (value, _gcr_pkcs11_importer_get_slot (self));
break;
case PROP_IMPORTED:
- g_value_set_boxed (value, _gcr_pkcs11_importer_get_imported (self));
+ g_value_take_boxed (value, _gcr_pkcs11_importer_get_imported (self));
+ break;
+ case PROP_QUEUED:
+ g_value_set_pointer (value, _gcr_pkcs11_importer_get_queued (self));
+ break;
+ case PROP_INTERACTION:
+ g_value_set_object (value, self->interaction);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
@@ -379,12 +463,12 @@ _gcr_pkcs11_importer_class_init (GcrPkcs11ImporterClass *klass)
gobject_class->set_property = _gcr_pkcs11_importer_set_property;
gobject_class->get_property = _gcr_pkcs11_importer_get_property;
- g_type_class_add_private (gobject_class, sizeof (GcrPkcs11ImporterPrivate));
-
g_object_class_override_property (gobject_class, PROP_LABEL, "label");
g_object_class_override_property (gobject_class, PROP_ICON, "icon");
+ g_object_class_override_property (gobject_class, PROP_INTERACTION, "interaction");
+
g_object_class_install_property (gobject_class, PROP_SLOT,
g_param_spec_object ("slot", "Slot", "PKCS#11 slot to import data into",
GCK_TYPE_SLOT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
@@ -393,6 +477,10 @@ _gcr_pkcs11_importer_class_init (GcrPkcs11ImporterClass *klass)
g_param_spec_boxed ("imported", "Imported", "Imported objects",
GCK_TYPE_LIST, G_PARAM_READABLE));
+ g_object_class_install_property (gobject_class, PROP_QUEUED,
+ g_param_spec_pointer ("queued", "Queued", "Queued attributes",
+ G_PARAM_READABLE));
+
registered = gck_attributes_new ();
gck_attributes_add_ulong (registered, CKA_CLASS, CKO_CERTIFICATE);
gck_attributes_add_ulong (registered, CKA_CERTIFICATE_TYPE, CKC_X_509);
@@ -493,16 +581,10 @@ _gcr_pkcs11_importer_queue_for_parsed (GcrImporter *importer,
{
GcrPkcs11Importer *self = GCR_PKCS11_IMPORTER (importer);
GckAttributes *attrs;
- gboolean is_private;
attrs = gcr_parsed_get_attributes (parsed);
+ _gcr_pkcs11_importer_queue (self, attrs);
- if (!gck_attributes_find_boolean (attrs, CKA_PRIVATE, &is_private))
- is_private = FALSE;
- if (is_private)
- self->pv->any_private = TRUE;
-
- g_queue_push_tail (&self->pv->queue, gck_attributes_ref (attrs));
return TRUE;
}
@@ -512,6 +594,7 @@ _gcr_pkcs11_importer_import_async (GcrImporter *importer,
GAsyncReadyCallback callback,
gpointer user_data)
{
+ GcrPkcs11Importer *self = GCR_PKCS11_IMPORTER (importer);
GSimpleAsyncResult *res;
GcrImporterData *data;
@@ -523,6 +606,11 @@ _gcr_pkcs11_importer_import_async (GcrImporter *importer,
data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
g_simple_async_result_set_op_res_gpointer (res, data, gcr_importer_data_free);
+ if (GCR_IS_IMPORT_INTERACTION (self->interaction))
+ gcr_import_interaction_set_importer (GCR_IMPORT_INTERACTION (self->interaction),
+ GCR_IMPORTER (self));
+ gck_slot_set_interaction (self->slot, self->interaction);
+
next_state (res, state_open_session);
g_object_unref (res);
}
@@ -569,29 +657,29 @@ GckSlot *
_gcr_pkcs11_importer_get_slot (GcrPkcs11Importer *self)
{
g_return_val_if_fail (GCR_IS_PKCS11_IMPORTER (self), NULL);
- return self->pv->slot;
+ return self->slot;
}
GList *
_gcr_pkcs11_importer_get_imported (GcrPkcs11Importer *self)
{
g_return_val_if_fail (GCR_IS_PKCS11_IMPORTER (self), NULL);
- return self->pv->objects;
+ return g_list_copy (self->objects);
+}
+
+GList *
+_gcr_pkcs11_importer_get_queued (GcrPkcs11Importer *self)
+{
+ g_return_val_if_fail (GCR_IS_PKCS11_IMPORTER (self), NULL);
+ return g_list_copy (self->queue.head);
}
void
_gcr_pkcs11_importer_queue (GcrPkcs11Importer *self,
GckAttributes *attrs)
{
- gboolean is_private;
-
g_return_if_fail (GCR_IS_PKCS11_IMPORTER (self));
g_return_if_fail (attrs != NULL);
- if (!gck_attributes_find_boolean (attrs, CKA_PRIVATE, &is_private))
- is_private = FALSE;
- if (is_private)
- self->pv->any_private = TRUE;
-
- g_queue_push_tail (&self->pv->queue, gck_attributes_ref (attrs));
+ g_queue_push_tail (&self->queue, gck_attributes_ref (attrs));
}
diff --git a/gcr/gcr-pkcs11-importer.h b/gcr/gcr-pkcs11-importer.h
index bb0a8f2..a1e47f2 100644
--- a/gcr/gcr-pkcs11-importer.h
+++ b/gcr/gcr-pkcs11-importer.h
@@ -41,19 +41,7 @@ G_BEGIN_DECLS
#define GCR_PKCS11_IMPORTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCR_TYPE_PKCS11_IMPORTER, GcrPkcs11ImporterClass))
typedef struct _GcrPkcs11Importer GcrPkcs11Importer;
-typedef struct _GcrPkcs11ImporterClass GcrPkcs11ImporterClass;
-typedef struct _GcrPkcs11ImporterPrivate GcrPkcs11ImporterPrivate;
-struct _GcrPkcs11Importer {
- GObject parent;
-
- /*< private >*/
- GcrPkcs11ImporterPrivate *pv;
-};
-
-struct _GcrPkcs11ImporterClass {
- GObjectClass parent_class;
-};
GType _gcr_pkcs11_importer_get_type (void);
@@ -64,6 +52,8 @@ void _gcr_pkcs11_importer_queue (GcrPkcs11Importe
GckSlot * _gcr_pkcs11_importer_get_slot (GcrPkcs11Importer *self);
+GList * _gcr_pkcs11_importer_get_queued (GcrPkcs11Importer *self);
+
GList * _gcr_pkcs11_importer_get_imported (GcrPkcs11Importer *self);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]