[gnome-keyring] gcr: Refactor GcrParser and delay listing of importers



commit 61040577ebb5f6dfbb4d07a30edde91205abd7a9
Author: Stef Walter <stefw collabora co uk>
Date:   Tue Sep 27 15:48:39 2011 +0200

    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.

 gcr/gcr-gnupg-importer.c     |   14 ++--
 gcr/gcr-import-button.c      |   48 ++++++++-
 gcr/gcr-import-button.h      |    2 +-
 gcr/gcr-importer.c           |   40 +++++--
 gcr/gcr-importer.h           |   26 +++---
 gcr/gcr-internal.h           |   10 --
 gcr/gcr-library.c            |   18 ++--
 gcr/gcr-library.h            |   10 ++
 gcr/gcr-parser.c             |  246 +++++++++++++++++++++++++++++++-----------
 gcr/gcr-parser.h             |   22 ++++
 gcr/gcr-pkcs11-certificate.c |    4 +-
 gcr/gcr-pkcs11-importer.c    |   41 +++++---
 gcr/gcr-pkcs11-importer.h    |    3 +
 gcr/gcr-trust.c              |    8 +-
 gcr/gcr-viewer-widget.c      |    9 +-
 gcr/gcr-viewer-window.c      |    4 +-
 tool/gkr-tool-import.c       |    6 +-
 17 files changed, 362 insertions(+), 149 deletions(-)
---
diff --git a/gcr/gcr-gnupg-importer.c b/gcr/gcr-gnupg-importer.c
index f527938..5cd8fae 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 253ba54..6ae289d 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 35b116c..3df1240 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 b82b7d8..658bc32 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 37ab2d9..e93395e 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 fdf3748..ef6153f 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 409f6b4..b190a94 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 88e13a3..617a580 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 7990633..2e7e65f 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 d6cb1c5..cb2676c 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 81a56d5..cb8b107 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 29a2972..f2932ba 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 bbf752c..bb0a8f2 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 eaa9800..48006e6 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 5db8b62..b06b1f6 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 6301917..e37287b 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 05f26dd..548831c 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;
 	}



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