[seahorse] pkcs11: Matching certificates and keys into a single item



commit 57d1e9d0ff77cfb26654df69becaf53b617442ad
Author: Stef Walter <stefw collabora co uk>
Date:   Thu Nov 3 13:29:08 2011 +0100

    pkcs11: Matching certificates and keys into a single item
    
     * Also fix regression of setting appropriate place on pkcs11 items

 pkcs11/seahorse-certificate.c |  105 ++++++++++++-
 pkcs11/seahorse-certificate.h |   10 +-
 pkcs11/seahorse-private-key.c |   53 ++++++-
 pkcs11/seahorse-private-key.h |    8 +-
 pkcs11/seahorse-token.c       |  363 +++++++++++++++++++++++++++++++----------
 5 files changed, 441 insertions(+), 98 deletions(-)
---
diff --git a/pkcs11/seahorse-certificate.c b/pkcs11/seahorse-certificate.c
index 664daaa..9572189 100644
--- a/pkcs11/seahorse-certificate.c
+++ b/pkcs11/seahorse-certificate.c
@@ -26,6 +26,7 @@
 #include "seahorse-pkcs11.h"
 #include "seahorse-pkcs11-actions.h"
 #include "seahorse-pkcs11-helpers.h"
+#include "seahorse-private-key.h"
 #include "seahorse-token.h"
 #include "seahorse-types.h"
 
@@ -49,7 +50,9 @@ enum {
 	PROP_PLACE,
 	PROP_ATTRIBUTES,
 	PROP_FLAGS,
-	PROP_ACTIONS
+	PROP_ACTIONS,
+	PROP_ICON,
+	PROP_PRIVATE_KEY
 };
 
 struct _SeahorseCertificatePrivate {
@@ -57,6 +60,8 @@ struct _SeahorseCertificatePrivate {
 	GckAttributes *attributes;
 	GckAttribute der_value;
 	GtkActionGroup *actions;
+	SeahorsePrivateKey *private_key;
+	GIcon *icon;
 };
 
 static void seahorse_certificate_certificate_iface (GcrCertificateIface *iface);
@@ -69,6 +74,27 @@ G_DEFINE_TYPE_WITH_CODE (SeahorseCertificate, seahorse_certificate, GCK_TYPE_OBJ
 );
 
 static void
+update_icon (SeahorseCertificate *self)
+{
+	GEmblem *emblem;
+	GIcon *eicon;
+	GIcon *icon;
+
+	g_clear_object (&self->pv->icon);
+	icon = gcr_certificate_get_icon (GCR_CERTIFICATE (self));
+	if (self->pv->private_key) {
+		eicon = g_themed_icon_new (GCR_ICON_KEY);
+		emblem = g_emblem_new (eicon);
+		self->pv->icon = g_emblemed_icon_new (icon, emblem);
+		g_object_unref (icon);
+		g_object_unref (eicon);
+		g_object_unref (emblem);
+	} else {
+		self->pv->icon = icon;
+	}
+}
+
+static void
 seahorse_certificate_init (SeahorseCertificate *self)
 {
 	self->pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_CERTIFICATE, SeahorseCertificatePrivate));
@@ -88,6 +114,15 @@ seahorse_certificate_notify (GObject *obj,
 		G_OBJECT_CLASS (seahorse_certificate_parent_class)->notify (obj, pspec);
 }
 
+static void
+seahorse_certificate_dispose (GObject *obj)
+{
+	SeahorseCertificate *self = SEAHORSE_CERTIFICATE (obj);
+
+	g_clear_object (&self->pv->private_key);
+
+	G_OBJECT_CLASS (seahorse_certificate_parent_class)->dispose (obj);
+}
 
 static void
 seahorse_certificate_finalize (GObject *obj)
