[gnome-keyring/dbus-api] [secrets] Complete some parts of the secrets fields code.



commit 193b002e32a4f657e80c3742215f1b4d87849bc3
Author: Stef Walter <stef memberwebs com>
Date:   Fri Jul 31 04:32:05 2009 +0000

    [secrets] Complete some parts of the secrets fields code.
    
    Including compat stuff to work with old uint32 and hashed
    attributes present in keyrings, but not in the secrets api.

 pkcs11/secret-store/gck-secret-binary.c     |  134 ++++++-----
 pkcs11/secret-store/gck-secret-collection.c |    7 +
 pkcs11/secret-store/gck-secret-fields.c     |  319 ++++++++++++++++++++++++---
 pkcs11/secret-store/gck-secret-fields.h     |   79 ++++++--
 4 files changed, 437 insertions(+), 102 deletions(-)
---
diff --git a/pkcs11/secret-store/gck-secret-binary.c b/pkcs11/secret-store/gck-secret-binary.c
index 073b6c2..3ee0d49 100644
--- a/pkcs11/secret-store/gck-secret-binary.c
+++ b/pkcs11/secret-store/gck-secret-binary.c
@@ -62,7 +62,6 @@ typedef struct {
 	guint32 id;
 	gchar *identifier;
 	guint32 type;
-	GHashTable *hashed_attributes;
 
 	/* encrypted: */
 	char *display_name;
@@ -173,19 +172,12 @@ buffer_get_raw_secret (EggBuffer *buffer, gsize offset, gsize *next_offset,
 	return TRUE;
 }
 
-typedef struct _AttributesCtx {
-	EggBuffer *buffer;
-	GHashTable *attributes;
-} AttributesCtx;
-
 static void
-add_each_attribute (gpointer key, gpointer value, gpointer user_data)
+buffer_add_attribute (EggBuffer *buffer, GHashTable *attributes, const gchar *key)
 {
-	AttributesCtx *ctx = user_data;
 	guint32 number;
-	gchar *end;
 	
-	buffer_add_utf8_string (ctx->buffer, key);
+	buffer_add_utf8_string (buffer, key);
 	
 	/* 
 	 * COMPATIBILITY:
@@ -199,32 +191,61 @@ add_each_attribute (gpointer key, gpointer value, gpointer user_data)
 	 */
 	
 	/* Determine if it's a uint32 compatible value, and store as such if it is */
-	if (gck_secret_fields_has_word (ctx->attributes, "compat-uint32", key)) {
-		number = strtoul (value, &end, 10);
-		if (!*end) {
-			egg_buffer_add_uint32 (ctx->buffer, 1);
-			egg_buffer_add_uint32 (ctx->buffer, number);
-			return;
-		}
+	if (gck_secret_fields_get_compat_uint32 (attributes, key, &number)) {
+		egg_buffer_add_uint32 (buffer, 1);
+		egg_buffer_add_uint32 (buffer, number);
+
+	/* A normal string attribute */
+	} else {
+		egg_buffer_add_uint32 (buffer, 0);
+		buffer_add_utf8_string (buffer, gck_secret_fields_get (attributes, key));
 	}
-	
-	/* A standard string attribute */
-	egg_buffer_add_uint32 (ctx->buffer, 0);
-	buffer_add_utf8_string (ctx->buffer, value);
 }
 
+static void
+buffer_add_hashed_attribute (EggBuffer *buffer, GHashTable *attributes, const gchar *key)
+{
+	guint32 number;
+	gchar *value;
+
+	buffer_add_utf8_string (buffer, key);
+
+	/* See comments in buffer_add_attribute. */
+
+	/* Determine if it's a uint32 compatible value, and store as such if it is */
+	if (gck_secret_fields_get_compat_hashed_uint32 (attributes, key, &number)) {
+		egg_buffer_add_uint32 (buffer, 1);
+		egg_buffer_add_uint32 (buffer, number);
+
+	/* A standard string attribute */
+	} else {
+		if (!gck_secret_fields_get_compat_hashed_string (attributes, key, &value))
+			g_return_if_reached ();
+		egg_buffer_add_uint32 (buffer, 0);
+		buffer_add_utf8_string (buffer, value);
+		g_free (value);
+	}
+}
 
 static gboolean
-buffer_add_attributes (EggBuffer *buffer, GHashTable *attributes)
+buffer_add_attributes (EggBuffer *buffer, GHashTable *attributes, gboolean hashed)
 {
-	AttributesCtx ctx;
+	GList *names, *l;
+	
+	g_assert (buffer);
+	
 	if (attributes == NULL) {
 		egg_buffer_add_uint32 (buffer, 0);
 	} else {
-		ctx.buffer = buffer;
-		ctx.attributes = attributes;
-		egg_buffer_add_uint32 (buffer, g_hash_table_size (attributes));
-		g_hash_table_foreach (attributes, add_each_attribute, &ctx);
+		names = gck_secret_fields_get_names (attributes);
+		egg_buffer_add_uint32 (buffer, g_list_length (names));
+		for (l = names; l; l = g_list_next (l)) {
+			if (hashed)
+				buffer_add_hashed_attribute (buffer, attributes, l->data);
+			else
+				buffer_add_attribute (buffer, attributes, l->data);
+		}
+		g_list_free (names);
 	}
 	
 	return !egg_buffer_has_error (buffer);
@@ -232,11 +253,10 @@ buffer_add_attributes (EggBuffer *buffer, GHashTable *attributes)
 
 static gboolean
 buffer_get_attributes (EggBuffer *buffer, gsize offset, gsize *next_offset,
-                       GHashTable **attributes_out)
+                       GHashTable **attributes_out, gboolean hashed)
 {
 	guint32 list_size;
 	GHashTable *attributes;
-	GString *compat_uint32;
 	char *name;
 	guint32 type;
 	char *str;
@@ -244,7 +264,6 @@ buffer_get_attributes (EggBuffer *buffer, gsize offset, gsize *next_offset,
 	int i;
 
 	attributes = NULL;
-	compat_uint32 = g_string_new ("");
 	
 	if (!egg_buffer_get_uint32 (buffer, offset, &offset, &list_size))
 		goto bail;
@@ -263,18 +282,23 @@ buffer_get_attributes (EggBuffer *buffer, gsize offset, gsize *next_offset,
 				g_free (name);
 				goto bail;
 			}
-			g_hash_table_replace (attributes, name, str);
+			if (hashed)
+				gck_secret_fields_add_compat_hashed_string (attributes, name, str);
+			else
+				gck_secret_fields_add (attributes, name, str);
+			g_free (name);
+			g_free (str);
 			break;
 		case 1: /* A uint32 */
-			if (!egg_buffer_get_uint32 (buffer, offset, 
-			                            &offset, &val)) {
+			if (!egg_buffer_get_uint32 (buffer, offset, &offset, &val)) {
 				g_free (name);
 				goto bail;
 			}
-			g_string_append_c (compat_uint32, ' ');
-			g_string_append (compat_uint32, name);
-			str = g_strdup_printf ("%u", val);
-			g_hash_table_replace (attributes, name, str);
+			if (hashed)
+				gck_secret_fields_add_compat_hashed_uint32 (attributes, name, val);
+			else
+				gck_secret_fields_add_compat_uint32 (attributes, name, val);
+			g_free (name);
 			break;
 		default:
 			g_free (name);
@@ -282,18 +306,12 @@ buffer_get_attributes (EggBuffer *buffer, gsize offset, gsize *next_offset,
 		}
 	}
 	
-	if (compat_uint32->len)
-		g_hash_table_replace (attributes, "compat-uint32", g_string_free (compat_uint32, FALSE));
-	else
-		g_string_free (compat_uint32, TRUE);
-
 	*attributes_out = attributes;
 	*next_offset = offset;
 	
 	return TRUE;
 	
 bail:
-	g_string_free (compat_uint32, TRUE);
 	g_hash_table_unref (attributes);
 	return FALSE;
 }
@@ -490,9 +508,8 @@ generate_encrypted_data (EggBuffer *buffer, GckSecretCollection *collection)
 		for (i = 0; i < 4; i++)
 			egg_buffer_add_uint32 (buffer, 0);
 
-		/* Null attributes = empty attribute array */
 		attributes = gck_secret_item_get_fields (item);
-		if (!buffer_add_attributes (buffer, attributes))
+		if (!buffer_add_attributes (buffer, attributes, FALSE))
 			break;
 
 		acl = g_object_get_data (G_OBJECT (item), "compat-acl");
@@ -507,10 +524,9 @@ generate_encrypted_data (EggBuffer *buffer, GckSecretCollection *collection)
 }
 
 static gboolean
-generate_hashed_attributes (GckSecretCollection *collection, EggBuffer *buffer)
+generate_hashed_items (GckSecretCollection *collection, EggBuffer *buffer)
 {
 	GHashTable *attributes;
-	GHashTable *hashed;
 	const gchar *value;
 	GList *items, *l;
 	guint32 id, type;
@@ -526,14 +542,12 @@ generate_hashed_attributes (GckSecretCollection *collection, EggBuffer *buffer)
 		egg_buffer_add_uint32 (buffer, id);
 		
 		attributes = gck_secret_item_get_fields (l->data);
-		value = g_hash_table_lookup (attributes, "compat-item-type");
+		value = g_hash_table_lookup (attributes, "gkr:item-type");
 		if (!value || !convert_to_integer (value, &type))
 			type = 0;
 		egg_buffer_add_uint32 (buffer, type);
 		
-		hashed = gck_secret_fields_hash (attributes);
-		buffer_add_attributes (buffer, hashed);
-		g_hash_table_unref (hashed);
+		buffer_add_attributes (buffer, attributes, TRUE);
 	}
 	
 	g_list_free (items);
@@ -590,7 +604,7 @@ gck_secret_binary_write (GckSecretCollection *collection, guchar **data, gsize *
 		egg_buffer_add_uint32 (&buffer, 0);
 
 	/* Hashed items: */
-	generate_hashed_attributes (collection, &buffer);
+	generate_hashed_items (collection, &buffer);
 
 	/* Encrypted data. Use non-pageable memory */
 	egg_buffer_init_full (&to_encrypt, 4096, egg_secure_realloc);
@@ -714,16 +728,15 @@ setup_item_from_info (GckSecretItem *item, gboolean locked, ItemInfo *info)
 	gck_secret_object_set_modified (obj, info->mtime);
 	
 	type = g_strdup_printf ("%u", info->type);
-	
+
+	gck_secret_fields_add (info->attributes, "gkr:item-type", type);
+	gck_secret_item_set_fields (item, info->attributes);
+
 	if (locked) {
-		gck_secret_fields_add (info->hashed_attributes, "compat-item-type", type);
-		gck_secret_item_set_fields (item, info->hashed_attributes);
 		g_object_set_data (G_OBJECT (item), "compat-acl", NULL);
 		gck_secret_item_set_secret (item, NULL);
 		
 	} else {
-		gck_secret_fields_add (info->attributes, "compat-item-type", type);
-		gck_secret_item_set_fields (item, info->attributes);
 		secret = gck_login_new_from_password (info->secret);
 		gck_secret_item_set_secret (item, secret);
 		g_object_unref (secret);
@@ -738,7 +751,6 @@ static void
 free_item_info (ItemInfo *info)
 {
 	g_free (info->identifier);
-	g_hash_table_unref (info->hashed_attributes);
 	g_free (info->display_name);
 	egg_secure_free (info->secret);
 	g_hash_table_unref (info->attributes);
@@ -822,7 +834,7 @@ gck_secret_binary_read (GckSecretCollection *collection, const guchar *data, gsi
 	for (i = 0; i < num_items; i++) {
 		if (!egg_buffer_get_uint32 (&buffer, offset, &offset, &items[i].id) ||
 		    !egg_buffer_get_uint32 (&buffer, offset, &offset, &items[i].type) ||
-		    !buffer_get_attributes (&buffer, offset, &offset, &items[i].hashed_attributes))
+		    !buffer_get_attributes (&buffer, offset, &offset, &items[i].attributes, TRUE))
 			goto bail;
 		identifier = g_strdup_printf ("%u", items[i].id);
 	}
@@ -876,7 +888,9 @@ gck_secret_binary_read (GckSecretCollection *collection, const guchar *data, gsi
 					if (!egg_buffer_get_uint32 (&buffer, offset, &offset, &tmp))
 						goto bail;
 				}
-				if (!buffer_get_attributes (&buffer, offset, &offset, &items[i].attributes))
+				if (items[i].attributes)
+					g_hash_table_unref (items[i].attributes);
+				if (!buffer_get_attributes (&buffer, offset, &offset, &items[i].attributes, FALSE))
 					goto bail;
 				if (!decode_acl (&buffer, offset, &offset, &items[i].acl))
 					goto bail;
diff --git a/pkcs11/secret-store/gck-secret-collection.c b/pkcs11/secret-store/gck-secret-collection.c
index 5c41849..37a879c 100644
--- a/pkcs11/secret-store/gck-secret-collection.c
+++ b/pkcs11/secret-store/gck-secret-collection.c
@@ -209,3 +209,10 @@ gck_secret_collection_lookup_secret (GckSecretCollection *self,
 	g_return_val_if_fail (identifier, NULL);
 	return g_hash_table_lookup (self->secrets, identifier);
 }
+
+GList*
+gck_secret_collection_get_items (GckSecretCollection *self)
+{
+	g_return_val_if_fail (GCK_IS_SECRET_COLLECTION (self), NULL);
+	return g_list_copy (self->items);
+}
diff --git a/pkcs11/secret-store/gck-secret-fields.c b/pkcs11/secret-store/gck-secret-fields.c
index dfc6068..317bf62 100644
--- a/pkcs11/secret-store/gck-secret-fields.c
+++ b/pkcs11/secret-store/gck-secret-fields.c
@@ -23,11 +23,105 @@
 
 #include "gck-secret-fields.h"
 
+#include "egg/egg-hex.h"
+
 #include "gck/gck-attributes.h"
 
 #include <ctype.h>
 #include <string.h>
 
+static gboolean
+begins_with (const gchar *string, const gchar *prefix)
+{
+	gsize len = strlen (prefix);
+	return (strncmp (string, prefix, len) == 0);
+}
+
+static gboolean
+is_compat_name (const gchar *name)
+{
+	g_assert (name);
+	return begins_with (name, "gkr:compat:");
+}
+
+static gchar*
+make_compat_hashed_name (const gchar *name)
+{
+	g_assert (!is_compat_name (name));
+	return g_strdup_printf ("gkr:compat:hashed:%s", name);
+}
+
+static gchar*
+make_compat_uint32_name (const gchar *name)
+{
+	g_assert (!is_compat_name (name));
+	return g_strdup_printf ("gkr:compat:uint32:%s", name);
+}
+
+static gboolean
+string_ptr_equal (const gchar *one, const gchar *two)
+{
+	if (one == two)
+		return TRUE;
+	if (!one || !two)
+		return FALSE;
+	return g_str_equal (one, two);
+}
+
+static gint
+string_ptr_compare (gconstpointer one, gconstpointer two)
+{
+	if (one == two)
+		return 0;
+	if (!one || !two)
+		return one < two;
+	return strcmp (one, two);
+}
+
+static gboolean
+parse_uint32 (const gchar *value, guint32 *result)
+{
+	gchar *end;
+	g_assert (value);
+	g_assert (result);
+	*result = strtoul(value, &end, 10);
+	return (*end == '\0');
+}
+
+static gchar*
+format_uint32 (guint32 value)
+{
+	return g_strdup_printf ("%u", value);
+}
+
+static gboolean
+compat_hash_value_as_uint32 (const gchar *value, guint32 *hash)
+{
+	guint32 x;
+
+	if (!value || !parse_uint32 (value, &x))
+		return FALSE;
+
+	/* The same algorithm as the old keyring code used */
+	*hash = 0x18273645 ^ x ^ (x << 16 | x >> 16);
+	return TRUE;
+}
+
+static gchar*
+compat_hash_value_as_string (const gchar *value)
+{
+	guchar digest[16];
+
+	if (!value)
+		return NULL;
+
+	g_assert (gcry_md_get_algo_dlen (GCRY_MD_MD5) == sizeof (digest));
+	gcry_md_hash_buffer (GCRY_MD_MD5, (void*)digest, value, strlen (value));
+
+	/* The old keyring code used lower case hex */
+	return egg_hex_encode_full (digest, sizeof (digest), FALSE, '\0', 0);
+}
+
 GType
 gck_secret_fields_boxed_type (void)
 {
@@ -152,50 +246,223 @@ gboolean
 gck_secret_fields_match (GHashTable *haystack, GHashTable *needle)
 {
 	GHashTableIter iter;
-	gpointer key, value, hay;
+	const gchar *key, *value, *hay;
+	gchar *other_key, *hashed;
+	gboolean match;
+	guint32 number;
 
 	g_return_val_if_fail (haystack, FALSE);
 	g_return_val_if_fail (needle, FALSE);
 
 	g_hash_table_iter_init (&iter, needle);
-	while (g_hash_table_iter_next (&iter, &key, &value)) {
+	while (g_hash_table_iter_next (&iter, (gpointer*)&key, (gpointer*)&value)) {
 		g_assert (key && value);
-		hay = g_hash_table_lookup (haystack, key);
-		if (hay == NULL)
-			return FALSE;
-		if (!g_str_equal (hay, value))
-			return FALSE;
+		
+		/* Compat attributes in the needle make no difference */
+		if (is_compat_name (key))
+			continue;
+
+		/* A direct match? */
+		if (g_hash_table_lookup_extended (haystack, key, NULL, (gpointer*)&hay)) {
+			match = string_ptr_equal (hay, value);
+			if (!match)
+				return FALSE;
+		}
+
+		/* Try to find a hashed value? */
+		other_key = make_compat_hashed_name (key);
+		match = g_hash_table_lookup_extended (haystack, other_key, NULL, (gpointer*)&hay);
+		g_free (other_key);
+
+		if (match) {
+
+			/*
+			 * Now since the old keyring code would hash in two different
+			 * ways depending on whether it was a uint32 or string,
+			 * we need to do the same here.
+			 */
+
+			other_key = make_compat_uint32_name (key);
+			if (g_hash_table_lookup (haystack, other_key)) {
+				hashed = NULL;
+				if (compat_hash_value_as_uint32 (value, &number))
+					hashed = format_uint32 (number);
+			} else {
+				hashed = compat_hash_value_as_string (value);
+			}
+			g_free (other_key);
+
+			/* Does the incoming hashed value match our hashed value? */
+			match = string_ptr_equal (hay, hashed);
+			g_free (hashed);
+
+			if (!match)
+				return FALSE;
+		}
 	}
 	
 	return TRUE;
 }
 
+void
+gck_secret_fields_add (GHashTable *fields, const gchar *name,
+                       const gchar *value)
+{
+	g_return_if_fail (fields);
+	g_return_if_fail (name);
+	g_hash_table_replace (fields, g_strdup (name), g_strdup (value));
+}
+
+const gchar*
+gck_secret_fields_get (GHashTable *fields, const gchar *name)
+{
+	g_return_val_if_fail (fields, NULL);
+	g_return_val_if_fail (name, NULL);
+	g_return_val_if_fail (!is_compat_name (name), NULL);
+	return g_hash_table_lookup (fields, name);
+}
+
+GList*
+gck_secret_fields_get_names (GHashTable *fields)
+{
+	const gchar *prefix = "gkr:compat:hashed:";
+	GList *keys, *l, *next;
+	gsize len = strlen (prefix);
+	gchar *last = NULL;
+
+	g_return_val_if_fail (fields, NULL);
+
+	keys = g_hash_table_get_keys (fields);
+
+	/* Include hashed compat attributes as their base name */
+	for (l = keys; l; l = g_list_next (l)) {
+		if (strncmp (prefix, l->data, len) == 0)
+			l->data = (gchar*)(l->data) + len;
+	}
+
+	/* Sort the list nicely */
+	keys = g_list_sort (keys, string_ptr_compare);
+
+	/* Remove all compat attributes, duplicates */
+	for (l = keys; l; l = next) {
+		next = g_list_next (l);
+		if (is_compat_name (l->data) || string_ptr_equal (last, l->data))
+			keys = g_list_delete_link (keys, l);
+		else
+			last = l->data;
+	}
+
+	return keys;
+}
+
+void
+gck_secret_fields_add_compat_uint32 (GHashTable *fields, const gchar *name,
+                                     guint32 value)
+{
+	g_return_if_fail (fields);
+	g_return_if_fail (name);
+	g_return_if_fail (!is_compat_name (name));
+	g_hash_table_replace (fields, g_strdup (name), format_uint32 (value));
+	g_hash_table_replace (fields, make_compat_uint32_name (name), g_strdup (name));
+}
+
 gboolean
-gck_secret_fields_has_word (GHashTable *fields, const gchar *name, const gchar *word)
+gck_secret_fields_get_compat_uint32 (GHashTable *fields, const gchar *name,
+                                     guint32 *value)
 {
-	const gchar *string;
-	const gchar *at;
-	gsize len = strlen (word);
+	gchar *other_key;
+	gboolean ret;
 
-	if (len == 0)
-		return FALSE;
+	g_return_val_if_fail (fields, FALSE);
+	g_return_val_if_fail (name, FALSE);
+	g_return_val_if_fail (value, FALSE);
+	g_return_val_if_fail (!is_compat_name (name), FALSE);
 
-	string = g_hash_table_lookup (fields, name);
-	if (!string)
-		return FALSE;
+	other_key = make_compat_uint32_name (name);
+	ret = g_hash_table_lookup (fields, other_key) != NULL;
+	g_free (other_key);
+
+	if (ret)
+		ret = parse_uint32 (g_hash_table_lookup (fields, name), value);
+
+	return ret;
+}
 
-	for (;;) {
-		at = strstr (string, word);
-		if (at == NULL)
-			return FALSE;
+void
+gck_secret_fields_add_compat_hashed_string (GHashTable *fields, const gchar *name,
+                                            const gchar *value)
+{
+	g_return_if_fail (fields);
+	g_return_if_fail (name);
+	g_return_if_fail (!is_compat_name (name));
+	g_hash_table_replace (fields, make_compat_hashed_name (name), g_strdup (value));
+}
+
+gboolean
+gck_secret_fields_get_compat_hashed_string (GHashTable *fields, const gchar *name,
+                                            gchar **value)
+{
+	gchar *other_key;
+	gboolean ret;
+	const gchar *val;
 
-		/* The word exists, is at beginning or end, or spaces around it */
-		if ((at == string || isspace (*(at - 1))) &&
-		    (*(at + len) == 0 || isspace (*(at + len))))
-			return TRUE;
+	g_return_val_if_fail (fields, FALSE);
+	g_return_val_if_fail (name, FALSE);
+	g_return_val_if_fail (value, FALSE);
+	g_return_val_if_fail (!is_compat_name (name), FALSE);
 
-		string = at + len;
+	/* Even though this is more expensive, it's far more common */
+	if (g_hash_table_lookup_extended (fields, name, NULL, (gpointer*)&val)) {
+		*value = compat_hash_value_as_string (val);
+		return TRUE;
 	}
+	
+	/* See if we already have it hashed */
+	other_key = make_compat_hashed_name (name);
+	ret = g_hash_table_lookup_extended (fields, other_key, NULL, (gpointer*)&val);
+	g_free (other_key);
+
+	if (ret)
+		*value = g_strdup (val);
+	return ret;
+}
+
+void
+gck_secret_fields_add_compat_hashed_uint32 (GHashTable *fields, const gchar *name, 
+                                            guint32 value)
+{
+	g_return_if_fail (fields);
+	g_return_if_fail (name);
+	g_return_if_fail (!is_compat_name (name));
+	g_hash_table_replace (fields, make_compat_hashed_name (name), format_uint32 (value));
+	g_hash_table_replace (fields, make_compat_uint32_name (name), g_strdup (name));
+}
 
-	g_assert_not_reached ();
+gboolean
+gck_secret_fields_get_compat_hashed_uint32 (GHashTable *fields, const gchar *name, 
+                                            guint32 *value)
+{
+	const gchar *val;
+	gchar *other_key;
+	gboolean ret;
+	
+	g_return_val_if_fail (fields, FALSE);
+	g_return_val_if_fail (name, FALSE);
+	g_return_val_if_fail (value, FALSE);
+	g_return_val_if_fail (!is_compat_name (name), FALSE);
+	
+	/* Even though this is more expensive, it's far more common */
+	other_key = make_compat_uint32_name (name);
+	ret = g_hash_table_lookup_extended (fields, other_key, NULL, (gpointer*)&val);
+	g_free (other_key);
+	if (ret && compat_hash_value_as_uint32 (val, value))
+		return TRUE;
+	
+	/* See if we already have it hashed */
+	other_key = make_compat_hashed_name (name);
+	ret = g_hash_table_lookup_extended (fields, other_key, NULL, (gpointer*)&val);
+	g_free (other_key);
+	if (ret)
+		ret = parse_uint32 (val, value);
+	return ret;	
 }
diff --git a/pkcs11/secret-store/gck-secret-fields.h b/pkcs11/secret-store/gck-secret-fields.h
index fe4d593..48e23af 100644
--- a/pkcs11/secret-store/gck-secret-fields.h
+++ b/pkcs11/secret-store/gck-secret-fields.h
@@ -27,29 +27,76 @@
 #include <glib.h>
 #include <glib-object.h>
 
-#define             GCK_BOXED_SECRET_FIELDS         (gck_secret_fields_boxed_type ())
+/*
+ * This represents a set of attributes from the secrets API. We 
+ * call them 'fields' here, so they don't get mixed up with the 
+ * PKCS#11 API's notion of attributes.
+ * 
+ * Each field has a name, and a string value. 
+ * 
+ * Previous versions of gnome-keyring had the notion of attributes
+ * that were integers. In this version everything is a string.
+ * 
+ * Compatibility attributes start with gkr:compat:
+ * 
+ * gkr:compat:uint32:xxxx  The presence of this attribute means that
+ * the xxxx attribute is a uint32 in older versions of gnome-keyring.
+ * The value of this attribute is insignificant.
+ * 
+ * gkr:compat:hashed:xxxx  This attribute contains a hashed version
+ * of xxxx. 
+ */
+
+#define         GCK_BOXED_SECRET_FIELDS                       (gck_secret_fields_boxed_type ())
+
+GType           gck_secret_fields_boxed_type                  (void);
+
+GHashTable*     gck_secret_fields_new                         (void);
+
+void            gck_secret_fields_add                         (GHashTable *fields,
+                                                               const gchar *name,
+                                                               const gchar *value);
+
+const gchar*    gck_secret_fields_get                         (GHashTable *fields,
+                                                               const gchar *name);
+
+CK_RV           gck_secret_fields_parse                       (CK_ATTRIBUTE_PTR attr,
+                                                               GHashTable **fields);
+
+CK_RV           gck_secret_fields_serialize                   (CK_ATTRIBUTE_PTR attr,
+                                                               GHashTable *fields);
+
+gboolean        gck_secret_fields_match                       (GHashTable *haystack,
+                                                               GHashTable *needle);
+
+GList*          gck_secret_fields_get_names                   (GHashTable *fields);
 
-GType               gck_secret_fields_boxed_type    (void);
+/* COMPAT ------------------------------------------------------------------------ */
 
-GHashTable*         gck_secret_fields_new           (void);
+GList*          gck_secret_fields_get_compat_hashed_names     (GHashTable *fields);
 
-void                gck_secret_fields_add           (GHashTable *fields,
-                                                     const gchar *name,
-                                                     const gchar *value);
+void            gck_secret_fields_add_compat_uint32           (GHashTable *fields, 
+                                                               const gchar *name,
+                                                               guint32 value);
 
-CK_RV               gck_secret_fields_parse         (CK_ATTRIBUTE_PTR attr,
-                                                     GHashTable **fields);
+gboolean        gck_secret_fields_get_compat_uint32           (GHashTable *fields,
+                                                               const gchar *name,
+                                                               guint32 *value);
 
-CK_RV               gck_secret_fields_serialize     (CK_ATTRIBUTE_PTR attr,
-                                                     GHashTable *fields);
+void            gck_secret_fields_add_compat_hashed_string    (GHashTable *fields, 
+                                                               const gchar *name,
+                                                               const gchar *value);
 
-gboolean            gck_secret_fields_match         (GHashTable *haystack,
-                                                     GHashTable *needle);
+gboolean        gck_secret_fields_get_compat_hashed_string    (GHashTable *fields, 
+                                                               const gchar *name,
+                                                               gchar **value);
 
-GHashTable*         gck_secret_fields_hash          (GHashTable *fields);
+void            gck_secret_fields_add_compat_hashed_uint32    (GHashTable *fields, 
+                                                               const gchar *name, 
+                                                               guint32 value);
 
-gboolean            gck_secret_fields_has_word      (GHashTable *fields,
-                                                     const gchar *name,
-                                                     const gchar *word);
+gboolean        gck_secret_fields_get_compat_hashed_uint32    (GHashTable *fields, 
+                                                               const gchar *name,
+                                                               guint32 *value);
 
 #endif /* __GCK_SECRET_FIELDS_H__ */



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