[gnome-keyring/dbus-api] [dbus] Refactor property parsing.



commit d6af3eabb5d2e2285c78760059fb055eb450c2bd
Author: Stef Walter <stef memberwebs com>
Date:   Thu Nov 12 01:36:59 2009 +0000

    [dbus] Refactor property parsing.
    
    Seperate the code that parses property variants into pkcs11
    attributes.

 daemon/dbus/Makefile.am           |    1 +
 daemon/dbus/gkd-secret-objects.c  |  493 +--------------------------------
 daemon/dbus/gkd-secret-objects.h  |    4 -
 daemon/dbus/gkd-secret-prompt.h   |    4 +
 daemon/dbus/gkd-secret-property.c |  559 +++++++++++++++++++++++++++++++++++++
 daemon/dbus/gkd-secret-property.h |   50 ++++
 6 files changed, 625 insertions(+), 486 deletions(-)
---
diff --git a/daemon/dbus/Makefile.am b/daemon/dbus/Makefile.am
index 8353bc9..ab99cad 100644
--- a/daemon/dbus/Makefile.am
+++ b/daemon/dbus/Makefile.am
@@ -19,6 +19,7 @@ libgkr_dbus_la_SOURCES = \
 	gkd-dbus-session.c \
 	gkd-dbus-util.c gkd-dbus-util.h \
 	gkd-secret-objects.c gkd-secret-objects.h \
+	gkd-secret-property.c gkd-secret-property.h \
 	gkd-secret-prompt.c gkd-secret-prompt.h \
 	gkd-secret-service.c gkd-secret-service.h \
 	gkd-secret-session.c gkd-secret-session.h \
diff --git a/daemon/dbus/gkd-secret-objects.c b/daemon/dbus/gkd-secret-objects.c
index b3a3fe1..2a52da4 100644
--- a/daemon/dbus/gkd-secret-objects.c
+++ b/daemon/dbus/gkd-secret-objects.c
@@ -25,6 +25,7 @@
 
 #include "gkd-secret-service.h"
 #include "gkd-secret-objects.h"
+#include "gkd-secret-property.h"
 #include "gkd-secret-types.h"
 #include "gkd-secret-util.h"
 