@@ -125,6 +160,12 @@ seahorse_certificate_get_property (GObject *obj,
 	case PROP_ACTIONS:
 		g_value_set_object (value, self->pv->actions);
 		break;
+	case PROP_ICON:
+		g_value_set_object (value, seahorse_certificate_get_icon (self));
+		break;
+	case PROP_PRIVATE_KEY:
+		g_value_set_object (value, seahorse_certificate_get_private_key (self));
+		break;
 	default:
 		gcr_certificate_mixin_get_property (obj, prop_id, value, pspec);
 		break;
@@ -142,8 +183,13 @@ seahorse_certificate_set_property (GObject *obj,
 
 	switch (prop_id) {
 	case PROP_PLACE:
-		g_return_if_fail (self->pv->token == NULL);
-		self->pv->token = g_value_dup_object (value);
+		if (self->pv->token)
+			g_object_remove_weak_pointer (G_OBJECT (self->pv->token),
+			                              (gpointer *)&self->pv->token);
+		self->pv->token = g_value_get_object (value);
+		if (self->pv->token)
+			g_object_add_weak_pointer (G_OBJECT (self->pv->token),
+			                           (gpointer *)&self->pv->token);
 		break;
 	case PROP_ATTRIBUTES:
 		if (self->pv->attributes)
@@ -157,6 +203,9 @@ seahorse_certificate_set_property (GObject *obj,
 			gck_attribute_init_copy (&self->pv->der_value, der_value);
 		}
 		break;
+	case PROP_PRIVATE_KEY:
+		seahorse_certificate_set_private_key (self, g_value_get_object (value));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -170,6 +219,7 @@ seahorse_certificate_class_init (SeahorseCertificateClass *klass)
 
 	g_type_class_add_private (klass, sizeof (SeahorseCertificatePrivate));
 
+	gobject_class->dispose = seahorse_certificate_dispose;
 	gobject_class->finalize = seahorse_certificate_finalize;
 	gobject_class->set_property = seahorse_certificate_set_property;
 	gobject_class->get_property = seahorse_certificate_get_property;
@@ -177,7 +227,7 @@ seahorse_certificate_class_init (SeahorseCertificateClass *klass)
 
 	g_object_class_install_property (gobject_class, PROP_PLACE,
 	         g_param_spec_object ("place", "place", "place", SEAHORSE_TYPE_TOKEN,
-	                              G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
+	                              G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE));
 
 	g_object_class_install_property (gobject_class, PROP_FLAGS,
 	         g_param_spec_flags ("flags", "flags", "flags", SEAHORSE_TYPE_FLAGS, SEAHORSE_FLAG_NONE,
@@ -187,6 +237,11 @@ seahorse_certificate_class_init (SeahorseCertificateClass *klass)
 	         g_param_spec_object ("actions", "Actions", "Actions", GTK_TYPE_ACTION_GROUP,
 	                              G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
 
+	g_object_class_install_property (gobject_class, PROP_PRIVATE_KEY,
+	            g_param_spec_object ("private-key", "Private key", "Private key associated with certificate",
+	                                 SEAHORSE_TYPE_PRIVATE_KEY, G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE));
+
+	g_object_class_override_property (gobject_class, PROP_ICON, "icon");
 	g_object_class_override_property (gobject_class, PROP_ATTRIBUTES, "attributes");
 
 	gcr_certificate_mixin_class_init (gobject_class);
@@ -215,3 +270,45 @@ seahorse_certificate_object_attributes_iface (GckObjectAttributesIface *iface)
 	iface->attribute_types = REQUIRED_ATTRS;
 	iface->n_attribute_types = G_N_ELEMENTS (REQUIRED_ATTRS);
 }
+
+GIcon *
+seahorse_certificate_get_icon (SeahorseCertificate *self)
+{
+	g_return_val_if_fail (SEAHORSE_IS_CERTIFICATE (self), NULL);
+
+	if (!self->pv->icon)
+		update_icon (self);
+
+	return self->pv->icon;
+}
+
+SeahorsePrivateKey *
+seahorse_certificate_get_private_key (SeahorseCertificate *self)
+{
+	g_return_val_if_fail (SEAHORSE_IS_CERTIFICATE (self), NULL);
+	return self->pv->private_key;
+}
+
+void
+seahorse_certificate_set_private_key (SeahorseCertificate *self,
+                                      SeahorsePrivateKey *private_key)
+{
+	GObject *obj;
+
+	g_return_if_fail (SEAHORSE_IS_CERTIFICATE (self));
+	g_return_if_fail (private_key == NULL || SEAHORSE_IS_PRIVATE_KEY (private_key));
+
+	if (self->pv->private_key)
+		g_object_remove_weak_pointer (G_OBJECT (private_key),
+		                              (gpointer *)self->pv->private_key);
+	self->pv->private_key = private_key;
+	if (self->pv->private_key)
+		g_object_add_weak_pointer (G_OBJECT (private_key),
+		                           (gpointer *)self->pv->private_key);
+
+	obj = G_OBJECT (self);
+	g_object_notify (obj, "private-key");
+	g_clear_object (&self->pv->icon);
+	g_object_notify (obj, "icon");
+	g_object_notify (obj, "description");
+}
diff --git a/pkcs11/seahorse-certificate.h b/pkcs11/seahorse-certificate.h
index 589c1ab..f6f4d8e 100644
--- a/pkcs11/seahorse-certificate.h
+++ b/pkcs11/seahorse-certificate.h
@@ -36,6 +36,7 @@
 typedef struct _SeahorseCertificate SeahorseCertificate;
 typedef struct _SeahorseCertificateClass SeahorseCertificateClass;
 typedef struct _SeahorseCertificatePrivate SeahorseCertificatePrivate;
+typedef struct _SeahorsePrivateKey SeahorsePrivateKey;
 
 struct _SeahorseCertificate {
 	GckObject parent;
@@ -48,12 +49,11 @@ struct _SeahorseCertificateClass {
 
 GType                 seahorse_certificate_get_type               (void) G_GNUC_CONST;
 
-void                  seahorse_certificate_realize                (SeahorseCertificate *self);
+GIcon *               seahorse_certificate_get_icon               (SeahorseCertificate *self);
 
-guint                 seahorse_certificate_get_validity           (SeahorseCertificate* self);
+SeahorsePrivateKey *  seahorse_certificate_get_private_key        (SeahorseCertificate *self);
 
-guint                 seahorse_certificate_get_trust              (SeahorseCertificate* self);
-
-gulong                seahorse_certificate_get_expires            (SeahorseCertificate* self);
+void                  seahorse_certificate_set_private_key        (SeahorseCertificate *self,
+                                                                   SeahorsePrivateKey *private_key);
 
 #endif /* __SEAHORSE_CERTIFICATE_H__ */
diff --git a/pkcs11/seahorse-private-key.c b/pkcs11/seahorse-private-key.c
index 58e0aeb..c869458 100644
--- a/pkcs11/seahorse-private-key.c
+++ b/pkcs11/seahorse-private-key.c
@@ -50,13 +50,15 @@ enum {
 	PROP_PLACE,
 	PROP_ATTRIBUTES,
 	PROP_FLAGS,
-	PROP_ACTIONS
+	PROP_ACTIONS,
+	PROP_CERTIFICATE,
 };
 
 struct _SeahorsePrivateKeyPrivate {
 	SeahorseToken *token;
 	GckAttributes *attributes;
 	GtkActionGroup *actions;
+	SeahorseCertificate *certificate;
 };
 
 static void seahorse_private_key_object_attributes_iface (GckObjectAttributesIface *iface);
@@ -106,6 +108,9 @@ seahorse_private_key_get_property (GObject *obj,
 	case PROP_ACTIONS:
 		g_value_set_object (value, self->pv->actions);
 		break;
+	case PROP_CERTIFICATE:
+		g_value_set_object (value, seahorse_private_key_get_certificate (self));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -122,14 +127,22 @@ seahorse_private_key_set_property (GObject *obj,
 
 	switch (prop_id) {
 	case PROP_PLACE:
-		g_return_if_fail (self->pv->token == NULL);
-		self->pv->token = g_value_dup_object (value);
+		if (self->pv->token)
+			g_object_remove_weak_pointer (G_OBJECT (self->pv->token),
+			                              (gpointer *)&self->pv->token);
+		self->pv->token = g_value_get_object (value);
+		if (self->pv->token)
+			g_object_add_weak_pointer (G_OBJECT (self->pv->token),
+			                           (gpointer *)&self->pv->token);
 		break;
 	case PROP_ATTRIBUTES:
 		if (self->pv->attributes)
 			gck_attributes_unref (self->pv->attributes);
 		self->pv->attributes = g_value_dup_boxed (value);
 		break;
+	case PROP_CERTIFICATE:
+		seahorse_private_key_set_certificate (self, g_value_get_object (value));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 		break;
@@ -149,7 +162,7 @@ seahorse_private_key_class_init (SeahorsePrivateKeyClass *klass)
 
 	g_object_class_install_property (gobject_class, PROP_PLACE,
 	         g_param_spec_object ("place", "place", "place", SEAHORSE_TYPE_TOKEN,
-	                              G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
+	                              G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE));
 
 	g_object_class_install_property (gobject_class, PROP_FLAGS,
 	         g_param_spec_flags ("flags", "flags", "flags", SEAHORSE_TYPE_FLAGS, SEAHORSE_FLAG_NONE,
@@ -159,6 +172,10 @@ seahorse_private_key_class_init (SeahorsePrivateKeyClass *klass)
 	         g_param_spec_object ("actions", "Actions", "Actions", GTK_TYPE_ACTION_GROUP,
 	                              G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
 
+	g_object_class_install_property (gobject_class, PROP_CERTIFICATE,
+	            g_param_spec_object ("certificate", "Certificate", "Certificate associated with this private key",
+	                                 SEAHORSE_TYPE_CERTIFICATE, G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE));
+
 	g_object_class_override_property (gobject_class, PROP_ATTRIBUTES, "attributes");
 }
 
@@ -168,3 +185,31 @@ seahorse_private_key_object_attributes_iface (GckObjectAttributesIface *iface)
 	iface->attribute_types = REQUIRED_ATTRS;
 	iface->n_attribute_types = G_N_ELEMENTS (REQUIRED_ATTRS);
 }
+
+SeahorseCertificate *
+seahorse_private_key_get_certificate (SeahorsePrivateKey *self)
+{
+	g_return_val_if_fail (SEAHORSE_IS_PRIVATE_KEY (self), NULL);
+	return self->pv->certificate;
+}
+
+void
+seahorse_private_key_set_certificate (SeahorsePrivateKey *self,
+                                      SeahorseCertificate *certificate)
+{
+	GObject *obj;
+
+	g_return_if_fail (SEAHORSE_IS_PRIVATE_KEY (self));
+	g_return_if_fail (certificate == NULL || SEAHORSE_IS_CERTIFICATE (certificate));
+
+	if (self->pv->certificate)
+		g_object_remove_weak_pointer (G_OBJECT (certificate),
+		                              (gpointer *)self->pv->certificate);
+	self->pv->certificate = certificate;
+	if (self->pv->certificate)
+		g_object_add_weak_pointer (G_OBJECT (certificate),
+		                           (gpointer *)self->pv->certificate);
+
+	obj = G_OBJECT (self);
+	g_object_notify (obj, "certificate");
+}
diff --git a/pkcs11/seahorse-private-key.h b/pkcs11/seahorse-private-key.h
index b15d4c4..f80aba7 100644
--- a/pkcs11/seahorse-private-key.h
+++ b/pkcs11/seahorse-private-key.h
@@ -26,6 +26,8 @@
 
 #include <glib-object.h>
 
+#include "seahorse-certificate.h"
+
 #define SEAHORSE_TYPE_PRIVATE_KEY               (seahorse_private_key_get_type ())
 #define SEAHORSE_PRIVATE_KEY(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_PRIVATE_KEY, SeahorsePrivateKey))
 #define SEAHORSE_PRIVATE_KEY_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_PRIVATE_KEY, SeahorsePrivateKeyClass))
@@ -33,7 +35,6 @@
 #define SEAHORSE_IS_PRIVATE_KEY_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_PRIVATE_KEY))
 #define SEAHORSE_PRIVATE_KEY_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_PRIVATE_KEY, SeahorsePrivateKeyClass))
 
-typedef struct _SeahorsePrivateKey SeahorsePrivateKey;
 typedef struct _SeahorsePrivateKeyClass SeahorsePrivateKeyClass;
 typedef struct _SeahorsePrivateKeyPrivate SeahorsePrivateKeyPrivate;
 
@@ -48,4 +49,9 @@ struct _SeahorsePrivateKeyClass {
 
 GType                 seahorse_private_key_get_type           (void) G_GNUC_CONST;
 
+SeahorseCertificate * seahorse_private_key_get_certificate    (SeahorsePrivateKey *self);
+
+void                  seahorse_private_key_set_certificate    (SeahorsePrivateKey *self,
+                                                               SeahorseCertificate *certificate);
+
 #endif /* __SEAHORSE_PRIVATE_KEY_H__ */
diff --git a/pkcs11/seahorse-token.c b/pkcs11/seahorse-token.c
index 1e98d49..ae79576 100644
--- a/pkcs11/seahorse-token.c
+++ b/pkcs11/seahorse-token.c
@@ -58,15 +58,15 @@ enum {
 struct _SeahorseTokenPrivate {
 	GckSlot *slot;
 	gchar *uri;
-	GHashTable *objects;
 	GckTokenInfo *info;
 	GckSession *session;
 	GtkActionGroup *actions;
+	GHashTable *object_for_handle;
+	GHashTable *objects_for_id;
+	GHashTable *id_for_object;
+	GHashTable *objects_visible;
 };
 
-static void          receive_object                      (SeahorseToken *self,
-                                                          GckObject *obj);
-
 static void          seahorse_token_place_iface          (SeahorsePlaceIface *iface);
 
 static void          seahorse_token_collection_iface     (GcrCollectionIface *iface);
@@ -76,6 +76,254 @@ G_DEFINE_TYPE_EXTENDED (SeahorseToken, seahorse_token, G_TYPE_OBJECT, 0,
                         G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_PLACE, seahorse_token_place_iface);
 );
 
+static void
+update_token_info (SeahorseToken *self)
+{
+	GckTokenInfo *info;
+	GObject *obj;
+
+	info = gck_slot_get_token_info (self->pv->slot);
+	if (info != NULL) {
+		gck_token_info_free (self->pv->info);
+		self->pv->info = info;
+
+		obj = G_OBJECT (self);
+		g_object_notify (obj, "info");
+		g_object_notify (obj, "lockable");
+		g_object_notify (obj, "unlockable");
+	}
+}
+
+static void
+update_id_map (SeahorseToken *self,
+               gpointer object,
+               GckAttribute *id)
+{
+	GPtrArray *objects;
+	GckAttribute *pid;
+	gboolean remove = FALSE;
+	gboolean add = FALSE;
+
+	/* See if this object was here before */
+	pid = g_hash_table_lookup (self->pv->id_for_object, object);
+
+	/* Decide what we're going to do */
+	if (id == NULL) {
+		if (pid != NULL) {
+			id = pid;
+			remove = TRUE;
+		}
+	} else {
+		if (pid == NULL) {
+			add = TRUE;
+		} else if (!gck_attribute_equal (id, pid)) {
+			remove = TRUE;
+			add = TRUE;
+		}
+	}
+
+	if (add) {
+		if (!g_hash_table_lookup_extended (self->pv->objects_for_id, id,
+		                                   (gpointer *)&id, (gpointer *)&objects)) {
+			objects = g_ptr_array_new ();
+			id = gck_attribute_dup (id);
+			g_hash_table_insert (self->pv->objects_for_id, id, objects);
+		}
+		g_ptr_array_add (objects, object);
+		g_hash_table_insert (self->pv->id_for_object, object, id);
+	}
+
+	/* Remove this object from the map */
+	if (remove) {
+		if (!g_hash_table_remove (self->pv->id_for_object, object))
+			g_assert_not_reached ();
+		objects = g_hash_table_lookup (self->pv->objects_for_id, id);
+		g_assert (objects != NULL);
+		g_assert (objects->len > 0);
+		if (objects->len == 1) {
+			if (!g_hash_table_remove (self->pv->objects_for_id, id))
+				g_assert_not_reached ();
+		} else {
+			if (!g_ptr_array_remove (objects, object))
+				g_assert_not_reached ();
+		}
+	}
+}
+
+static gpointer
+lookup_id_map (SeahorseToken *self,
+               GType object_type,
+               GckAttribute *id)
+{
+	GPtrArray *objects;
+	guint i;
+
+	objects = g_hash_table_lookup (self->pv->objects_for_id, id);
+	if (objects == NULL)
+		return NULL;
+
+	for (i = 0; i < objects->len; i++) {
+		if (G_TYPE_CHECK_INSTANCE_TYPE (objects->pdata[i], object_type))
+			return objects->pdata[i];
+	}
+
+	return NULL;
+}
+
+static void
+update_visibility (SeahorseToken *self,
+                   GList *objects,
+                   gboolean visible)
+{
+	gboolean have;
+	gpointer object;
+	GList *l;
+
+	for (l = objects; l != NULL; l = g_list_next (l)) {
+		object = l->data;
+		have = g_hash_table_lookup (self->pv->objects_visible, object) != NULL;
+		if (!have && visible) {
+			g_hash_table_insert (self->pv->objects_visible, object, object);
+			gcr_collection_emit_added (GCR_COLLECTION (self), object);
+		} else if (have && !visible) {
+			if (!g_hash_table_remove (self->pv->objects_visible, object))
+				g_assert_not_reached ();
+			gcr_collection_emit_removed (GCR_COLLECTION (self), object);
+		}
+	}
+}
+
+static gboolean
+make_certificate_key_pair (SeahorseCertificate *certificate,
+                           SeahorsePrivateKey *private_key)
+{
+	if (seahorse_certificate_get_private_key (certificate) ||
+	    seahorse_private_key_get_certificate (private_key))
+		return FALSE;
+
+	seahorse_certificate_set_private_key (certificate, private_key);
+	seahorse_private_key_set_certificate (private_key, certificate);
+	return TRUE;
+}
+
+static gpointer
+break_certificate_key_pair (gpointer object)
+{
+	SeahorseCertificate *certificate = NULL;
+	SeahorsePrivateKey *private_key = NULL;
+	gpointer pair;
+
+	if (SEAHORSE_IS_CERTIFICATE (object)) {
+		certificate = SEAHORSE_CERTIFICATE (object);
+		pair = seahorse_certificate_get_private_key (certificate);
+		seahorse_certificate_set_private_key (certificate, NULL);
+	} else if (SEAHORSE_IS_PRIVATE_KEY (object)) {
+		private_key = SEAHORSE_PRIVATE_KEY (object);
+		pair = seahorse_private_key_get_certificate (private_key);
+		seahorse_private_key_set_certificate (private_key, NULL);
+	} else {
+		pair = NULL;
+	}
+
+	return pair;
+}
+
+static void
+receive_objects (SeahorseToken *self,
+                 GList *objects)
+{
+	GckAttributes *attrs;
+	GckAttribute *id;
+	gpointer object;
+	gpointer prev;
+	gpointer pair;
+	gulong handle;
+	GList *show = NULL;
+	GList *hide = NULL;
+	GList *l;
+
+	for (l = objects; l != NULL; l = g_list_next (l)) {
+		object = l->data;
+		handle = gck_object_get_handle (object);
+		attrs = gck_object_attributes_get_attributes (object);
+
+		prev = g_hash_table_lookup (self->pv->object_for_handle, &handle);
+		if (prev == NULL) {
+			g_hash_table_insert (self->pv->object_for_handle,
+			                     g_memdup (&handle, sizeof (handle)),
+			                     g_object_ref (object));
+			g_object_set (object, "place", self, NULL);
+		} else if (prev != object) {
+			gck_object_attributes_set_attributes (prev, attrs);
+			object = prev;
+		}
+
+		id = gck_attributes_find (attrs, CKA_ID);
+		update_id_map (self, object, id);
+
+		if (SEAHORSE_IS_CERTIFICATE (object)) {
+			pair = lookup_id_map (self, SEAHORSE_TYPE_PRIVATE_KEY, id);
+			if (pair && make_certificate_key_pair (object, pair))
+				hide = g_list_prepend (hide, pair);
+			show = g_list_prepend (show, object);
+
+		} else if (SEAHORSE_IS_PRIVATE_KEY (object)) {
+			pair = lookup_id_map (self, SEAHORSE_TYPE_CERTIFICATE, id);
+			if (pair && make_certificate_key_pair (pair, object))
+				hide = g_list_prepend (hide, object);
+			else
+				show = g_list_prepend (show, object);
+
+		} else {
+			show = g_list_prepend (show, object);
+		}
+
+		gck_attributes_unref (attrs);
+	}
+
+	update_visibility (self, hide, FALSE);
+	g_list_free (hide);
+
+	update_visibility (self, show, TRUE);
+	g_list_free (show);
+}
+
+static void
+remove_objects (SeahorseToken *self,
+                GList *objects)
+{
+	GList *depaired = NULL;
+	GList *hide = NULL;
+	gulong handle;
+	gpointer object;
+	gpointer pair;
+	GList *l;
+
+	for (l = objects; l != NULL; l = g_list_next (l)) {
+		object = l->data;
+		pair = break_certificate_key_pair (object);
+		if (pair != NULL)
+			depaired = g_list_prepend (depaired, pair);
+		update_id_map (self, object, NULL);
+		hide = g_list_prepend (hide, object);
+	}
+
+	/* Remove the ownership of these */
+	for (l = objects; l != NULL; l = g_list_next (l)) {
+		handle = gck_object_get_handle (l->data);
+		g_object_set (object, "place", NULL, NULL);
+		g_hash_table_remove (self->pv->object_for_handle, &handle);
+	}
+
+	update_visibility (self, hide, FALSE);
+	g_list_free (hide);
+
+	/* Add everything that was paired */
+	receive_objects (self, depaired);
+	g_list_free (depaired);
+}
+
+
 typedef struct {
 	SeahorseToken *token;
 	GCancellable *cancellable;
@@ -94,17 +342,6 @@ pkcs11_refresh_free (gpointer data)
 	g_free (closure);
 }
 
-static gboolean
-remove_each_object (gpointer key,
-                    gpointer value,
-                    gpointer user_data)
-{
-	SeahorseToken *token = SEAHORSE_TOKEN (user_data);
-	GckObject *object = GCK_OBJECT (value);
-	seahorse_token_remove_object (token, object);
-	return TRUE;
-}
-
 static void
 on_refresh_next_objects (GObject *source,
                          GAsyncResult *result,
@@ -119,9 +356,10 @@ on_refresh_next_objects (GObject *source,
 
 	objects = gck_enumerator_next_finish (closure->enumerator, result, &error);
 
-	/* Remove all objects that were found, from the check table */
+	receive_objects (closure->token, objects);
+
+	/* Remove all objects that were found from the check table */
 	for (l = objects; l; l = g_list_next (l)) {
-		receive_object (closure->token, l->data);
 		handle = gck_object_get_handle (l->data);
 		g_hash_table_remove (closure->checks, &handle);
 	}
@@ -140,7 +378,10 @@ on_refresh_next_objects (GObject *source,
 
 	/* Otherwise we're done, remove everything not found */
 	} else {
-		g_hash_table_foreach_remove (closure->checks, remove_each_object, closure->token);
+		objects = g_hash_table_get_values (closure->checks);
+		remove_objects (closure->token, objects);
+		g_list_free (objects);
+
 		g_simple_async_result_complete (res);
 	}
 
@@ -148,24 +389,6 @@ on_refresh_next_objects (GObject *source,
 }
 
 static void
-update_token_info (SeahorseToken *self)
-{
-	GckTokenInfo *info;
-	GObject *obj;
-
-	info = gck_slot_get_token_info (self->pv->slot);
-	if (info != NULL) {
-		gck_token_info_free (self->pv->info);
-		self->pv->info = info;
-
-		obj = G_OBJECT (self);
-		g_object_notify (obj, "info");
-		g_object_notify (obj, "lockable");
-		g_object_notify (obj, "unlockable");
-	}
-}
-
-static void
 refresh_enumerate (GSimpleAsyncResult *res)
 {
 	RefreshClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
@@ -296,10 +519,16 @@ static void
 seahorse_token_init (SeahorseToken *self)
 {
 	self->pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_TOKEN, SeahorseTokenPrivate));
-	self->pv->objects = g_hash_table_new_full (seahorse_pkcs11_ulong_hash,
-	                                           seahorse_pkcs11_ulong_equal,
-	                                           g_free, g_object_unref);
 	self->pv->actions = seahorse_pkcs11_token_actions_instance ();
+	self->pv->object_for_handle = g_hash_table_new_full (seahorse_pkcs11_ulong_hash,
+	                                                     seahorse_pkcs11_ulong_equal,
+	                                                     g_free, g_object_unref);
+	self->pv->objects_for_id = g_hash_table_new_full (gck_attribute_hash,
+	                                                  gck_attribute_equal,
+	                                                  gck_attribute_free,
+	                                                  (GDestroyNotify)g_ptr_array_unref);
+	self->pv->id_for_object = g_hash_table_new (g_direct_hash, g_direct_equal);
+	self->pv->objects_visible = g_hash_table_new (g_direct_hash, g_direct_equal);
 }
 
 static void
@@ -429,7 +658,10 @@ seahorse_token_finalize (GObject *obj)
 {
 	SeahorseToken *self = SEAHORSE_TOKEN (obj);
 
-	g_hash_table_destroy (self->pv->objects);
+	g_hash_table_destroy (self->pv->objects_visible);
+	g_hash_table_destroy (self->pv->object_for_handle);
+	g_hash_table_destroy (self->pv->objects_for_id);
+	g_hash_table_destroy (self->pv->id_for_object);
 	g_assert (self->pv->slot == NULL);
 	g_clear_object (&self->pv->actions);
 	g_free (self->pv->uri);
@@ -491,14 +723,14 @@ static guint
 seahorse_token_get_length (GcrCollection *collection)
 {
 	SeahorseToken *self = SEAHORSE_TOKEN (collection);
-	return g_hash_table_size (self->pv->objects);
+	return g_hash_table_size (self->pv->objects_visible);
 }
 
 static GList *
 seahorse_token_get_objects (GcrCollection *collection)
 {
 	SeahorseToken *self = SEAHORSE_TOKEN (collection);
-	return g_hash_table_get_values (self->pv->objects);
+	return g_hash_table_get_values (self->pv->objects_visible);
 }
 
 static gboolean
@@ -506,13 +738,7 @@ seahorse_token_contains (GcrCollection *collection,
                          GObject *object)
 {
 	SeahorseToken *self = SEAHORSE_TOKEN (collection);
-	gulong handle;
-
-	if (!GCK_IS_OBJECT (object))
-		return FALSE;
-
-	handle = gck_object_get_handle (GCK_OBJECT (object));
-	return g_hash_table_lookup (self->pv->objects, &handle) == object;
+	return g_hash_table_lookup (self->pv->objects_visible, object) != NULL;
 }
 
 static void
@@ -636,51 +862,20 @@ seahorse_token_get_unlockable (SeahorseToken *self)
 		return FALSE;
 
 	return !is_session_logged_in (self->pv->session);
-
-}
-
-static void
-receive_object (SeahorseToken *self,
-                GckObject *obj)
-{
-	GckAttributes *attrs;
-	GckObject *prev;
-	gulong handle;
-
-	g_return_if_fail (SEAHORSE_IS_TOKEN (self));
-
-	handle = gck_object_get_handle (obj);
-	prev = g_hash_table_lookup (self->pv->objects, &handle);
-	if (prev != NULL) {
-		attrs = gck_object_attributes_get_attributes (GCK_OBJECT_ATTRIBUTES (obj));
-		gck_object_attributes_set_attributes (GCK_OBJECT_ATTRIBUTES (prev), attrs);
-		gck_attributes_unref (attrs);
-	} else {
-		g_hash_table_insert (self->pv->objects,
-		                     g_memdup (&handle, sizeof (handle)),
-		                     g_object_ref (obj));
-		gcr_collection_emit_added (GCR_COLLECTION (self), G_OBJECT (obj));
-	}
 }
 
 void
 seahorse_token_remove_object (SeahorseToken *self,
                               GckObject *object)
 {
-	gulong handle;
+	GList *objects;
 
 	g_return_if_fail (SEAHORSE_IS_TOKEN (self));
 	g_return_if_fail (GCK_IS_OBJECT (object));
 
-	g_object_ref (object);
-
-	handle = gck_object_get_handle (object);
-	g_return_if_fail (g_hash_table_lookup (self->pv->objects, &handle) == object);
-
-	g_hash_table_remove (self->pv->objects, &handle);
-	gcr_collection_emit_removed (GCR_COLLECTION (self), G_OBJECT (object));
-
-	g_object_unref (object);
+	objects = g_list_prepend (NULL, g_object_ref (object));
+	remove_objects (self, objects);
+	g_list_free_full (objects, g_object_unref);
 }
 
 static void



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