summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stefw@collabora.co.uk>2011-09-27 15:48:39 +0200
committerStef Walter <stefw@collabora.co.uk>2011-09-27 15:48:39 +0200
commit61040577ebb5f6dfbb4d07a30edde91205abd7a9 (patch)
tree7ad773130474c103d580d4210e5332a76cdcdd5d
parent6cf14cf7397de26f80257dc49c741ec17f446a51 (diff)
downloadgnome-keyring-61040577ebb5f6dfbb4d07a30edde91205abd7a9.tar.gz
gcr: Refactor GcrParser and delay listing of importers
* PKCS#11 takes a long time to initialize with certain smart cards (several seconds). So we can't block the UI. * Expose the PKCS#11 initialization functions publicly. * Refactor GcrParser so that the current parsed item can be held around until later in the form of a GcrParsed structure. * Queue parsed items in GcrImportButton until PKCS#11 is initialized.
-rw-r--r--gcr/gcr-gnupg-importer.c14
-rw-r--r--gcr/gcr-import-button.c48
-rw-r--r--gcr/gcr-import-button.h2
-rw-r--r--gcr/gcr-importer.c40
-rw-r--r--gcr/gcr-importer.h26
-rw-r--r--gcr/gcr-internal.h10
-rw-r--r--gcr/gcr-library.c18
-rw-r--r--gcr/gcr-library.h10
-rw-r--r--gcr/gcr-parser.c246
-rw-r--r--gcr/gcr-parser.h22
-rw-r--r--gcr/gcr-pkcs11-certificate.c4
-rw-r--r--gcr/gcr-pkcs11-importer.c41
-rw-r--r--gcr/gcr-pkcs11-importer.h3
-rw-r--r--gcr/gcr-trust.c8
-rw-r--r--gcr/gcr-viewer-widget.c9
-rw-r--r--gcr/gcr-viewer-window.c4
-rw-r--r--tool/gkr-tool-import.c6
17 files changed, 362 insertions, 149 deletions
diff --git a/gcr/gcr-gnupg-importer.c b/gcr/gcr-gnupg-importer.c
index f527938c..5cd8faea 100644
--- a/gcr/gcr-gnupg-importer.c
+++ b/gcr/gcr-gnupg-importer.c
@@ -207,15 +207,15 @@ _gcr_gnupg_importer_class_init (GcrGnupgImporterClass *klass)
}
static GList *
-_gcr_gnupg_importer_create_for_parsed (GcrParser *parser)
+_gcr_gnupg_importer_create_for_parsed (GcrParsed *parsed)
{
GcrImporter *self;
- if (gcr_parser_get_parsed_format (parser) != GCR_FORMAT_OPENPGP_PACKET)
- return FALSE;
+ if (gcr_parsed_get_format (parsed) != GCR_FORMAT_OPENPGP_PACKET)
+ return NULL;
self = _gcr_gnupg_importer_new (NULL);
- if (!gcr_importer_queue_for_parsed (self, parser))
+ if (!gcr_importer_queue_for_parsed (self, parsed))
g_assert_not_reached ();
return g_list_append (NULL, self);
@@ -223,16 +223,16 @@ _gcr_gnupg_importer_create_for_parsed (GcrParser *parser)
static gboolean
_gcr_gnupg_importer_queue_for_parsed (GcrImporter *importer,
- GcrParser *parser)
+ GcrParsed *parsed)
{
GcrGnupgImporter *self = GCR_GNUPG_IMPORTER (importer);
gconstpointer block;
gsize n_block;
- if (gcr_parser_get_parsed_format (parser) != GCR_FORMAT_OPENPGP_PACKET)
+ if (gcr_parsed_get_format (parsed) != GCR_FORMAT_OPENPGP_PACKET)
return FALSE;
- block = gcr_parser_get_parsed_block (parser, &n_block);
+ block = gcr_parsed_get_data (parsed, &n_block);
g_return_val_if_fail (block, FALSE);
g_memory_input_stream_add_data (self->pv->packets, g_memdup (block, n_block),
diff --git a/gcr/gcr-import-button.c b/gcr/gcr-import-button.c
index 253ba541..6ae289d8 100644
--- a/gcr/gcr-import-button.c
+++ b/gcr/gcr-import-button.c
@@ -60,7 +60,9 @@ enum {
*/
struct _GcrImportButtonPrivate {
+ GList *queued;
GList *importers;
+ gboolean ready;
gboolean created;
gboolean importing;
gchar *imported;
@@ -96,8 +98,15 @@ update_import_button (GcrImportButton *self)
gchar *message;
gchar *label;
+ /* Initializing, set a spinner */
+ if (!self->pv->ready) {
+ gtk_widget_show (self->pv->spinner);
+ gtk_widget_hide (self->pv->arrow);
+ gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
+ gtk_widget_set_tooltip_text (GTK_WIDGET (self), _("Initializing..."));
+
/* Importing, set a spinner */
- if (self->pv->importing) {
+ } else if (self->pv->importing) {
gtk_widget_show (self->pv->spinner);
gtk_widget_hide (self->pv->arrow);
gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
@@ -150,6 +159,25 @@ update_import_button (GcrImportButton *self)
}
static void
+on_library_pkcs11_ready (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GcrImportButton *self = GCR_IMPORT_BUTTON (user_data);
+ GList *queued, *l;
+
+ self->pv->ready = TRUE;
+
+ /* Process the parsed items that have been seen */
+ queued = self->pv->queued;
+ self->pv->queued = NULL;
+ for (l = queued; l != NULL; l = g_list_next (l))
+ gcr_import_button_add_parsed (self, l->data);
+ g_assert (self->pv->queued == NULL);
+ g_list_free_full (queued, gcr_parsed_unref);
+}
+
+static void
gcr_import_button_constructed (GObject *obj)
{
GcrImportButton *self = GCR_IMPORT_BUTTON (obj);
@@ -175,6 +203,8 @@ gcr_import_button_constructed (GObject *obj)
gtk_container_add (GTK_CONTAINER (self), grid);
update_import_button (self);
+
+ gcr_pkcs11_initialize_async (NULL, on_library_pkcs11_ready, g_object_ref (self));
}
static void
@@ -224,6 +254,9 @@ gcr_import_button_dispose (GObject *obj)
g_cancellable_cancel (self->pv->cancellable);
g_clear_object (&self->pv->menu);
+ g_list_free_full (self->pv->queued, gcr_parsed_unref);
+ self->pv->queued = NULL;
+
G_OBJECT_CLASS (gcr_import_button_parent_class)->dispose (obj);
}
@@ -463,20 +496,25 @@ gcr_import_button_new (const gchar *label)
void
gcr_import_button_add_parsed (GcrImportButton *self,
- GcrParser *parser)
+ GcrParsed *parsed)
{
GList *importers;
g_return_if_fail (GCR_IS_IMPORT_BUTTON (self));
- g_return_if_fail (GCR_IS_PARSER (parser));
+ g_return_if_fail (parsed != NULL);
+
+ if (!self->pv->ready) {
+ self->pv->queued = g_list_prepend (self->pv->queued, gcr_parsed_ref (parsed));
+ return;
+ }
g_free (self->pv->imported);
self->pv->imported = NULL;
if (self->pv->created) {
- importers = gcr_importer_queue_and_filter_for_parsed (self->pv->importers, parser);
+ importers = gcr_importer_queue_and_filter_for_parsed (self->pv->importers, parsed);
} else {
- importers = gcr_importer_create_for_parsed (parser);
+ importers = gcr_importer_create_for_parsed (parsed);
self->pv->created = TRUE;
}
diff --git a/gcr/gcr-import-button.h b/gcr/gcr-import-button.h
index 35b116c3..3df12407 100644
--- a/gcr/gcr-import-button.h
+++ b/gcr/gcr-import-button.h
@@ -61,7 +61,7 @@ GType gcr_import_button_get_type (void) G_GNUC_CONST
GcrImportButton * gcr_import_button_new (const gchar *label);
void gcr_import_button_add_parsed (GcrImportButton *button,
- GcrParser *parser);
+ GcrParsed *parsed);
G_END_DECLS
diff --git a/gcr/gcr-importer.c b/gcr/gcr-importer.c
index b82b7d80..658bc324 100644
--- a/gcr/gcr-importer.c
+++ b/gcr/gcr-importer.c
@@ -154,19 +154,30 @@ sort_registered_by_n_attrs (gconstpointer a, gconstpointer b)
return (na == nb) ? 0 : -1;
}
+static gboolean
+check_if_seen_or_add (GHashTable *seen,
+ gpointer key)
+{
+ if (g_hash_table_lookup (seen, key))
+ return TRUE;
+ g_hash_table_insert (seen, key, key);
+ return FALSE;
+}
+
/**
* gcr_importer_create_for_parsed:
- * @parser: a parser with a parsed item to import
+ * @parsed: a parser with a parsed item to import
*
* Create a set of importers which can import this parsed item.
* The parsed item is represented by the state of the GcrParser at the
* time of calling this method.
*
* Returns: a list of importers which can import the parsed item, which
- * should be freed with gck_list_unref_free().
+ * should be freed with g_object_unref(), or %NULL if no types
+ * of importers can be created.
*/
GList *
-gcr_importer_create_for_parsed (GcrParser *parser)
+gcr_importer_create_for_parsed (GcrParsed *parsed)
{
GcrRegistered *registered;
GcrImporterIface *iface;
@@ -175,10 +186,11 @@ gcr_importer_create_for_parsed (GcrParser *parser)
gboolean matched;
gulong n_attrs;
GList *results = NULL;
+ GHashTable *seen;
gulong j;
gsize i;
- g_return_val_if_fail (GCR_IS_PARSER (parser), NULL);
+ g_return_val_if_fail (parsed != NULL, NULL);
gcr_importer_register_well_known ();
@@ -190,12 +202,14 @@ gcr_importer_create_for_parsed (GcrParser *parser)
registered_sorted = TRUE;
}
- attrs = gcr_parser_get_parsed_attributes (parser);
+ attrs = gcr_parsed_get_attributes (parsed);
if (attrs != NULL)
gck_attributes_ref (attrs);
else
attrs = gck_attributes_new ();
+ seen = g_hash_table_new (g_direct_hash, g_direct_equal);
+
for (i = 0; i < registered_importers->len; ++i) {
registered = &(g_array_index (registered_importers, GcrRegistered, i));
n_attrs = gck_attributes_count (registered->attrs);
@@ -210,17 +224,21 @@ gcr_importer_create_for_parsed (GcrParser *parser)
}
if (matched) {
+ if (check_if_seen_or_add (seen, GUINT_TO_POINTER (registered->importer_type)))
+ continue;
+
instance_class = g_type_class_ref (registered->importer_type);
iface = g_type_interface_peek (instance_class, GCR_TYPE_IMPORTER);
g_return_val_if_fail (iface != NULL, NULL);
g_return_val_if_fail (iface->create_for_parsed, NULL);
- results = g_list_concat (results, (iface->create_for_parsed) (parser));
+ results = g_list_concat (results, (iface->create_for_parsed) (parsed));
g_type_class_unref (instance_class);
}
}
+ g_hash_table_unref (seen);
gck_attributes_unref (attrs);
return results;
}
@@ -240,18 +258,18 @@ gcr_importer_create_for_parsed (GcrParser *parser)
*/
gboolean
gcr_importer_queue_for_parsed (GcrImporter *importer,
- GcrParser *parser)
+ GcrParsed *parsed)
{
GcrImporterIface *iface;
g_return_val_if_fail (GCR_IS_IMPORTER (importer), FALSE);
- g_return_val_if_fail (GCR_IS_PARSER (parser), FALSE);
+ g_return_val_if_fail (parsed != NULL, FALSE);
iface = GCR_IMPORTER_GET_INTERFACE (importer);
g_return_val_if_fail (iface != NULL, FALSE);
g_return_val_if_fail (iface->queue_for_parsed != NULL, FALSE);
- return (iface->queue_for_parsed) (importer, parser);
+ return (iface->queue_for_parsed) (importer, parsed);
}
/**
@@ -271,13 +289,13 @@ gcr_importer_queue_for_parsed (GcrImporter *importer,
*/
GList *
gcr_importer_queue_and_filter_for_parsed (GList *importers,
- GcrParser *parser)
+ GcrParsed *parsed)
{
GList *results = NULL;
GList *l;
for (l = importers; l != NULL; l = g_list_next (l)) {
- if (gcr_importer_queue_for_parsed (l->data, parser))
+ if (gcr_importer_queue_for_parsed (l->data, parsed))
results = g_list_prepend (results, g_object_ref (l->data));
}
diff --git a/gcr/gcr-importer.h b/gcr/gcr-importer.h
index 37ab2d97..e93395eb 100644
--- a/gcr/gcr-importer.h
+++ b/gcr/gcr-importer.h
@@ -45,10 +45,10 @@ typedef struct _GcrImporterIface GcrImporterIface;
struct _GcrImporterIface {
GTypeInterface parent;
- GList * (*create_for_parsed) (GcrParser *parser);
+ GList * (*create_for_parsed) (GcrParsed *parsed);
gboolean (*queue_for_parsed) (GcrImporter *importer,
- GcrParser *parser);
+ GcrParsed *parsed);
gboolean (*import_sync) (GcrImporter *importer,
GCancellable *cancellable,
@@ -67,33 +67,33 @@ struct _GcrImporterIface {
gpointer reserved[14];
};
-GType gcr_importer_get_type (void);
+GType gcr_importer_get_type (void);
-GList * gcr_importer_create_for_parsed (GcrParser *parser);
+GList * gcr_importer_create_for_parsed (GcrParsed *parsed);
-gboolean gcr_importer_queue_for_parsed (GcrImporter *importer,
- GcrParser *parser);
+gboolean gcr_importer_queue_for_parsed (GcrImporter *importer,
+ GcrParsed *parsed);
-GList * gcr_importer_queue_and_filter_for_parsed (GList *importers,
- GcrParser *parser);
+GList * gcr_importer_queue_and_filter_for_parsed (GList *importers,
+ GcrParsed *parsed);
-gboolean gcr_importer_import (GcrImporter *importer,
+gboolean gcr_importer_import (GcrImporter *importer,
GCancellable *cancellable,
GError **error);
-void gcr_importer_import_async (GcrImporter *importer,
+void gcr_importer_import_async (GcrImporter *importer,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
-gboolean gcr_importer_import_finish (GcrImporter *importer,
+gboolean gcr_importer_import_finish (GcrImporter *importer,
GAsyncResult *result,
GError **error);
-void gcr_importer_register (GType importer_type,
+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-internal.h b/gcr/gcr-internal.h
index fdf37488..ef6153fc 100644
--- a/gcr/gcr-internal.h
+++ b/gcr/gcr-internal.h
@@ -32,16 +32,6 @@
void _gcr_initialize_library (void);
-gboolean _gcr_initialize_pkcs11 (GCancellable *cancellable,
- GError **error);
-
-void _gcr_initialize_pkcs11_async (GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-
-gboolean _gcr_initialize_pkcs11_finish (GAsyncResult *result,
- GError **error);
-
void _gcr_set_pkcs11_config_dir (const gchar *dir);
#endif /* GCR_INTERNAL_H_ */
diff --git a/gcr/gcr-library.c b/gcr/gcr-library.c
index 409f6b45..b190a94a 100644
--- a/gcr/gcr-library.c
+++ b/gcr/gcr-library.c
@@ -211,14 +211,14 @@ on_initialize_registered (GObject *object,
}
void
-_gcr_initialize_pkcs11_async (GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
+gcr_pkcs11_initialize_async (GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
GSimpleAsyncResult *res;
res = g_simple_async_result_new (NULL, callback, user_data,
- _gcr_initialize_pkcs11_async);
+ gcr_pkcs11_initialize_async);
if (initialized_modules) {
_gcr_debug ("already initialized, no need to async");
@@ -234,11 +234,11 @@ _gcr_initialize_pkcs11_async (GCancellable *cancellable,
}
gboolean
-_gcr_initialize_pkcs11_finish (GAsyncResult *result,
- GError **error)
+gcr_pkcs11_initialize_finish (GAsyncResult *result,
+ GError **error)
{
g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
- _gcr_initialize_pkcs11_async), FALSE);
+ gcr_pkcs11_initialize_async), FALSE);
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
return FALSE;
@@ -247,8 +247,8 @@ _gcr_initialize_pkcs11_finish (GAsyncResult *result,
}
gboolean
-_gcr_initialize_pkcs11 (GCancellable *cancellable,
- GError **error)
+gcr_pkcs11_initialize (GCancellable *cancellable,
+ GError **error)
{
GList *results;
GError *err = NULL;
diff --git a/gcr/gcr-library.h b/gcr/gcr-library.h
index 88e13a3f..617a580b 100644
--- a/gcr/gcr-library.h
+++ b/gcr/gcr-library.h
@@ -32,6 +32,16 @@
#include <glib.h>
+void gcr_pkcs11_initialize_async (GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean gcr_pkcs11_initialize_finish (GAsyncResult *result,
+ GError **error);
+
+gboolean gcr_pkcs11_initialize (GCancellable *cancellable,
+ GError **error);
+
GList* gcr_pkcs11_get_modules (void);
void gcr_pkcs11_set_modules (GList *modules);
diff --git a/gcr/gcr-parser.c b/gcr/gcr-parser.c
index 7990633d..2e7e65f6 100644
--- a/gcr/gcr-parser.c
+++ b/gcr/gcr-parser.c
@@ -113,15 +113,18 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
-typedef struct _GcrParsed {
+struct _GcrParsed {
+ gint refs;
GckAttributes *attrs;
const gchar *description;
gchar *label;
- gconstpointer block;
- gsize n_block;
+ gpointer data;
+ gsize n_data;
+ gboolean sensitive;
+ GDestroyNotify destroy_func;
GcrDataFormat format;
struct _GcrParsed *next;
-} GcrParsed;
+};
struct _GcrParserPrivate {
GTree *specific_formats;
@@ -211,8 +214,8 @@ parsed_attribute (GcrParsed *parsed,
gconstpointer data,
gsize n_data)
{
- g_assert (parsed);
- g_assert (parsed->attrs);
+ g_assert (parsed != NULL);
+ g_assert (parsed->attrs != NULL);
gck_attributes_add_data (parsed->attrs, type, data, n_data);
}
@@ -245,8 +248,8 @@ parsed_ulong_attribute (GcrParsed *parsed,
CK_ATTRIBUTE_TYPE type,
gulong value)
{
- g_assert (parsed);
- g_assert (parsed->attrs);
+ g_assert (parsed != NULL);
+ g_assert (parsed->attrs != NULL);
gck_attributes_add_ulong (parsed->attrs, type, value);
}
@@ -255,8 +258,8 @@ parsed_boolean_attribute (GcrParsed *parsed,
CK_ATTRIBUTE_TYPE type,
gboolean value)
{
- g_assert (parsed);
- g_assert (parsed->attrs);
+ g_assert (parsed != NULL);
+ g_assert (parsed->attrs != NULL);
gck_attributes_add_boolean (parsed->attrs, type, value);
}
@@ -264,25 +267,26 @@ parsed_boolean_attribute (GcrParsed *parsed,
static void
parsing_block (GcrParsed *parsed,
gint format,
- gconstpointer block,
- gsize n_block)
+ gconstpointer data,
+ gsize n_data)
{
- g_assert (parsed);
- g_assert (block);
- g_assert (n_block);
+ g_assert (parsed != NULL);
+ g_assert (data != NULL);
+ g_assert (n_data != 0);
g_assert (format);
- g_assert (!parsed->block);
+ g_assert (parsed->data == NULL);
+ g_assert (parsed->destroy_func == NULL);
parsed->format = format;
- parsed->block = block;
- parsed->n_block = n_block;
+ parsed->data = (gpointer)data;
+ parsed->n_data = n_data;
}
static void
parsed_description (GcrParsed *parsed,
CK_OBJECT_CLASS klass)
{
- g_assert (parsed);
+ g_assert (parsed != NULL);
switch (klass) {
case CKO_PRIVATE_KEY:
parsed->description = _("Private Key");
@@ -306,10 +310,10 @@ static void
parsing_object (GcrParsed *parsed,
CK_OBJECT_CLASS klass)
{
- g_assert (parsed);
- g_assert (!parsed->attrs);
+ g_assert (parsed != NULL);
+ g_assert (parsed->attrs == NULL);
- if (klass == CKO_PRIVATE_KEY)
+ if (parsed->sensitive)
parsed->attrs = gck_attributes_new_full ((GckAllocator)egg_secure_realloc);
else
parsed->attrs = gck_attributes_new ();
@@ -323,9 +327,9 @@ parsed_attributes (GcrParsed *parsed,
{
gulong klass;
- g_assert (parsed);
- g_assert (attrs);
- g_assert (!parsed->attrs);
+ g_assert (parsed != NULL);
+ g_assert (attrs != NULL);
+ g_assert (parsed->attrs == NULL);
parsed->attrs = gck_attributes_ref (attrs);
if (gck_attributes_find_ulong (attrs, CKA_CLASS, &klass))
@@ -336,15 +340,18 @@ static void
parsed_label (GcrParsed *parsed,
const gchar *label)
{
- g_assert (parsed);
- g_assert (!parsed->label);
+ g_assert (parsed != NULL);
+ g_assert (parsed->label == NULL);
parsed->label = g_strdup (label);
}
static GcrParsed *
-push_parsed (GcrParser *self)
+push_parsed (GcrParser *self,
+ gboolean sensitive)
{
GcrParsed *parsed = g_new0 (GcrParsed, 1);
+ parsed->refs = 0;
+ parsed->sensitive = sensitive;
parsed->next = self->pv->parsed;
self->pv->parsed = parsed;
return parsed;
@@ -436,7 +443,7 @@ parse_der_private_key_rsa (GcrParser *self, const guchar *data, gsize n_data)
gulong version;
GcrParsed *parsed;
- parsed = push_parsed (self);
+ parsed = push_parsed (self, TRUE);
asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPrivateKey", data, n_data);
if (!asn)
@@ -489,7 +496,7 @@ parse_der_private_key_dsa (GcrParser *self, const guchar *data, gsize n_data)
GNode *asn = NULL;
GcrParsed *parsed;
- parsed = push_parsed (self);
+ parsed = push_parsed (self, TRUE);
asn = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPrivateKey", data, n_data);
if (!asn)
@@ -528,7 +535,7 @@ parse_der_private_key_dsa_parts (GcrParser *self, const guchar *keydata, gsize n
GNode *asn_key = NULL;
GcrParsed *parsed;
- parsed = push_parsed (self);
+ parsed = push_parsed (self, TRUE);
asn_params = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAParameters", params, n_params);
asn_key = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPrivatePart", keydata, n_keydata);
@@ -592,7 +599,7 @@ parse_der_pkcs8_plain (GcrParser *self, const guchar *data, gsize n_data)
GNode *asn = NULL;
GcrParsed *parsed;
- parsed = push_parsed (self);
+ parsed = push_parsed (self, TRUE);
ret = GCR_ERROR_UNRECOGNIZED;
asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-PrivateKeyInfo", data, n_data);
@@ -667,10 +674,10 @@ parse_der_pkcs8_encrypted (GcrParser *self, const guchar *data, gsize n_data)
const guchar *params;
gsize n_crypted, n_params;
const gchar *password;
- gint l;
GcrParsed *parsed;
+ gint l;
- parsed = push_parsed (self);
+ parsed = push_parsed (self, FALSE);
ret = GCR_ERROR_UNRECOGNIZED;
asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-EncryptedPrivateKeyInfo", data, n_data);
@@ -770,7 +777,7 @@ parse_der_certificate (GcrParser *self, const guchar *data, gsize n_data)
if (asn == NULL)
return GCR_ERROR_UNRECOGNIZED;
- parsed = push_parsed (self);
+ parsed = push_parsed (self, FALSE);
parsing_block (parsed, GCR_FORMAT_DER_CERTIFICATE_X509, data, n_data);
parsing_object (parsed, CKO_CERTIFICATE);
@@ -850,7 +857,7 @@ parse_der_pkcs7 (GcrParser *self, const guchar *data, gsize n_data)
GQuark oid;
GcrParsed *parsed;
- parsed = push_parsed (self);
+ parsed = push_parsed (self, FALSE);
ret = GCR_ERROR_UNRECOGNIZED;
asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-7-ContentInfo", data, n_data);
@@ -1036,7 +1043,7 @@ handle_pkcs12_bag (GcrParser *self, const guchar *data, gsize n_data)
if (!element)
goto done;
- parsed = push_parsed (self);
+ parsed = push_parsed (self, FALSE);
friendly = parse_pkcs12_bag_friendly_name (egg_asn1x_node (asn, i, "bagAttributes", NULL));
if (friendly != NULL)
@@ -1353,7 +1360,7 @@ parse_der_pkcs12 (GcrParser *self, const guchar *data, gsize n_data)
GQuark oid;
GcrParsed *parsed;
- parsed = push_parsed (self);
+ parsed = push_parsed (self, FALSE);
ret = GCR_ERROR_UNRECOGNIZED;
asn = decode_pkcs12_asn1_accepting_invalid_crap (pkix_asn1_tab, "pkcs-12-PFX",
@@ -1420,7 +1427,7 @@ on_openpgp_packet (GPtrArray *records,
if (records->len == 0)
return;
- parsed = push_parsed (self);
+ parsed = push_parsed (self, FALSE);
/* All we can do is the packet bounds */
parsing_block (parsed, GCR_FORMAT_OPENPGP_PACKET, outer, n_outer);
@@ -1616,7 +1623,7 @@ handle_pem_data (GQuark type,
if (!formats_for_armor_type (type, &inner_format, &outer_format))
return;
- parsed = push_parsed (args->parser);
+ parsed = push_parsed (args->parser, FALSE);
/* Fill in information necessary for prompting */
parsing_block (parsed, outer_format, outer, n_outer);
@@ -1735,7 +1742,7 @@ on_openssh_public_key_parsed (GckAttributes *attrs,
GcrParser *self = GCR_PARSER (user_data);
GcrParsed *parsed;
- parsed = push_parsed (self);
+ parsed = push_parsed (self, FALSE);
parsing_block (parsed, GCR_FORMAT_OPENSSH_PUBLIC, outer, n_outer);
parsed_attributes (parsed, attrs);
parsed_label (parsed, label);
@@ -2238,6 +2245,85 @@ gcr_parser_format_supported (GcrParser *self,
return parser_format_lookup (format) ? TRUE : FALSE;
}
+GcrParsed *
+gcr_parser_get_parsed (GcrParser *self)
+{
+ g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
+ return self->pv->parsed;
+}
+
+GType
+gcr_parsed_get_type (void)
+{
+ static volatile gsize initialized = 0;
+ static GType type = 0;
+ if (g_once_init_enter (&initialized)) {
+ type = g_boxed_type_register_static ("GcrParsed",
+ (GBoxedCopyFunc)gcr_parsed_ref,
+ (GBoxedFreeFunc)gcr_parsed_unref);
+ g_once_init_leave (&initialized, 1);
+ }
+ return type;
+}
+
+GcrParsed *
+gcr_parsed_ref (GcrParsed *parsed)
+{
+ GcrParsed *copy;
+
+ g_return_val_if_fail (parsed != NULL, NULL);
+
+ /* Already had a reference */
+ if (g_atomic_int_exchange_and_add (&parsed->refs, 1) >= 1)
+ return parsed;
+
+ /* If this is the first reference, flatten the stack of parsed */
+ copy = g_new0 (GcrParsed, 1);
+ copy->refs = 1;
+ copy->label = g_strdup (gcr_parsed_get_label (parsed));
+ copy->attrs = gcr_parsed_get_attributes (parsed);
+ if (copy->attrs)
+ gck_attributes_ref (copy->attrs);
+ copy->description = gcr_parsed_get_description (parsed);
+ copy->next = NULL;
+
+ /* Find the block of data to copy */
+ while (parsed != NULL) {
+ if (parsed->data != NULL) {
+ if (parsed->sensitive) {
+ copy->data = egg_secure_alloc (parsed->n_data);
+ memcpy (copy->data, parsed->data, parsed->n_data);
+ copy->destroy_func = egg_secure_free;
+ } else {
+ copy->data = g_memdup (parsed->data, parsed->n_data);
+ copy->destroy_func = g_free;
+ }
+ copy->n_data = parsed->n_data;
+ break;
+ }
+ parsed = parsed->next;
+ }
+
+ return copy;
+}
+
+void
+gcr_parsed_unref (gpointer parsed)
+{
+ GcrParsed *par = parsed;
+
+ g_return_if_fail (parsed != NULL);
+
+ if (g_atomic_int_dec_and_test (&par->refs)) {
+ if (par->attrs)
+ gck_attributes_unref (par->attrs);
+ g_free (par->label);
+ if (par->destroy_func)
+ (par->destroy_func) (par->data);
+ g_free (par);
+ }
+}
+
/**
* gcr_parser_get_parsed_description:
* @self: The parser
@@ -2251,13 +2337,19 @@ gcr_parser_format_supported (GcrParser *self,
const gchar*
gcr_parser_get_parsed_description (GcrParser *self)
{
- GcrParsed *parsed;
-
g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
+ g_return_val_if_fail (self->pv->parsed != NULL, NULL);
+
+ return gcr_parsed_get_description (self->pv->parsed);
+}
- for (parsed = self->pv->parsed; parsed != NULL; parsed = parsed->next) {
+const gchar*
+gcr_parsed_get_description (GcrParsed *parsed)
+{
+ while (parsed != NULL) {
if (parsed->description != NULL)
return parsed->description;
+ parsed = parsed->next;
}
return NULL;
@@ -2273,16 +2365,22 @@ gcr_parser_get_parsed_description (GcrParser *self)
* Returns: The attributes for the current item. These are owned by the parser
* and should not be freed.
*/
-GckAttributes*
+GckAttributes *
gcr_parser_get_parsed_attributes (GcrParser *self)
{
- GcrParsed *parsed;
-
g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
+ g_return_val_if_fail (self->pv->parsed != NULL, NULL);
+
+ return gcr_parsed_get_attributes (self->pv->parsed);
+}
- for (parsed = self->pv->parsed; parsed != NULL; parsed = parsed->next) {
+GckAttributes *
+gcr_parsed_get_attributes (GcrParsed *parsed)
+{
+ while (parsed != NULL) {
if (parsed->attrs != NULL)
return parsed->attrs;
+ parsed = parsed->next;
}
return NULL;
@@ -2301,13 +2399,19 @@ gcr_parser_get_parsed_attributes (GcrParser *self)
const gchar*
gcr_parser_get_parsed_label (GcrParser *self)
{
- GcrParsed *parsed;
-
g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
+ g_return_val_if_fail (self->pv->parsed != NULL, NULL);
- for (parsed = self->pv->parsed; parsed != NULL; parsed = parsed->next) {
+ return gcr_parsed_get_label (self->pv->parsed);
+}
+
+const gchar*
+gcr_parsed_get_label (GcrParsed *parsed)
+{
+ while (parsed != NULL) {
if (parsed->label != NULL)
return parsed->label;
+ parsed = parsed->next;
}
return NULL;
@@ -2328,19 +2432,28 @@ gconstpointer
gcr_parser_get_parsed_block (GcrParser *self,
gsize *n_block)
{
- GcrParsed *parsed;
-
g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
- g_return_val_if_fail (n_block, NULL);
+ g_return_val_if_fail (n_block != NULL, NULL);
+ g_return_val_if_fail (self->pv->parsed != NULL, NULL);
- for (parsed = self->pv->parsed; parsed != NULL; parsed = parsed->next) {
- if (parsed->block != NULL) {
- *n_block = parsed->n_block;
- return parsed->block;
+ return gcr_parsed_get_data (self->pv->parsed, n_block);
+}
+
+gconstpointer
+gcr_parsed_get_data (GcrParsed *parsed,
+ gsize *n_data)
+{
+ g_return_val_if_fail (n_data != NULL, NULL);
+
+ while (parsed != NULL) {
+ if (parsed->data != NULL) {
+ *n_data = parsed->n_data;
+ return parsed->data;
}
+ parsed = parsed->next;
}
- *n_block = 0;
+ *n_data = 0;
return NULL;
}
@@ -2358,18 +2471,23 @@ gcr_parser_get_parsed_block (GcrParser *self,
GcrDataFormat
gcr_parser_get_parsed_format (GcrParser *self)
{
- GcrParsed *parsed;
-
g_return_val_if_fail (GCR_IS_PARSER (self), 0);
+ g_return_val_if_fail (self->pv->parsed != NULL, 0);
+
+ return gcr_parsed_get_format (self->pv->parsed);
+}
- for (parsed = self->pv->parsed; parsed != NULL; parsed = parsed->next) {
- if (parsed->block != NULL)
+GcrDataFormat
+gcr_parsed_get_format (GcrParsed *parsed)
+{
+ while (parsed != NULL) {
+ if (parsed->data != NULL)
return parsed->format;
+ parsed = parsed->next;
}
return 0;
}
-
/* ---------------------------------------------------------------------------------
* STREAM PARSING
*/
diff --git a/gcr/gcr-parser.h b/gcr/gcr-parser.h
index d6cb1c52..cb2676c2 100644
--- a/gcr/gcr-parser.h
+++ b/gcr/gcr-parser.h
@@ -43,6 +43,7 @@ G_BEGIN_DECLS
typedef struct _GcrParser GcrParser;
typedef struct _GcrParserClass GcrParserClass;
typedef struct _GcrParserPrivate GcrParserPrivate;
+typedef struct _GcrParsed GcrParsed;
struct _GcrParser {
GObject parent;
@@ -98,6 +99,8 @@ gboolean gcr_parser_parse_stream_finish (GcrParser *self,
void gcr_parser_add_password (GcrParser *self,
const gchar *password);
+GcrParsed * gcr_parser_get_parsed (GcrParser *self);
+
const gchar* gcr_parser_get_parsed_label (GcrParser *self);
const gchar* gcr_parser_get_parsed_description (GcrParser *self);
@@ -109,6 +112,25 @@ gconstpointer gcr_parser_get_parsed_block (GcrParser *self,
GcrDataFormat gcr_parser_get_parsed_format (GcrParser *self);
+#define GCR_TYPE_PARSED (gcr_parsed_get_type ())
+
+GType gcr_parsed_get_type (void) G_GNUC_CONST;
+
+GcrParsed * gcr_parsed_ref (GcrParsed *parsed);
+
+void gcr_parsed_unref (gpointer parsed);
+
+const gchar* gcr_parsed_get_label (GcrParsed *parsed);
+
+const gchar* gcr_parsed_get_description (GcrParsed *parsed);
+
+GckAttributes* gcr_parsed_get_attributes (GcrParsed *parsed);
+
+gconstpointer gcr_parsed_get_data (GcrParsed *parsed,
+ gsize *n_data);
+
+GcrDataFormat gcr_parsed_get_format (GcrParsed *parsed);
+
G_END_DECLS
#endif /* __GCR_PARSER_H__ */
diff --git a/gcr/gcr-pkcs11-certificate.c b/gcr/gcr-pkcs11-certificate.c
index 81a56d56..cb8b107e 100644
--- a/gcr/gcr-pkcs11-certificate.c
+++ b/gcr/gcr-pkcs11-certificate.c
@@ -121,7 +121,7 @@ perform_lookup_certificate (GckAttributes *search,
GckEnumerator *en;
GList *modules;
- if (!_gcr_initialize_pkcs11 (cancellable, error))
+ if (!gcr_pkcs11_initialize (cancellable, error))
return NULL;
modules = gcr_pkcs11_get_modules ();
@@ -366,7 +366,7 @@ gcr_pkcs11_certificate_lookup_issuer (GcrCertificate *certificate, GCancellable
g_return_val_if_fail (GCR_IS_CERTIFICATE (certificate), NULL);
- if (!_gcr_initialize_pkcs11 (cancellable, error))
+ if (!gcr_pkcs11_initialize (cancellable, error))
return NULL;
search = prepare_lookup_certificate_issuer (certificate);
diff --git a/gcr/gcr-pkcs11-importer.c b/gcr/gcr-pkcs11-importer.c
index 29a29720..f2932bab 100644
--- a/gcr/gcr-pkcs11-importer.c
+++ b/gcr/gcr-pkcs11-importer.c
@@ -24,8 +24,10 @@
#include "config.h"
+#include "gcr-base.h"
#include "gcr-internal.h"
#include "gcr-library.h"
+#include "gcr-internal.h"
#include "gcr-parser.h"
#include "gcr-pkcs11-importer.h"
@@ -409,19 +411,11 @@ _gcr_pkcs11_importer_class_init (GcrPkcs11ImporterClass *klass)
static GList *
list_all_slots (void)
{
- GError *error = NULL;
- GList *modules, *l;
- GList *results = NULL;
-
- if (!_gcr_initialize_pkcs11 (NULL, &error)) {
- g_warning ("couldn't initialize PKCS#11 modules: %s", error->message);
- g_clear_error (&error);
- return NULL;
- }
+ GList *modules;
+ GList *results;
modules = gcr_pkcs11_get_modules ();
- for (l = modules; l != NULL; l = g_list_next (l))
- results = g_list_concat (results, gck_modules_get_slots (modules, TRUE));
+ results = gck_modules_get_slots (modules, TRUE);
gck_list_unref_free (modules);
return results;
@@ -468,7 +462,7 @@ is_slot_importable (GckSlot *slot,
}
static GList *
-_gcr_pkcs11_importer_create_for_parsed (GcrParser *parser)
+_gcr_pkcs11_importer_create_for_parsed (GcrParsed *parsed)
{
GcrImporter *self;
GList *slots, *l;
@@ -484,7 +478,7 @@ _gcr_pkcs11_importer_create_for_parsed (GcrParser *parser)
if (importable) {
self = _gcr_pkcs11_importer_new (l->data);
- if (!gcr_importer_queue_for_parsed (self, parser))
+ if (!gcr_importer_queue_for_parsed (self, parsed))
g_assert_not_reached ();
results = g_list_prepend (results, self);
}
@@ -496,13 +490,13 @@ _gcr_pkcs11_importer_create_for_parsed (GcrParser *parser)
static gboolean
_gcr_pkcs11_importer_queue_for_parsed (GcrImporter *importer,
- GcrParser *parser)
+ GcrParsed *parsed)
{
GcrPkcs11Importer *self = GCR_PKCS11_IMPORTER (importer);
GckAttributes *attrs;
gboolean is_private;
- attrs = gcr_parser_get_parsed_attributes (parser);
+ attrs = gcr_parsed_get_attributes (parsed);
if (!gck_attributes_find_boolean (attrs, CKA_PRIVATE, &is_private))
is_private = FALSE;
@@ -580,3 +574,20 @@ _gcr_pkcs11_importer_get_imported (GcrPkcs11Importer *self)
g_return_val_if_fail (GCR_IS_PKCS11_IMPORTER (self), NULL);
return self->pv->objects;
}
+
+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));
+}
diff --git a/gcr/gcr-pkcs11-importer.h b/gcr/gcr-pkcs11-importer.h
index bbf752ca..bb0a8f21 100644
--- a/gcr/gcr-pkcs11-importer.h
+++ b/gcr/gcr-pkcs11-importer.h
@@ -59,6 +59,9 @@ GType _gcr_pkcs11_importer_get_type (void);
GcrImporter * _gcr_pkcs11_importer_new (GckSlot *slot);
+void _gcr_pkcs11_importer_queue (GcrPkcs11Importer *self,
+ GckAttributes *attrs);
+
GckSlot * _gcr_pkcs11_importer_get_slot (GcrPkcs11Importer *self);
GList * _gcr_pkcs11_importer_get_imported (GcrPkcs11Importer *self);
diff --git a/gcr/gcr-trust.c b/gcr/gcr-trust.c
index eaa98001..48006e64 100644
--- a/gcr/gcr-trust.c
+++ b/gcr/gcr-trust.c
@@ -161,7 +161,7 @@ perform_is_certificate_pinned (GckAttributes *search,
GList *slots;
GckObject *object;
- if (!_gcr_initialize_pkcs11 (cancellable, error))
+ if (!gcr_pkcs11_initialize (cancellable, error))
return FALSE;
slots = gcr_pkcs11_get_trust_lookup_slots ();
@@ -339,7 +339,7 @@ perform_add_pinned_certificate (GckAttributes *search,
GckEnumerator *en;
GList *slots;
- if (!_gcr_initialize_pkcs11 (cancellable, error))
+ if (!gcr_pkcs11_initialize (cancellable, error))
return FALSE;
slots = gcr_pkcs11_get_trust_lookup_slots ();
@@ -553,7 +553,7 @@ perform_remove_pinned_certificate (GckAttributes *attrs,
GckEnumerator *en;
GList *slots;
- if (!_gcr_initialize_pkcs11 (cancellable, error))
+ if (!gcr_pkcs11_initialize (cancellable, error))
return FALSE;
slots = gcr_pkcs11_get_trust_lookup_slots ();
@@ -735,7 +735,7 @@ perform_is_certificate_anchored (GckAttributes *attrs,
GList *slots;
GckObject *object;
- if (!_gcr_initialize_pkcs11 (cancellable, error))
+ if (!gcr_pkcs11_initialize (cancellable, error))
return FALSE;
slots = gcr_pkcs11_get_trust_lookup_slots ();
diff --git a/gcr/gcr-viewer-widget.c b/gcr/gcr-viewer-widget.c
index 5db8b62b..b06b1f60 100644
--- a/gcr/gcr-viewer-widget.c
+++ b/gcr/gcr-viewer-widget.c
@@ -76,7 +76,7 @@ struct _GcrViewerWidgetClass {
void (*added) (GcrViewerWidget *widget,
GcrRenderer *renderer,
- GcrParser *parser);
+ GcrParsed *parsed);
};
struct _GcrViewerWidgetPrivate {
@@ -138,7 +138,8 @@ on_parser_parsed (GcrParser *parser,
/* Let callers know we're rendering data */
if (actual == TRUE)
- g_signal_emit (self, signals[ADDED], 0, renderer, parser);
+ g_signal_emit (self, signals[ADDED], 0, renderer,
+ gcr_parser_get_parsed (parser));
g_object_unref (renderer);
}
@@ -277,8 +278,8 @@ gcr_viewer_widget_class_init (GcrViewerWidgetClass *klass)
signals[ADDED] = g_signal_new ("added", GCR_TYPE_VIEWER_WIDGET, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GcrViewerWidgetClass, added),
- NULL, NULL, _gcr_marshal_VOID__OBJECT_OBJECT,
- G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT);
+ NULL, NULL, _gcr_marshal_VOID__OBJECT_BOXED,
+ G_TYPE_NONE, 2, G_TYPE_OBJECT, GCR_TYPE_PARSED);
}
static void
diff --git a/gcr/gcr-viewer-window.c b/gcr/gcr-viewer-window.c
index 63019172..e37287bd 100644
--- a/gcr/gcr-viewer-window.c
+++ b/gcr/gcr-viewer-window.c
@@ -41,11 +41,11 @@ G_DEFINE_TYPE (GcrViewerWindow, _gcr_viewer_window, GTK_TYPE_WINDOW);
static void
on_viewer_renderer_added (GcrViewerWidget *viewer,
GcrRenderer *renderer,
- GcrParser *parser,
+ GcrParsed *parsed,
gpointer user_data)
{
GcrViewerWindow *self = GCR_VIEWER_WINDOW (user_data);
- gcr_import_button_add_parsed (self->pv->import, parser);
+ gcr_import_button_add_parsed (self->pv->import, parsed);
}
static void
diff --git a/tool/gkr-tool-import.c b/tool/gkr-tool-import.c
index 05f26ddc..548831c5 100644
--- a/tool/gkr-tool-import.c
+++ b/tool/gkr-tool-import.c
@@ -146,12 +146,14 @@ on_parser_parsed (GcrParser *parser,
gpointer user_data)
{
ImportClosure *closure = user_data;
+ GcrParsed *parsed;
GList *filtered;
+ parsed = gcr_parser_get_parsed (parser);
if (closure->num_parsed == 0) {
- closure->importers = gcr_importer_create_for_parsed (parser);
+ closure->importers = gcr_importer_create_for_parsed (parsed);
} else {
- filtered = gcr_importer_queue_and_filter_for_parsed (closure->importers, parser);
+ filtered = gcr_importer_queue_and_filter_for_parsed (closure->importers, parsed);
gck_list_unref_free (closure->importers);
closure->importers = filtered;
}