@@ -46,438 +47,10 @@ struct _GkdSecretObjects {
 
 G_DEFINE_TYPE (GkdSecretObjects, gkd_secret_objects, G_TYPE_OBJECT);
 
-typedef enum _DataType {
-	DATA_TYPE_INVALID = 0,
-
-	/*
-	 * The attribute is a CK_BBOOL.
-	 * Property is DBUS_TYPE_BOOLEAN
-	 */
-	DATA_TYPE_BOOL,
-
-	/*
-	 * The attribute is in the format: "%Y%m%d%H%M%S00"
-	 * Property is DBUS_TYPE_INT64 since 1970 epoch.
-	 */
-	DATA_TYPE_TIME,
-
-	/*
-	 * The attribute is a CK_UTF8_CHAR string, not null-terminated
-	 * Property is a DBUS_TYPE_STRING
-	 */
-	DATA_TYPE_STRING,
-
-	/*
-	 * The attribute is in the format: name\0value\0name2\0value2
-	 * Property is dbus dictionary of strings: a{ss}
-	 */
-	DATA_TYPE_FIELDS
-} DataType;
-
 /* -----------------------------------------------------------------------------
  * INTERNAL
  */
 
-static gboolean
-property_to_attribute (const gchar *prop_name, CK_ATTRIBUTE_TYPE *attr_type, DataType *data_type)
-{
-	g_return_val_if_fail (prop_name, FALSE);
-	g_assert (attr_type);
-	g_assert (data_type);
-
-	if (g_str_equal (prop_name, "Label")) {
-		*attr_type = CKA_LABEL;
-		*data_type = DATA_TYPE_STRING;
-
-	} else if (g_str_equal (prop_name, "Locked")) {
-		*attr_type = CKA_G_LOCKED;
-		*data_type = DATA_TYPE_BOOL;
-
-	} else if (g_str_equal (prop_name, "Created")) {
-		*attr_type = CKA_G_CREATED;
-		*data_type = DATA_TYPE_TIME;
-
-	} else if (g_str_equal (prop_name, "Modified")) {
-		*attr_type = CKA_G_MODIFIED;
-		*data_type = DATA_TYPE_TIME;
-
-	} else if (g_str_equal (prop_name, "Attributes")) {
-		*attr_type = CKA_G_FIELDS;
-		*data_type = DATA_TYPE_FIELDS;
-
-	} else {
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-static gboolean
-attribute_to_property (CK_ATTRIBUTE_TYPE attr_type, const gchar **prop_name, DataType *data_type)
-{
-	g_assert (prop_name);
-	g_assert (data_type);
-
-	switch (attr_type) {
-	case CKA_LABEL:
-		*prop_name = "Label";
-		*data_type = DATA_TYPE_STRING;
-		break;
-	case CKA_G_LOCKED:
-		*prop_name = "Locked";
-		*data_type = DATA_TYPE_BOOL;
-		break;
-	case CKA_G_CREATED:
-		*prop_name = "Created";
-		*data_type = DATA_TYPE_TIME;
-		break;
-	case CKA_G_MODIFIED:
-		*prop_name = "Modified";
-		*data_type = DATA_TYPE_TIME;
-		break;
-	case CKA_G_FIELDS:
-		*prop_name = "Attributes";
-		*data_type = DATA_TYPE_FIELDS;
-		break;
-	default:
-		return FALSE;
-	};
-
-	return TRUE;
-}
-
-typedef void (*IterAppendFunc) (DBusMessageIter*, GP11Attribute*);
-typedef gboolean (*IterGetFunc) (DBusMessageIter*, GP11Attribute*);
-
-static void
-iter_append_string (DBusMessageIter *iter, GP11Attribute *attr)
-{
-	gchar *value;
-
-	g_assert (iter);
-	g_assert (attr);
-
-	if (attr->length == 0) {
-		value = "";
-		dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &value);
-	} else {
-		value = g_strndup ((const gchar*)attr->value, attr->length);
-		dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &value);
-		g_free (value);
-	}
-}
-
-static gboolean
-iter_get_string (DBusMessageIter *iter, GP11Attribute* attr)
-{
-	const char *value;
-
-	g_assert (iter);
-	g_assert (attr);
-
-	g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING, FALSE);
-	dbus_message_iter_get_basic (iter, &value);
-	if (value == NULL)
-		value = "";
-	gp11_attribute_init_string (attr, attr->type, value);
-	return TRUE;
-}
-
-static void
-iter_append_bool (DBusMessageIter *iter, GP11Attribute *attr)
-{
-	dbus_bool_t value;
-
-	g_assert (iter);
-	g_assert (attr);
-
-	value = gp11_attribute_get_boolean (attr) ? TRUE : FALSE;
-	dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &value);
-}
-
-static gboolean
-iter_get_bool (DBusMessageIter *iter, GP11Attribute* attr)
-{
-	dbus_bool_t value;
-
-	g_assert (iter);
-	g_assert (attr);
-
-	g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BOOLEAN, FALSE);
-	dbus_message_iter_get_basic (iter, &value);
-	gp11_attribute_init_boolean (attr, attr->type, value ? TRUE : FALSE);
-	return TRUE;
-}
-
-static void
-iter_append_time (DBusMessageIter *iter, GP11Attribute *attr)
-{
-	gint64 value;
-	struct tm tm;
-	gchar buf[15];
-
-	g_assert (iter);
-	g_assert (attr);
-
-	if (attr->length == 0) {
-		value = -1;
-
-	} else if (!attr->value || attr->length != 16) {
-		g_warning ("invalid length of time attribute");
-		value = -1;
-
-	} else {
-		memset (&tm, 0, sizeof (tm));
-		memcpy (buf, attr->value, 14);
-		buf[14] = 0;
-
-		if (!strptime(buf, "%Y%m%d%H%M%S", &tm)) {
-			g_warning ("invalid format of time attribute");
-			value = -1;
-		}
-
-		/* Convert to seconds since epoch */
-		value = timegm (&tm);
-		if (value < 0) {
-			g_warning ("invalid time attribute");
-			value = -1;
-		}
-	}
-
-	dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &value);
-}
-
-static gboolean
-iter_get_time (DBusMessageIter *iter, GP11Attribute* attr)
-{
-	time_t time;
-	struct tm tm;
-	gchar buf[20];
-	gint64 value;
-
-	g_assert (iter);
-	g_assert (attr);
-
-	g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_INT64, FALSE);
-	dbus_message_iter_get_basic (iter, &value);
-	if (value < 0) {
-		gp11_attribute_init_empty (attr, attr->type);
-		return TRUE;
-	}
-
-	time = value;
-	if (!gmtime_r (&time, &tm))
-		g_return_val_if_reached (FALSE);
-
-	if (!strftime (buf, sizeof (buf), "%Y%m%d%H%M%S00", &tm))
-		g_return_val_if_reached (FALSE);
-
-	gp11_attribute_init (attr, attr->type, buf, 16);
-	return TRUE;
-}
-
-static void
-iter_append_fields (DBusMessageIter *iter, GP11Attribute *attr)
-{
-	DBusMessageIter array;
-	DBusMessageIter dict;
-	const gchar *ptr;
-	const gchar *last;
-	const gchar *name;
-	gsize n_name;
-	const gchar *value;
-	gsize n_value;
-	gchar *string;
-
-	g_assert (iter);
-	g_assert (attr);
-
-	ptr = (gchar*)attr->value;
-	last = ptr + attr->length;
-	g_return_if_fail (ptr || last == ptr);
-
-	dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "{ss}", &array);
-
-	while (ptr && ptr != last) {
-		g_assert (ptr < last);
-
-		name = ptr;
-		ptr = memchr (ptr, 0, last - ptr);
-		if (ptr == NULL) /* invalid */
-			break;
-
-		n_name = ptr - name;
-		value = ++ptr;
-		ptr = memchr (ptr, 0, last - ptr);
-		if (ptr == NULL) /* invalid */
-			break;
-
-		n_value = ptr - value;
-		++ptr;
-
-		dbus_message_iter_open_container (&array, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
-
-		string = g_strndup (name, n_name);
-		dbus_message_iter_append_basic (&dict, DBUS_TYPE_STRING, &string);
-		g_free (string);
-
-		string = g_strndup (value, n_value);
-		dbus_message_iter_append_basic (&dict, DBUS_TYPE_STRING, &string);
-		g_free (string);
-
-		dbus_message_iter_close_container (&array, &dict);
-	}
-
-	dbus_message_iter_close_container (iter, &array);
-}
-
-static gboolean
-iter_get_fields (DBusMessageIter *iter, GP11Attribute* attr)
-{
-	DBusMessageIter array;
-	DBusMessageIter dict;
-	GString *result;
-	const gchar *string;
-
-	g_assert (iter);
-
-	result = g_string_new ("");
-
-	g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, FALSE);
-	dbus_message_iter_recurse (iter, &array);
-
-	while (dbus_message_iter_get_arg_type (&array) == DBUS_TYPE_DICT_ENTRY) {
-		dbus_message_iter_recurse (&array, &dict);
-
-		/* Key */
-		g_return_val_if_fail (dbus_message_iter_get_arg_type (&dict) == DBUS_TYPE_STRING, FALSE);
-		dbus_message_iter_get_basic (&dict, &string);
-		g_string_append (result, string);
-		g_string_append_c (result, '\0');
-
-		dbus_message_iter_next (&dict);
-
-		/* Value */
-		g_return_val_if_fail (dbus_message_iter_get_arg_type (&dict) == DBUS_TYPE_STRING, FALSE);
-		dbus_message_iter_get_basic (&dict, &string);
-		g_string_append (result, string);
-		g_string_append_c (result, '\0');
-
-		dbus_message_iter_next (&array);
-	}
-
-	gp11_attribute_init (attr, attr->type, result->str, result->len);
-	g_string_free (result, TRUE);
-	return TRUE;
-}
-
-static void
-iter_append_variant (DBusMessageIter *iter, DataType data_type, GP11Attribute *attr)
-{
-	DBusMessageIter sub;
-	IterAppendFunc func;
-	const gchar *sig;
-
-	g_assert (iter);
-	g_assert (attr);
-
-	switch (data_type) {
-	case DATA_TYPE_STRING:
-		func = iter_append_string;
-		sig = DBUS_TYPE_STRING_AS_STRING;
-		break;
-	case DATA_TYPE_BOOL:
-		func = iter_append_bool;
-		sig = DBUS_TYPE_BOOLEAN_AS_STRING;
-		break;
-	case DATA_TYPE_TIME:
-		func = iter_append_time;
-		sig = DBUS_TYPE_INT64_AS_STRING;
-		break;
-	case DATA_TYPE_FIELDS:
-		func = iter_append_fields;
-		sig = "a{ss}";
-		break;
-	default:
-		g_assert (FALSE);
-		break;
-	}
-
-	dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, sig, &sub);
-	(func) (&sub, attr);
-	dbus_message_iter_close_container (iter, &sub);
-}
-
-static gboolean
-iter_get_variant (DBusMessageIter *iter, DataType data_type, GP11Attribute *attr)
-{
-	DBusMessageIter variant;
-	IterGetFunc func;
-	gboolean ret;
-	const gchar *sig;
-	char *signature;
-
-	g_assert (iter);
-	g_assert (attr);
-
-	g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_VARIANT, FALSE);
-	dbus_message_iter_recurse (iter, &variant);
-
-	switch (data_type) {
-	case DATA_TYPE_STRING:
-		func = iter_get_string;
-		sig = DBUS_TYPE_STRING_AS_STRING;
-		break;
-	case DATA_TYPE_BOOL:
-		func = iter_get_bool;
-		sig = DBUS_TYPE_BOOLEAN_AS_STRING;
-		break;
-	case DATA_TYPE_TIME:
-		func = iter_get_time;
-		sig = DBUS_TYPE_INT64_AS_STRING;
-		break;
-	case DATA_TYPE_FIELDS:
-		func = iter_get_fields;
-		sig = "a{ss}";
-		break;
-	default:
-		g_assert (FALSE);
-		break;
-	}
-
-	signature = dbus_message_iter_get_signature (&variant);
-	g_return_val_if_fail (signature, FALSE);
-	ret = g_str_equal (sig, signature);
-	dbus_free (signature);
-
-	if (ret == FALSE)
-		return FALSE;
-
-	return (func) (&variant, attr);
-}
-
-static void
-iter_append_property_dict (DBusMessageIter *iter, GP11Attributes *attrs)
-{
-	DBusMessageIter dict;
-	GP11Attribute *attr;
-	DataType data_type;
-	const gchar *name;
-	gulong num, i;
-
-	num = gp11_attributes_count (attrs);
-	for (i = 0; i < num; ++i) {
-		attr = gp11_attributes_at (attrs, i);
-		if (!attribute_to_property (attr->type, &name, &data_type))
-			g_return_if_reached ();
-
-		dbus_message_iter_open_container (iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
-		dbus_message_iter_append_basic (&dict, DBUS_TYPE_STRING, &name);
-		iter_append_variant (&dict, data_type, attr);
-		dbus_message_iter_close_container (iter, &dict);
-	}
-}
-
 static void
 iter_append_item_paths (DBusMessageIter *iter, GList *items)
 {
@@ -527,13 +100,10 @@ object_property_get (GP11Object *object, DBusMessage *message,
 	GError *error = NULL;
 	DBusMessage *reply;
 	GP11Attribute attr;
-	DataType data_type;
 
-	/* What type of property is it? */
-	if (!property_to_attribute (prop_name, &attr.type, &data_type)) {
+	if (!gkd_secret_property_get_type (prop_name, &attr.type))
 		return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED,
 		                                      "Object does not have the '%s' property", prop_name);
-	}
 
 	/* Retrieve the actual attribute */
 	attr.value = gp11_object_get_data (object, attr.type, &attr.length, &error);
@@ -548,7 +118,7 @@ object_property_get (GP11Object *object, DBusMessage *message,
 	/* Marshall the data back out */
 	reply = dbus_message_new_method_return (message);
 	dbus_message_iter_init_append (reply, &iter);
-	iter_append_variant (&iter, data_type, &attr);
+	gkd_secret_property_append_variant (&iter, &attr);
 	g_free (attr.value);
 	return reply;
 }
@@ -562,22 +132,20 @@ object_property_set (GP11Object *object, DBusMessage *message,
 	GP11Attribute *attr;
 	GError *error = NULL;
 	gulong attr_type;
-	DataType data_type;
 
 	g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_VARIANT, NULL);
 
 	/* What type of property is it? */
-	if (!property_to_attribute (prop_name, &attr_type, &data_type)) {
+	if (!gkd_secret_property_get_type (prop_name, &attr_type))
 		return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED,
 		                                      "Object does not have the '%s' property", prop_name);
-	}
 
 	attrs = gp11_attributes_new ();
 	gp11_attributes_add_empty (attrs, attr_type);
 	attr = gp11_attributes_at (attrs, 0);
 
 	/* Retrieve the actual attribute value */
-	if (!iter_get_variant (iter, data_type, attr)) {
+	if (!gkd_secret_property_parse_variant (iter, prop_name, attr)) {
 		gp11_attributes_unref (attrs);
 		return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED,
 		                                      "The property type or value was invalid: %s", prop_name);
@@ -678,7 +246,7 @@ item_property_getall (GP11Object *object, DBusMessage *message)
 
 	dbus_message_iter_init_append (reply, &iter);
 	dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
-	iter_append_property_dict (&array, attrs);
+	gkd_secret_property_append_all (&array, attrs);
 	dbus_message_iter_close_container (&iter, &array);
 	return reply;
 }
@@ -826,7 +394,7 @@ collection_property_getall (GkdSecretObjects *self, GP11Object *object, DBusMess
 	dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{sv}", &array);
 
 	/* Append all the usual properties */
-	iter_append_property_dict (&array, attrs);
+	gkd_secret_property_append_all (&array, attrs);
 
 	/* Append the Items property */
 	dbus_message_iter_open_container (&array, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
@@ -903,7 +471,7 @@ collection_method_create_item (GkdSecretObjects *self, GP11Object *object, DBusM
 	dbus_bool_t replace = FALSE;
 	GP11Attributes *attrs;
 	GP11Attribute *fields;
-	DBusMessageIter iter;
+	DBusMessageIter iter, array;
 	GP11Object *item = NULL;
 	const gchar *prompt;
 	GError *error = NULL;
@@ -918,7 +486,8 @@ collection_method_create_item (GkdSecretObjects *self, GP11Object *object, DBusM
 	if (!dbus_message_iter_init (message, &iter))
 		g_return_val_if_reached (NULL);
 	attrs = gp11_attributes_new ();
-	if (!gkd_secret_objects_parse_item_props (self, &iter, attrs)) {
+	dbus_message_iter_recurse (&iter, &array);
+	if (!gkd_secret_property_parse_all (&array, attrs)) {
 		gp11_attributes_unref (attrs);
 		return dbus_message_new_error_printf (message, DBUS_ERROR_INVALID_ARGS,
 		                                      "Invalid properties");
@@ -1195,46 +764,6 @@ gkd_secret_objects_dispatch (GkdSecretObjects *self, DBusMessage *message)
 	return reply;
 }
 
-gboolean
-gkd_secret_objects_parse_item_props (GkdSecretObjects *self, DBusMessageIter *iter,
-                                     GP11Attributes *attrs)
-{
-	DBusMessageIter array, dict;
-	CK_ATTRIBUTE_TYPE attr_type;
-	GP11Attribute *attr;
-	const char *name;
-	DataType data_type;
-
-	g_return_val_if_fail (GKD_SECRET_IS_OBJECTS (self), FALSE);
-	g_return_val_if_fail (iter, FALSE);
-	g_return_val_if_fail (attrs, FALSE);
-
-	dbus_message_iter_recurse (iter, &array);
-
-	while (dbus_message_iter_get_arg_type (&array) == DBUS_TYPE_DICT_ENTRY) {
-		dbus_message_iter_recurse (&array, &dict);
-
-		/* Property name */
-		g_return_val_if_fail (dbus_message_iter_get_arg_type (&dict) == DBUS_TYPE_STRING, FALSE);
-		dbus_message_iter_get_basic (&dict, &name);
-		dbus_message_iter_next (&dict);
-
-		if (!property_to_attribute (name, &attr_type, &data_type))
-			return FALSE;
-
-		/* Property value */
-		g_return_val_if_fail (dbus_message_iter_get_arg_type (&dict) == DBUS_TYPE_VARIANT, FALSE);
-		attr = gp11_attributes_add_empty (attrs, attr_type);
-		if (!iter_get_variant (&dict, data_type, attr))
-			return FALSE;
-
-		dbus_message_iter_next (&array);
-	}
-
-	return TRUE;
-}
-
-
 void
 gkd_secret_objects_append_item_paths (GkdSecretObjects *self, DBusMessageIter *iter,
                                       DBusMessage *message, GP11Object *collection)
@@ -1332,7 +861,7 @@ gkd_secret_objects_handle_search_items (GkdSecretObjects *self, DBusMessage *mes
 	attr = gp11_attributes_add_empty (attrs, CKA_G_FIELDS);
 
 	dbus_message_iter_init (message, &iter);
-	if (!iter_get_fields (&iter, attr)) {
+	if (!gkd_secret_property_parse_fields (&iter, attr)) {
 		gp11_attributes_unref (attrs);
 		return dbus_message_new_error (message, DBUS_ERROR_FAILED,
 		                               "Invalid data in attributes argument");
diff --git a/daemon/dbus/gkd-secret-objects.h b/daemon/dbus/gkd-secret-objects.h
index bb8fef7..c6dadbe 100644
--- a/daemon/dbus/gkd-secret-objects.h
+++ b/daemon/dbus/gkd-secret-objects.h
@@ -54,10 +54,6 @@ void                gkd_secret_objects_append_collection_paths   (GkdSecretObjec
                                                                   DBusMessageIter *iter,
                                                                   DBusMessage *message);
 
-gboolean            gkd_secret_objects_parse_item_props          (GkdSecretObjects *self,
-                                                                  DBusMessageIter *iter,
-                                                                  GP11Attributes *attrs);
-
 void                gkd_secret_objects_append_item_paths         (GkdSecretObjects *self,
                                                                   DBusMessageIter *iter,
                                                                   DBusMessage *message,
diff --git a/daemon/dbus/gkd-secret-prompt.h b/daemon/dbus/gkd-secret-prompt.h
index 4ca1ac9..de8c069 100644
--- a/daemon/dbus/gkd-secret-prompt.h
+++ b/daemon/dbus/gkd-secret-prompt.h
@@ -28,6 +28,10 @@
 
 #include "prompt/gkd-prompt.h"
 
+#include "gp11/gp11.h"
+
+#include <dbus/dbus.h>
+
 #define GKD_SECRET_TYPE_PROMPT               (gkd_secret_prompt_get_type ())
 #define GKD_SECRET_PROMPT(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GKD_SECRET_TYPE_PROMPT, GkdSecretPrompt))
 #define GKD_SECRET_PROMPT_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GKD_SECRET_TYPE_PROMPT, GkdSecretPromptClass))
diff --git a/daemon/dbus/gkd-secret-property.c b/daemon/dbus/gkd-secret-property.c
new file mode 100644
index 0000000..acd9e56
--- /dev/null
+++ b/daemon/dbus/gkd-secret-property.c
@@ -0,0 +1,559 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2008 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "gkd-secret-property.h"
+
+#include "pkcs11/pkcs11i.h"
+
+#include <string.h>
+
+
+typedef enum _DataType {
+	DATA_TYPE_INVALID = 0,
+
+	/*
+	 * The attribute is a CK_BBOOL.
+	 * Property is DBUS_TYPE_BOOLEAN
+	 */
+	DATA_TYPE_BOOL,
+
+	/*
+	 * The attribute is in the format: "%Y%m%d%H%M%S00"
+	 * Property is DBUS_TYPE_INT64 since 1970 epoch.
+	 */
+	DATA_TYPE_TIME,
+
+	/*
+	 * The attribute is a CK_UTF8_CHAR string, not null-terminated
+	 * Property is a DBUS_TYPE_STRING
+	 */
+	DATA_TYPE_STRING,
+
+	/*
+	 * The attribute is in the format: name\0value\0name2\0value2
+	 * Property is dbus dictionary of strings: a{ss}
+	 */
+	DATA_TYPE_FIELDS
+} DataType;
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+static gboolean
+property_to_attribute (const gchar *prop_name, CK_ATTRIBUTE_TYPE *attr_type, DataType *data_type)
+{
+	g_return_val_if_fail (prop_name, FALSE);
+	g_assert (attr_type);
+	g_assert (data_type);
+
+	if (g_str_equal (prop_name, "Label")) {
+		*attr_type = CKA_LABEL;
+		*data_type = DATA_TYPE_STRING;
+
+	} else if (g_str_equal (prop_name, "Locked")) {
+		*attr_type = CKA_G_LOCKED;
+		*data_type = DATA_TYPE_BOOL;
+
+	} else if (g_str_equal (prop_name, "Created")) {
+		*attr_type = CKA_G_CREATED;
+		*data_type = DATA_TYPE_TIME;
+
+	} else if (g_str_equal (prop_name, "Modified")) {
+		*attr_type = CKA_G_MODIFIED;
+		*data_type = DATA_TYPE_TIME;
+
+	} else if (g_str_equal (prop_name, "Attributes")) {
+		*attr_type = CKA_G_FIELDS;
+		*data_type = DATA_TYPE_FIELDS;
+
+	} else {
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gboolean
+attribute_to_property (CK_ATTRIBUTE_TYPE attr_type, const gchar **prop_name, DataType *data_type)
+{
+	g_assert (prop_name);
+	g_assert (data_type);
+
+	switch (attr_type) {
+	case CKA_LABEL:
+		*prop_name = "Label";
+		*data_type = DATA_TYPE_STRING;
+		break;
+	case CKA_G_LOCKED:
+		*prop_name = "Locked";
+		*data_type = DATA_TYPE_BOOL;
+		break;
+	case CKA_G_CREATED:
+		*prop_name = "Created";
+		*data_type = DATA_TYPE_TIME;
+		break;
+	case CKA_G_MODIFIED:
+		*prop_name = "Modified";
+		*data_type = DATA_TYPE_TIME;
+		break;
+	case CKA_G_FIELDS:
+		*prop_name = "Attributes";
+		*data_type = DATA_TYPE_FIELDS;
+		break;
+	default:
+		return FALSE;
+	};
+
+	return TRUE;
+}
+
+typedef void (*IterAppendFunc) (DBusMessageIter*, GP11Attribute*);
+typedef gboolean (*IterGetFunc) (DBusMessageIter*, GP11Attribute*);
+
+static void
+iter_append_string (DBusMessageIter *iter, GP11Attribute *attr)
+{
+	gchar *value;
+
+	g_assert (iter);
+	g_assert (attr);
+
+	if (attr->length == 0) {
+		value = "";
+		dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &value);
+	} else {
+		value = g_strndup ((const gchar*)attr->value, attr->length);
+		dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &value);
+		g_free (value);
+	}
+}
+
+static gboolean
+iter_get_string (DBusMessageIter *iter, GP11Attribute* attr)
+{
+	const char *value;
+
+	g_assert (iter);
+	g_assert (attr);
+
+	g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING, FALSE);
+	dbus_message_iter_get_basic (iter, &value);
+	if (value == NULL)
+		value = "";
+	gp11_attribute_init_string (attr, attr->type, value);
+	return TRUE;
+}
+
+static void
+iter_append_bool (DBusMessageIter *iter, GP11Attribute *attr)
+{
+	dbus_bool_t value;
+
+	g_assert (iter);
+	g_assert (attr);
+
+	value = gp11_attribute_get_boolean (attr) ? TRUE : FALSE;
+	dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &value);
+}
+
+static gboolean
+iter_get_bool (DBusMessageIter *iter, GP11Attribute* attr)
+{
+	dbus_bool_t value;
+
+	g_assert (iter);
+	g_assert (attr);
+
+	g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BOOLEAN, FALSE);
+	dbus_message_iter_get_basic (iter, &value);
+	gp11_attribute_init_boolean (attr, attr->type, value ? TRUE : FALSE);
+	return TRUE;
+}
+
+static void
+iter_append_time (DBusMessageIter *iter, GP11Attribute *attr)
+{
+	gint64 value;
+	struct tm tm;
+	gchar buf[15];
+
+	g_assert (iter);
+	g_assert (attr);
+
+	if (attr->length == 0) {
+		value = -1;
+
+	} else if (!attr->value || attr->length != 16) {
+		g_warning ("invalid length of time attribute");
+		value = -1;
+
+	} else {
+		memset (&tm, 0, sizeof (tm));
+		memcpy (buf, attr->value, 14);
+		buf[14] = 0;
+
+		if (!strptime(buf, "%Y%m%d%H%M%S", &tm)) {
+			g_warning ("invalid format of time attribute");
+			value = -1;
+		}
+
+		/* Convert to seconds since epoch */
+		value = timegm (&tm);
+		if (value < 0) {
+			g_warning ("invalid time attribute");
+			value = -1;
+		}
+	}
+
+	dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &value);
+}
+
+static gboolean
+iter_get_time (DBusMessageIter *iter, GP11Attribute* attr)
+{
+	time_t time;
+	struct tm tm;
+	gchar buf[20];
+	gint64 value;
+
+	g_assert (iter);
+	g_assert (attr);
+
+	g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_INT64, FALSE);
+	dbus_message_iter_get_basic (iter, &value);
+	if (value < 0) {
+		gp11_attribute_init_empty (attr, attr->type);
+		return TRUE;
+	}
+
+	time = value;
+	if (!gmtime_r (&time, &tm))
+		g_return_val_if_reached (FALSE);
+
+	if (!strftime (buf, sizeof (buf), "%Y%m%d%H%M%S00", &tm))
+		g_return_val_if_reached (FALSE);
+
+	gp11_attribute_init (attr, attr->type, buf, 16);
+	return TRUE;
+}
+
+static void
+iter_append_fields (DBusMessageIter *iter, GP11Attribute *attr)
+{
+	DBusMessageIter array;
+	DBusMessageIter dict;
+	const gchar *ptr;
+	const gchar *last;
+	const gchar *name;
+	gsize n_name;
+	const gchar *value;
+	gsize n_value;
+	gchar *string;
+
+	g_assert (iter);
+	g_assert (attr);
+
+	ptr = (gchar*)attr->value;
+	last = ptr + attr->length;
+	g_return_if_fail (ptr || last == ptr);
+
+	dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "{ss}", &array);
+
+	while (ptr && ptr != last) {
+		g_assert (ptr < last);
+
+		name = ptr;
+		ptr = memchr (ptr, 0, last - ptr);
+		if (ptr == NULL) /* invalid */
+			break;
+
+		n_name = ptr - name;
+		value = ++ptr;
+		ptr = memchr (ptr, 0, last - ptr);
+		if (ptr == NULL) /* invalid */
+			break;
+
+		n_value = ptr - value;
+		++ptr;
+
+		dbus_message_iter_open_container (&array, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
+
+		string = g_strndup (name, n_name);
+		dbus_message_iter_append_basic (&dict, DBUS_TYPE_STRING, &string);
+		g_free (string);
+
+		string = g_strndup (value, n_value);
+		dbus_message_iter_append_basic (&dict, DBUS_TYPE_STRING, &string);
+		g_free (string);
+
+		dbus_message_iter_close_container (&array, &dict);
+	}
+
+	dbus_message_iter_close_container (iter, &array);
+}
+
+static gboolean
+iter_get_fields (DBusMessageIter *iter, GP11Attribute* attr)
+{
+	DBusMessageIter array;
+	DBusMessageIter dict;
+	GString *result;
+	const gchar *string;
+
+	g_assert (iter);
+
+	result = g_string_new ("");
+
+	g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, FALSE);
+	dbus_message_iter_recurse (iter, &array);
+
+	while (dbus_message_iter_get_arg_type (&array) == DBUS_TYPE_DICT_ENTRY) {
+		dbus_message_iter_recurse (&array, &dict);
+
+		/* Key */
+		g_return_val_if_fail (dbus_message_iter_get_arg_type (&dict) == DBUS_TYPE_STRING, FALSE);
+		dbus_message_iter_get_basic (&dict, &string);
+		g_string_append (result, string);
+		g_string_append_c (result, '\0');
+
+		dbus_message_iter_next (&dict);
+
+		/* Value */
+		g_return_val_if_fail (dbus_message_iter_get_arg_type (&dict) == DBUS_TYPE_STRING, FALSE);
+		dbus_message_iter_get_basic (&dict, &string);
+		g_string_append (result, string);
+		g_string_append_c (result, '\0');
+
+		dbus_message_iter_next (&array);
+	}
+
+	gp11_attribute_init (attr, attr->type, result->str, result->len);
+	g_string_free (result, TRUE);
+	return TRUE;
+}
+
+static void
+iter_append_variant (DBusMessageIter *iter, DataType data_type, GP11Attribute *attr)
+{
+	DBusMessageIter sub;
+	IterAppendFunc func;
+	const gchar *sig;
+
+	g_assert (iter);
+	g_assert (attr);
+
+	switch (data_type) {
+	case DATA_TYPE_STRING:
+		func = iter_append_string;
+		sig = DBUS_TYPE_STRING_AS_STRING;
+		break;
+	case DATA_TYPE_BOOL:
+		func = iter_append_bool;
+		sig = DBUS_TYPE_BOOLEAN_AS_STRING;
+		break;
+	case DATA_TYPE_TIME:
+		func = iter_append_time;
+		sig = DBUS_TYPE_INT64_AS_STRING;
+		break;
+	case DATA_TYPE_FIELDS:
+		func = iter_append_fields;
+		sig = "a{ss}";
+		break;
+	default:
+		g_assert (FALSE);
+		break;
+	}
+
+	dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, sig, &sub);
+	(func) (&sub, attr);
+	dbus_message_iter_close_container (iter, &sub);
+}
+
+static gboolean
+iter_get_variant (DBusMessageIter *iter, DataType data_type, GP11Attribute *attr)
+{
+	DBusMessageIter variant;
+	IterGetFunc func;
+	gboolean ret;
+	const gchar *sig;
+	char *signature;
+
+	g_assert (iter);
+	g_assert (attr);
+
+	g_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_VARIANT, FALSE);
+	dbus_message_iter_recurse (iter, &variant);
+
+	switch (data_type) {
+	case DATA_TYPE_STRING:
+		func = iter_get_string;
+		sig = DBUS_TYPE_STRING_AS_STRING;
+		break;
+	case DATA_TYPE_BOOL:
+		func = iter_get_bool;
+		sig = DBUS_TYPE_BOOLEAN_AS_STRING;
+		break;
+	case DATA_TYPE_TIME:
+		func = iter_get_time;
+		sig = DBUS_TYPE_INT64_AS_STRING;
+		break;
+	case DATA_TYPE_FIELDS:
+		func = iter_get_fields;
+		sig = "a{ss}";
+		break;
+	default:
+		g_assert (FALSE);
+		break;
+	}
+
+	signature = dbus_message_iter_get_signature (&variant);
+	g_return_val_if_fail (signature, FALSE);
+	ret = g_str_equal (sig, signature);
+	dbus_free (signature);
+
+	if (ret == FALSE)
+		return FALSE;
+
+	return (func) (&variant, attr);
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC
+ */
+
+gboolean
+gkd_secret_property_get_type (const gchar *property, CK_ATTRIBUTE_TYPE *type)
+{
+	DataType data_type;
+
+	g_return_val_if_fail (property, FALSE);
+	g_return_val_if_fail (type, FALSE);
+
+	return property_to_attribute (property, type, &data_type);
+}
+
+gboolean
+gkd_secret_property_parse_all (DBusMessageIter *array, GP11Attributes *attrs)
+{
+	DBusMessageIter dict;
+	CK_ATTRIBUTE_TYPE attr_type;
+	GP11Attribute *attr;
+	const char *name;
+	DataType data_type;
+
+	g_return_val_if_fail (array, FALSE);
+	g_return_val_if_fail (attrs, FALSE);
+
+	while (dbus_message_iter_get_arg_type (array) == DBUS_TYPE_DICT_ENTRY) {
+		dbus_message_iter_recurse (array, &dict);
+
+		/* Property name */
+		g_return_val_if_fail (dbus_message_iter_get_arg_type (&dict) == DBUS_TYPE_STRING, FALSE);
+		dbus_message_iter_get_basic (&dict, &name);
+		dbus_message_iter_next (&dict);
+
+		if (!property_to_attribute (name, &attr_type, &data_type))
+			return FALSE;
+
+		/* Property value */
+		g_return_val_if_fail (dbus_message_iter_get_arg_type (&dict) == DBUS_TYPE_VARIANT, FALSE);
+		attr = gp11_attributes_add_empty (attrs, attr_type);
+		if (!iter_get_variant (&dict, data_type, attr))
+			return FALSE;
+
+		dbus_message_iter_next (array);
+	}
+
+	return TRUE;
+}
+
+gboolean
+gkd_secret_property_append_all (DBusMessageIter *array, GP11Attributes *attrs)
+{
+	DBusMessageIter dict;
+	GP11Attribute *attr;
+	DataType data_type;
+	const gchar *name;
+	gulong num, i;
+
+	g_return_val_if_fail (array, FALSE);
+	g_return_val_if_fail (attrs, FALSE);
+
+	num = gp11_attributes_count (attrs);
+	for (i = 0; i < num; ++i) {
+		attr = gp11_attributes_at (attrs, i);
+		if (!attribute_to_property (attr->type, &name, &data_type))
+			g_return_val_if_reached (FALSE);
+
+		dbus_message_iter_open_container (array, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
+		dbus_message_iter_append_basic (&dict, DBUS_TYPE_STRING, &name);
+		iter_append_variant (&dict, data_type, attr);
+		dbus_message_iter_close_container (array, &dict);
+	}
+
+	return TRUE;
+}
+
+gboolean
+gkd_secret_property_append_variant (DBusMessageIter *iter, GP11Attribute *attr)
+{
+	const gchar *property;
+	DataType data_type;
+
+	g_return_val_if_fail (attr, FALSE);
+	g_return_val_if_fail (iter, FALSE);
+
+	if (!attribute_to_property (attr->type, &property, &data_type))
+		return FALSE;
+	iter_append_variant (iter, data_type, attr);
+	return TRUE;
+}
+
+gboolean
+gkd_secret_property_parse_variant (DBusMessageIter *iter, const gchar *property,
+                                   GP11Attribute *attr)
+{
+	CK_ATTRIBUTE_TYPE attr_type;
+	DataType data_type;
+
+	g_return_val_if_fail (attr, FALSE);
+	g_return_val_if_fail (iter, FALSE);
+	g_return_val_if_fail (property, FALSE);
+
+	if (!property_to_attribute (property, &attr_type, &data_type))
+		return FALSE;
+
+	attr->type = attr_type;
+	return iter_get_variant (iter, data_type, attr);
+}
+
+gboolean
+gkd_secret_property_parse_fields (DBusMessageIter *iter, GP11Attribute *attr)
+{
+	g_return_val_if_fail (attr, FALSE);
+	g_return_val_if_fail (iter, FALSE);
+
+	attr->type = CKA_G_FIELDS;
+	return iter_get_fields (iter, attr);
+}
diff --git a/daemon/dbus/gkd-secret-property.h b/daemon/dbus/gkd-secret-property.h
new file mode 100644
index 0000000..c523a03
--- /dev/null
+++ b/daemon/dbus/gkd-secret-property.h
@@ -0,0 +1,50 @@
+/*
+ * gnome-keyring
+ *
+ * Copyright (C) 2009 Stefan Walter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __GKD_SECRET_PROPERTY_H__
+#define __GKD_SECRET_PROPERTY_H__
+
+#include "gkd-secret-types.h"
+
+#include "gp11/gp11.h"
+
+#include <dbus/dbus.h>
+
+gboolean               gkd_secret_property_get_type               (const gchar *property,
+                                                                   CK_ATTRIBUTE_TYPE *type);
+
+gboolean               gkd_secret_property_append_variant         (DBusMessageIter *iter,
+                                                                   GP11Attribute *attr);
+
+gboolean               gkd_secret_property_append_all             (DBusMessageIter *array,
+                                                                   GP11Attributes *attrs);
+
+gboolean               gkd_secret_property_parse_variant          (DBusMessageIter *iter,
+                                                                   const gchar *property,
+                                                                   GP11Attribute *attr);
+
+gboolean               gkd_secret_property_parse_fields           (DBusMessageIter *iter,
+                                                                   GP11Attribute *attr);
+
+gboolean               gkd_secret_property_parse_all              (DBusMessageIter *array,
+                                                                   GP11Attributes *attrs);
+
+#endif /* __GKD_SECRET_PROPERTY_H__ */



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