[telepathy-mission-control/master] mcd-account: allow non-string secrets by using GKeyFile's serialisation

Jonny Lamb jonny.lamb at collabora.co.uk
Mon Sep 14 11:09:22 PDT 2009


Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
---
 src/mcd-account.c |  485 ++++++++++++++++++++++++++++++-----------------------
 1 files changed, 272 insertions(+), 213 deletions(-)

diff --git a/src/mcd-account.c b/src/mcd-account.c
index 441f0aa..3da3248 100644
--- a/src/mcd-account.c
+++ b/src/mcd-account.c
@@ -66,6 +66,9 @@ GnomeKeyringPasswordSchema keyring_schema = {
         { NULL, 0 }
     }
 };
+
+#define MCD_GNOME_KEYRING_GROUP_NAME "group"
+#define MCD_GNOME_KEYRING_KEY_NAME "key"
 #endif
 
 #define DELAY_PROPERTY_CHANGED
@@ -359,6 +362,95 @@ mcd_account_loaded (McdAccount *account)
     g_object_unref (account);
 }
 
+static gboolean
+keyfile_set_value (GKeyFile *keyfile,
+                   const gchar *group_name,
+                   const gchar *key_name,
+                   const GValue *value,
+                   GError **error)
+{
+    gchar buf[21];  /* enough for '-' + the 19 digits of 2**63 + '\0' */
+
+    if (!value)
+    {
+        g_key_file_remove_key (keyfile, group_name, key_name, NULL);
+        DEBUG ("unset param %s", key_name);
+        return TRUE;
+    }
+
+    switch (G_VALUE_TYPE (value))
+    {
+    case G_TYPE_STRING:
+        g_key_file_set_string (keyfile, group_name, key_name,
+                               g_value_get_string (value));
+        break;
+
+    case G_TYPE_UINT:
+        g_snprintf (buf, sizeof (buf), "%u", g_value_get_uint (value));
+        g_key_file_set_string (keyfile, group_name, key_name,
+                               buf);
+        break;
+
+    case G_TYPE_INT:
+        g_key_file_set_integer (keyfile, group_name, key_name,
+                                g_value_get_int (value));
+        break;
+
+    case G_TYPE_BOOLEAN:
+        g_key_file_set_boolean (keyfile, group_name, key_name,
+                                g_value_get_boolean (value));
+        break;
+
+    case G_TYPE_UCHAR:
+        g_key_file_set_integer (keyfile, group_name, key_name,
+                                g_value_get_uchar (value));
+        break;
+
+    case G_TYPE_UINT64:
+        g_snprintf (buf, sizeof (buf), "%" G_GUINT64_FORMAT,
+                    g_value_get_uint64 (value));
+        g_key_file_set_string (keyfile, group_name, key_name,
+                               buf);
+        break;
+
+    case G_TYPE_INT64:
+        g_snprintf (buf, sizeof (buf), "%" G_GINT64_FORMAT,
+                    g_value_get_int64 (value));
+        g_key_file_set_string (keyfile, group_name, key_name,
+                               buf);
+        break;
+
+    case G_TYPE_DOUBLE:
+        g_key_file_set_double (keyfile, group_name, key_name,
+                               g_value_get_double (value));
+        break;
+
+    default:
+        if (G_VALUE_HOLDS (value, G_TYPE_STRV))
+        {
+            gchar **strings = g_value_get_boxed (value);
+
+            g_key_file_set_string_list (keyfile, group_name, key_name,
+                                        (const gchar **)strings,
+                                        g_strv_length (strings));
+        }
+        else if (G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
+        {
+            const gchar *path = g_value_get_boxed (value);
+
+            g_key_file_set_string (keyfile, group_name, key_name,
+                                   path);
+        }
+        else
+        {
+            g_warning ("Unexpected param type %s", G_VALUE_TYPE_NAME (value));
+            return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
 #if ENABLE_GNOME_KEYRING
 typedef struct
 {
@@ -403,9 +495,9 @@ set_parameter (McdAccount *account, const gchar *name, const GValue *value,
 {
     McdAccountPrivate *priv = account->priv;
     gchar key[MAX_KEY_LENGTH];
-    gchar buf[21];  /* enough for '-' + the 19 digits of 2**63 + '\0' */
     const TpConnectionManagerParam *param;
     gboolean is_secret = FALSE;
+    GError *error = NULL;
 
     param = mcd_manager_get_protocol_param (priv->manager,
                                             priv->protocol_name, name);
@@ -418,45 +510,52 @@ set_parameter (McdAccount *account, const gchar *name, const GValue *value,
     {
         if (gnome_keyring_is_available ())
         {
-            if (G_VALUE_TYPE (value) != G_TYPE_STRING)
+            gchar *display_name;
+            KeyringSetData *data;
+
+            data = g_slice_new0 (KeyringSetData);
+            data->account = account;
+            data->name = g_strdup (name);
+            data->callback = callback;
+            data->user_data = user_data;
+
+            display_name = g_strdup_printf ("account: %s; param: %s",
+                                            priv->unique_name, name);
+
+            if (value != NULL)
             {
-                g_warning ("Cannot set non-string secret parameter %s in keyring; "
-                           "falling back to storing in keyfile", name);
+                GKeyFile *keyfile;
+                gchar *keyfile_data;
+
+                /* TODO: handle errors */
+                keyfile = g_key_file_new ();
+                keyfile_set_value (keyfile, MCD_GNOME_KEYRING_GROUP_NAME,
+                                   MCD_GNOME_KEYRING_KEY_NAME, value, &error);
+
+                keyfile_data = g_key_file_get_value (keyfile,
+                                                     MCD_GNOME_KEYRING_GROUP_NAME,
+                                                     MCD_GNOME_KEYRING_KEY_NAME, &error);
+
+                gnome_keyring_store_password (&keyring_schema, GNOME_KEYRING_DEFAULT,
+                                              display_name, keyfile_data,
+                                              keyring_set_cb, data, NULL,
+                                              "account", priv->unique_name,
+                                              "param", name,
+                                              NULL);
+
+                g_free (keyfile_data);
+                g_key_file_free (keyfile);
             }
             else
             {
-                gchar *display_name;
-                KeyringSetData *data;
-
-                data = g_slice_new0 (KeyringSetData);
-                data->account = account;
-                data->name = g_strdup (name);
-                data->callback = callback;
-                data->user_data = user_data;
-
-                display_name = g_strdup_printf ("Password for account %s",
-                                                priv->unique_name);
-
-                if (value != NULL)
-                {
-                    gnome_keyring_store_password (&keyring_schema, GNOME_KEYRING_DEFAULT,
-                                                  display_name, g_value_get_string (value),
-                                                  keyring_set_cb, data, NULL,
-                                                  "account", priv->unique_name,
-                                                  "param", name,
-                                                  NULL);
-                }
-                else
-                {
-                    gnome_keyring_delete_password (&keyring_schema, keyring_set_cb,
-                                                   data, NULL,
-                                                   "account", priv->unique_name,
-                                                   "param", name,
-                                                   NULL);
-                }
-                g_free (display_name);
-                return;
+                gnome_keyring_delete_password (&keyring_schema, keyring_set_cb,
+                                               data, NULL,
+                                               "account", priv->unique_name,
+                                               "param", name,
+                                               NULL);
             }
+            g_free (display_name);
+            return;
         }
         else
         {
@@ -468,87 +567,136 @@ set_parameter (McdAccount *account, const gchar *name, const GValue *value,
 
     g_snprintf (key, sizeof (key), "param-%s", name);
 
-    if (!value)
+    keyfile_set_value (priv->keyfile, priv->unique_name, key,
+                       value, &error);
+
+    if (callback != NULL)
     {
-        g_key_file_remove_key (priv->keyfile, priv->unique_name, key, NULL);
-        DEBUG ("unset param %s", name);
-        goto out;
+        callback (account, error, user_data);
     }
 
-    switch (G_VALUE_TYPE (value))
+    if (error != NULL)
+        g_error_free (error);
+}
+
+static GValue *
+keyfile_get_value (GKeyFile *keyfile,
+                   const gchar *group_name,
+                   const gchar *key_name,
+                   GType type,
+                   GError **error)
+{
+    GValue *value = NULL;
+
+    gchar *v_string = NULL;
+    gint64 v_int = 0;
+    guint64 v_uint = 0;
+    gboolean v_bool = FALSE;
+    double v_double = 0.0;
+
+    switch (type)
     {
     case G_TYPE_STRING:
-	g_key_file_set_string (priv->keyfile, priv->unique_name, key,
-			       g_value_get_string (value));
-	break;
-
-    case G_TYPE_UINT:
-        g_snprintf (buf, sizeof (buf), "%u", g_value_get_uint (value));
-        g_key_file_set_string (priv->keyfile, priv->unique_name, key,
-                               buf);
+        v_string = g_key_file_get_string (keyfile, group_name,
+                                          key_name, error);
+        value = tp_g_value_slice_new_take_string (v_string);
         break;
 
     case G_TYPE_INT:
-	g_key_file_set_integer (priv->keyfile, priv->unique_name, key,
-				g_value_get_int (value));
-	break;
+        v_int = g_key_file_get_integer (keyfile, group_name,
+                                        key_name, error);
+        value = tp_g_value_slice_new_int (v_int);
+        break;
 
-    case G_TYPE_BOOLEAN:
-	g_key_file_set_boolean (priv->keyfile, priv->unique_name, key,
-				g_value_get_boolean (value));
-	break;
+    case G_TYPE_INT64:
+        v_int = tp_g_key_file_get_int64 (keyfile, group_name,
+                                         key_name, error);
+        value = tp_g_value_slice_new_int64 (v_int);
+        break;
+
+    case G_TYPE_UINT:
+        v_uint = tp_g_key_file_get_uint64 (keyfile,
+                                           group_name, key_name, error);
+
+        if (v_uint > 0xFFFFFFFFU)
+        {
+            /* TODO: set an error */
+        }
+        else
+        {
+            value = tp_g_value_slice_new_uint (v_uint);
+        }
+        break;
 
     case G_TYPE_UCHAR:
-        g_key_file_set_integer (priv->keyfile, priv->unique_name, key,
-                                g_value_get_uchar (value));
+        v_int = g_key_file_get_integer (keyfile, group_name,
+                                        key_name, error);
+
+        if (v_int < 0 || v_int > 0xFF)
+        {
+            /* TODO: set an error */
+        }
+        else
+        {
+            value = tp_g_value_slice_new (G_TYPE_UCHAR);
+            g_value_set_uchar (value, v_int);
+        }
         break;
 
     case G_TYPE_UINT64:
-        g_snprintf (buf, sizeof (buf), "%" G_GUINT64_FORMAT,
-                    g_value_get_uint64 (value));
-        g_key_file_set_string (priv->keyfile, priv->unique_name, key,
-                               buf);
+        v_uint = tp_g_key_file_get_uint64 (keyfile,
+                                           group_name, key_name, error);
+
+        value = tp_g_value_slice_new_uint64 (v_uint);
         break;
 
-    case G_TYPE_INT64:
-        g_snprintf (buf, sizeof (buf), "%" G_GINT64_FORMAT,
-                    g_value_get_int64 (value));
-        g_key_file_set_string (priv->keyfile, priv->unique_name, key,
-                               buf);
+    case G_TYPE_BOOLEAN:
+        v_bool = g_key_file_get_boolean (keyfile, group_name,
+                                         key_name, NULL);
+
+        value = tp_g_value_slice_new_boolean (v_bool);
         break;
 
     case G_TYPE_DOUBLE:
-        g_key_file_set_double (priv->keyfile, priv->unique_name, key,
-                               g_value_get_double (value));
+        v_double = g_key_file_get_double (keyfile, group_name,
+                                          key_name, NULL);
+
+        value = tp_g_value_slice_new_double (v_double);
         break;
 
     default:
-        if (G_VALUE_HOLDS (value, G_TYPE_STRV))
+        if (type == G_TYPE_STRV)
         {
-            gchar **strings = g_value_get_boxed (value);
+            gchar **v = g_key_file_get_string_list (keyfile,
+                                                    group_name, key_name,
+                                                    NULL, error);
 
-            g_key_file_set_string_list (priv->keyfile, priv->unique_name, key,
-                                        (const gchar **)strings,
-                                        g_strv_length (strings));
+            value = tp_g_value_slice_new_take_boxed (G_TYPE_STRV, v);
         }
-        else if (G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
+        else if (type == DBUS_TYPE_G_OBJECT_PATH)
         {
-            const gchar *path = g_value_get_boxed (value);
+            v_string = g_key_file_get_string (keyfile,
+                                              group_name, key_name,
+                                              error);
 
-            g_key_file_set_string (priv->keyfile, priv->unique_name, key,
-                                   path);
+            if (!tp_dbus_check_valid_object_path (v_string, NULL))
+            {
+                g_free (v_string);
+                /* TODO: set an error */
+            }
+            else
+            {
+                value = tp_g_value_slice_new_take_object_path (v_string);
+            }
         }
         else
         {
-            g_warning ("Unexpected param type %s", G_VALUE_TYPE_NAME (value));
+            g_warning ("%s: cannot get property %s, unknown type %s",
+                       G_STRFUNC, key_name, g_type_name (type));
         }
     }
 
-out:
-    if (callback != NULL)
-    {
-      callback (account, NULL, user_data);
-    }
+    return value;
 }
 
 static GType mc_param_type (const TpConnectionManagerParam *param);
@@ -558,6 +706,7 @@ typedef struct
 {
     McdAccount *account;
     gchar *name;
+    GType type;
     McdAccountGetParameterCb callback;
     gpointer user_data;
 } KeyringGetData;
@@ -569,6 +718,7 @@ keyring_get_cb (GnomeKeyringResult result, const gchar* password,
     KeyringGetData *data = (KeyringGetData *) user_data;
     GValue *value = NULL;
     GError *error = NULL;
+    GKeyFile *keyfile = NULL;
 
     if (result != GNOME_KEYRING_RESULT_OK)
     {
@@ -579,12 +729,22 @@ keyring_get_cb (GnomeKeyringResult result, const gchar* password,
     else
     {
         DEBUG ("Successfully got secret parameter %s from keyring", data->name);
-        value = tp_g_value_slice_new_string (password);
+
+        keyfile = g_key_file_new ();
+        g_key_file_set_value (keyfile, MCD_GNOME_KEYRING_GROUP_NAME,
+            MCD_GNOME_KEYRING_KEY_NAME, password);
+
+        value = keyfile_get_value (keyfile, MCD_GNOME_KEYRING_GROUP_NAME,
+                                   MCD_GNOME_KEYRING_KEY_NAME,
+                                   data->type, &error);
     }
 
     if (data->callback != NULL)
         data->callback (data->account, value, error, data->user_data);
 
+    if (keyfile != NULL)
+        g_key_file_free (keyfile);
+
     if (value != NULL)
         tp_g_value_slice_free (value);
 
@@ -608,12 +768,6 @@ get_parameter (McdAccount *account, const gchar *name,
     GValue *value = NULL;
     GType type;
 
-    gchar *v_string = NULL;
-    gint64 v_int = 0;
-    guint64 v_uint = 0;
-    gboolean v_bool = FALSE;
-    double v_double = 0.0;
-
     param = mcd_manager_get_protocol_param (priv->manager,
                                             priv->protocol_name, name);
 
@@ -627,27 +781,21 @@ get_parameter (McdAccount *account, const gchar *name,
     {
         if (gnome_keyring_is_available ())
         {
-            if (type != G_TYPE_STRING)
-            {
-                g_warning ("Not looking for non-string secret parameter %s in keyring", name);
-            }
-            else
-            {
-                KeyringGetData *data;
-
-                data = g_slice_new0 (KeyringGetData);
-                data->account = account;
-                data->name = g_strdup (name);
-                data->callback = callback;
-                data->user_data = user_data;
-
-                gnome_keyring_find_password (&keyring_schema,
-                                             keyring_get_cb, data, NULL,
-                                             "account", priv->unique_name,
-                                             "param", name,
-                                             NULL);
-                return;
-            }
+            KeyringGetData *data;
+
+            data = g_slice_new0 (KeyringGetData);
+            data->account = account;
+            data->name = g_strdup (name);
+            data->type = type;
+            data->callback = callback;
+            data->user_data = user_data;
+
+            gnome_keyring_find_password (&keyring_schema,
+                                         keyring_get_cb, data, NULL,
+                                         "account", priv->unique_name,
+                                         "param", name,
+                                         NULL);
+            return;
         }
         else
         {
@@ -658,103 +806,13 @@ get_parameter (McdAccount *account, const gchar *name,
 #endif
 
     g_snprintf (key, sizeof (key), "param-%s", name);
-    if (!g_key_file_has_key (priv->keyfile, priv->unique_name, key, NULL))
-        goto error;
-
-    switch (type)
+    if (g_key_file_has_key (priv->keyfile, priv->unique_name, key, NULL))
     {
-    case G_TYPE_STRING:
-        v_string = g_key_file_get_string (priv->keyfile, priv->unique_name,
-                                          key, NULL);
-        value = tp_g_value_slice_new_take_string (v_string);
-        break;
-
-    case G_TYPE_INT:
-        v_int = g_key_file_get_integer (priv->keyfile, priv->unique_name,
-                                        key, NULL);
-        value = tp_g_value_slice_new_int (v_int);
-        break;
-
-    case G_TYPE_INT64:
-        v_int = tp_g_key_file_get_int64 (priv->keyfile, priv->unique_name,
-                                         key, NULL);
-        value = tp_g_value_slice_new_int64 (v_int);
-        break;
-
-    case G_TYPE_UINT:
-        v_uint = tp_g_key_file_get_uint64 (priv->keyfile,
-                                           priv->unique_name, key, NULL);
-
-        if (v_uint > 0xFFFFFFFFU)
-        {
-            goto error;
-        }
-
-        value = tp_g_value_slice_new_uint (v_uint);
-        break;
-
-    case G_TYPE_UCHAR:
-        v_int = g_key_file_get_integer (priv->keyfile, priv->unique_name,
-                                        key, NULL);
-
-        if (v_int < 0 || v_int > 0xFF)
-        {
-            goto error;
-        }
-        value = tp_g_value_slice_new (G_TYPE_UCHAR);
-        g_value_set_uchar (value, v_int);
-        break;
-
-    case G_TYPE_UINT64:
-        v_uint = tp_g_key_file_get_uint64 (priv->keyfile,
-                                           priv->unique_name, key, NULL);
-
-        value = tp_g_value_slice_new_uint64 (v_uint);
-        break;
-
-    case G_TYPE_BOOLEAN:
-        v_bool = g_key_file_get_boolean (priv->keyfile, priv->unique_name,
-                                         key, NULL);
-
-        value = tp_g_value_slice_new_boolean (v_bool);
-        break;
-
-    case G_TYPE_DOUBLE:
-        v_double = g_key_file_get_double (priv->keyfile, priv->unique_name,
-                                          key, NULL);
-
-        value = tp_g_value_slice_new_double (v_double);
-        break;
-
-    default:
-        if (type == G_TYPE_STRV)
-        {
-            gchar **v = g_key_file_get_string_list (priv->keyfile,
-                                                    priv->unique_name, key,
-                                                    NULL, NULL);
-
-            value = tp_g_value_slice_new_take_boxed (G_TYPE_STRV, v);
-        }
-        else if (type == DBUS_TYPE_G_OBJECT_PATH)
-        {
-            v_string = g_key_file_get_string (priv->keyfile,
-                                              priv->unique_name, key,
-                                              NULL);
-
-            if (!tp_dbus_check_valid_object_path (v_string, NULL))
-            {
-                g_free (v_string);
-                goto error;
-            }
-
-            value = tp_g_value_slice_new_take_object_path (v_string);
-        }
-        else
-        {
-            g_warning ("%s: cannot get property %s, unknown type %s",
-                       G_STRFUNC, name, g_type_name (type));
-            goto error;
-        }
+        value = keyfile_get_value (priv->keyfile, priv->unique_name, key, type, &error);
+    }
+    else
+    {
+        /* TODO: set an error */
     }
 
     if (value != NULL)
@@ -765,12 +823,13 @@ get_parameter (McdAccount *account, const gchar *name,
 
         return;
     }
-
-error:
-    if (callback != NULL)
-        callback (account, NULL, error, user_data);
-    if (error != NULL)
-        g_error_free (error);
+    else
+    {
+        if (callback != NULL)
+            callback (account, NULL, error, user_data);
+        if (error != NULL)
+            g_error_free (error);
+    }
 }
 
 
-- 
1.5.6.5




More information about the telepathy-commits mailing list