[Pkg-telepathy-commits] [telepathy-mission-control-6] 93/280: Default account backend: store each account as a stringified GVariant in a file
Simon McVittie
smcv at debian.org
Thu Mar 27 20:07:09 UTC 2014
This is an automated email from the git hooks/post-receive script.
smcv pushed a commit to branch debian
in repository telepathy-mission-control-6.
commit f9722e84786bf00137b980948eb83539e94f3945
Author: Simon McVittie <simon.mcvittie at collabora.co.uk>
Date: Tue Oct 29 13:35:43 2013 +0000
Default account backend: store each account as a stringified GVariant in a file
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=54875
Reviewed-by: Guillaume Desmottes <guillaume.desmottes at collabora.co.uk>
---
src/mcd-account-manager-default.c | 513 +++++++++++++++++----
src/mcd-account-manager-default.h | 2 +-
.../account-storage/default-keyring-storage.py | 108 +++--
tests/twisted/account-storage/diverted-storage.py | 4 -
4 files changed, 481 insertions(+), 146 deletions(-)
diff --git a/src/mcd-account-manager-default.c b/src/mcd-account-manager-default.c
index 6bbea0e..4dc0e8b 100644
--- a/src/mcd-account-manager-default.c
+++ b/src/mcd-account-manager-default.c
@@ -1,8 +1,8 @@
/*
- * The default account manager keyfile storage pseudo-plugin
+ * The default account manager storage pseudo-plugin
*
* Copyright © 2010 Nokia Corporation
- * Copyright © 2010 Collabora Ltd.
+ * Copyright © 2010-2012 Collabora Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -32,20 +32,22 @@
#include "mcd-debug.h"
#include "mcd-misc.h"
-#define PLUGIN_NAME "default-gkeyfile"
+#define PLUGIN_NAME "default"
#define PLUGIN_PRIORITY MCP_ACCOUNT_STORAGE_PLUGIN_PRIO_DEFAULT
-#define PLUGIN_DESCRIPTION "GKeyFile (default) account storage backend"
-#define INITIAL_CONFIG "# Telepathy accounts\n"
+#define PLUGIN_DESCRIPTION "Default account storage backend"
typedef struct {
/* owned string, attribute => owned string, value
- * attributes to be stored in the keyfile */
+ * attributes to be stored in the variant-file */
GHashTable *attributes;
/* owned string, parameter (without "param-") => owned string, value
- * parameters to be stored in the keyfile */
+ * parameters to be stored in the variant-file */
GHashTable *untyped_parameters;
/* TRUE if the entire account is pending deletion */
gboolean pending_deletion;
+ /* TRUE if the account doesn't really exist, but is here to stop us
+ * loading it from a lower-priority file */
+ gboolean absent;
} McdDefaultStoredAccount;
static McdDefaultStoredAccount *
@@ -72,6 +74,7 @@ ensure_stored_account (McdAccountManagerDefault *self,
}
sa->pending_deletion = FALSE;
+ sa->absent = FALSE;
return sa;
}
@@ -113,17 +116,37 @@ get_old_filename (void)
}
static gchar *
-account_filename_in (const gchar *dir)
+accounts_cfg_in (const gchar *dir)
{
return g_build_filename (dir, "telepathy", "mission-control", "accounts.cfg",
NULL);
}
+static gchar *
+account_directory_in (const gchar *dir)
+{
+ return g_build_filename (dir, "telepathy", "mission-control", NULL);
+}
+
+static gchar *
+account_file_in (const gchar *dir,
+ const gchar *account)
+{
+ gchar *basename = g_strdup_printf ("%s.account", account);
+ gchar *ret;
+
+ g_strdelimit (basename, "/", '-');
+ ret = g_build_filename (dir, "telepathy", "mission-control",
+ basename, NULL);
+ g_free (basename);
+ return ret;
+}
+
static void
mcd_account_manager_default_init (McdAccountManagerDefault *self)
{
DEBUG ("mcd_account_manager_default_init");
- self->filename = account_filename_in (g_get_user_data_dir ());
+ self->directory = account_directory_in (g_get_user_data_dir ());
self->accounts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
stored_account_free);
self->save = FALSE;
@@ -136,8 +159,7 @@ mcd_account_manager_default_class_init (McdAccountManagerDefaultClass *cls)
DEBUG ("mcd_account_manager_default_class_init");
}
-/* We happen to know that the string MC gave us is "sufficiently escaped" to
- * put it in the keyfile as-is. */
+/* The value is escaped as if for a keyfile */
static gboolean
set_parameter (const McpAccountStorage *self,
const McpAccountManager *am,
@@ -213,7 +235,7 @@ get_parameter (const McpAccountStorage *self,
{
gchar *v = NULL;
- if (sa == NULL)
+ if (sa == NULL || sa->absent)
return FALSE;
v = g_hash_table_lookup (sa->untyped_parameters, parameter);
@@ -222,7 +244,6 @@ get_parameter (const McpAccountStorage *self,
return FALSE;
mcp_account_manager_set_value (am, account, prefixed, v);
- g_free (v);
}
else
{
@@ -241,7 +262,7 @@ _get (const McpAccountStorage *self,
McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
McdDefaultStoredAccount *sa = lookup_stored_account (amd, account);
- if (sa == NULL)
+ if (sa == NULL || sa->absent)
return FALSE;
if (key != NULL)
@@ -259,7 +280,6 @@ _get (const McpAccountStorage *self,
return FALSE;
mcp_account_manager_set_value (am, account, key, v);
- g_free (v);
}
else
{
@@ -321,7 +341,7 @@ _delete (const McpAccountStorage *self,
McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
McdDefaultStoredAccount *sa = lookup_stored_account (amd, account);
- if (sa == NULL)
+ if (sa == NULL || sa->absent)
{
/* Apparently we never had this account anyway. The plugin API
* considers this to be "success". */
@@ -362,84 +382,162 @@ _delete (const McpAccountStorage *self,
return TRUE;
}
+static gboolean
+am_default_commit_one (McdAccountManagerDefault *self,
+ const gchar *account_name,
+ McdDefaultStoredAccount *sa)
+{
+ gchar *filename;
+ GHashTableIter inner;
+ gpointer k, v;
+ GVariantBuilder params_builder;
+ GVariantBuilder attrs_builder;
+ GVariant *content;
+ gchar *content_text;
+ gboolean ret;
+ GError *error = NULL;
+
+ filename = account_file_in (g_get_user_data_dir (), account_name);
+
+ if (sa->pending_deletion)
+ {
+ const gchar * const *iter;
+
+ DEBUG ("Deleting account %s from %s", account_name, filename);
+
+ if (g_unlink (filename) != 0)
+ {
+ int e = errno;
+
+ /* ENOENT is OK, anything else is more upsetting */
+ if (e != ENOENT)
+ {
+ WARNING ("Unable to delete %s: %s", filename,
+ g_strerror (e));
+ g_free (filename);
+ return FALSE;
+ }
+ }
+
+ for (iter = g_get_system_data_dirs ();
+ iter != NULL && *iter != NULL;
+ iter++)
+ {
+ gchar *other = account_file_in (*iter, account_name);
+ gboolean other_exists = g_file_test (other, G_FILE_TEST_EXISTS);
+
+ g_free (other);
+
+ if (other_exists)
+ {
+ /* There is a lower-priority file that would provide this
+ * account. We can't delete a file from XDG_DATA_DIRS which
+ * are conceptually read-only, but we can mask it with an
+ * empty file (prior art: systemd) */
+ if (!g_file_set_contents (filename, "", 0, &error))
+ {
+ WARNING ("Unable to save empty account file to %s: %s",
+ filename, error->message);
+ g_clear_error (&error);
+ g_free (filename);
+ return FALSE;
+ }
+
+ break;
+ }
+ }
+
+ g_free (filename);
+ return TRUE;
+ }
+
+ DEBUG ("Saving account %s to %s", account_name, filename);
+
+ g_variant_builder_init (&attrs_builder, G_VARIANT_TYPE_VARDICT);
+
+ g_hash_table_iter_init (&inner, sa->attributes);
+
+ while (g_hash_table_iter_next (&inner, &k, &v))
+ {
+ /* FIXME: for now, we put the keyfile-escaped value in a string,
+ * and store that. This needs fixing to use typed attributes
+ * before this code gets released. */
+ g_variant_builder_add (&attrs_builder, "{sv}",
+ k, g_variant_new_string (v));
+ }
+
+ g_variant_builder_init (¶ms_builder, G_VARIANT_TYPE ("a{ss}"));
+ g_hash_table_iter_init (&inner, sa->untyped_parameters);
+
+ while (g_hash_table_iter_next (&inner, &k, &v))
+ {
+ g_variant_builder_add (¶ms_builder, "{ss}", k, v);
+ }
+
+ g_variant_builder_add (&attrs_builder, "{sv}",
+ "KeyFileParameters", g_variant_builder_end (¶ms_builder));
+
+ content = g_variant_ref_sink (g_variant_builder_end (&attrs_builder));
+ content_text = g_variant_print (content, TRUE);
+ DEBUG ("%s", content_text);
+ g_variant_unref (content);
+
+ if (g_file_set_contents (filename, content_text, -1, &error))
+ {
+ ret = TRUE;
+ }
+ else
+ {
+ WARNING ("Unable to save account to %s: %s", filename,
+ error->message);
+ g_clear_error (&error);
+ ret = FALSE;
+ }
+
+ g_free (filename);
+ g_free (content_text);
+ return ret;
+}
static gboolean
_commit (const McpAccountStorage *self,
const McpAccountManager *am,
const gchar *account)
{
- gsize n;
- gchar *data;
McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
- gboolean rval = FALSE;
- gchar *dir;
+ gboolean all_succeeded = TRUE;
GError *error = NULL;
GHashTableIter outer;
gpointer account_p, sa_p;
- GKeyFile *keyfile;
if (!amd->save)
return TRUE;
- dir = g_path_get_dirname (amd->filename);
-
- DEBUG ("Saving accounts to %s", amd->filename);
+ DEBUG ("Saving accounts to %s", amd->directory);
- if (!mcd_ensure_directory (dir, &error))
+ if (!mcd_ensure_directory (amd->directory, &error))
{
g_warning ("%s", error->message);
g_error_free (error);
- /* fall through anyway: writing to the file will fail, but it does
+ /* fall through anyway: writing to the files will fail, but it does
* give us a chance to commit to the keyring too */
}
- g_free (dir);
-
- keyfile = g_key_file_new ();
-
g_hash_table_iter_init (&outer, amd->accounts);
while (g_hash_table_iter_next (&outer, &account_p, &sa_p))
{
- McdDefaultStoredAccount *sa = sa_p;
- GHashTableIter inner;
- gpointer k, v;
-
- /* don't save accounts that are being deleted */
- if (sa->pending_deletion)
- continue;
-
- g_hash_table_iter_init (&inner, sa->attributes);
-
- while (g_hash_table_iter_next (&inner, &k, &v))
- g_key_file_set_value (keyfile, account_p, k, v);
-
- g_hash_table_iter_init (&inner, sa->untyped_parameters);
-
- while (g_hash_table_iter_next (&inner, &k, &v))
+ if (account == NULL || !tp_strdiff (account, account_p))
{
- gchar *prefixed = g_strdup_printf ("param-%s", (const gchar *) k);
-
- g_key_file_set_value (keyfile, account_p, prefixed, v);
- g_free (prefixed);
+ if (!am_default_commit_one (amd, account_p, sa_p))
+ all_succeeded = FALSE;
}
}
- data = g_key_file_to_data (keyfile, &n, NULL);
- rval = g_file_set_contents (amd->filename, data, n, &error);
-
- if (rval)
+ if (all_succeeded)
{
amd->save = FALSE;
}
- else
- {
- g_warning ("%s", error->message);
- g_error_free (error);
- }
-
- g_free (data);
- g_key_file_unref (keyfile);
g_hash_table_iter_init (&outer, amd->accounts);
@@ -452,10 +550,10 @@ _commit (const McpAccountStorage *self,
g_hash_table_iter_remove (&outer);
}
- return rval;
+ return all_succeeded;
}
-static void
+static gboolean
am_default_load_keyfile (McdAccountManagerDefault *self,
const gchar *filename)
{
@@ -464,6 +562,13 @@ am_default_load_keyfile (McdAccountManagerDefault *self,
gsize i;
gsize n = 0;
GStrv account_tails;
+ gboolean all_ok = TRUE;
+
+ /* We shouldn't call this function without modification if we think we've
+ * migrated to a newer storage format, because it doesn't check whether
+ * each account has already been loaded. */
+ g_assert (!self->loaded);
+ g_assert (g_hash_table_size (self->accounts) == 0);
if (g_key_file_load_from_file (keyfile, filename,
G_KEY_FILE_KEEP_COMMENTS, &error))
@@ -475,12 +580,10 @@ am_default_load_keyfile (McdAccountManagerDefault *self,
DEBUG ("Failed to load accounts from %s: %s", filename, error->message);
g_error_free (error);
- /* Start with a blank configuration, but do not save straight away;
- * we don't want to overwrite a corrupt-but-maybe-recoverable
- * configuration file with an empty one until given a reason to
- * do so. */
- g_key_file_load_from_data (keyfile, INITIAL_CONFIG, -1,
- G_KEY_FILE_KEEP_COMMENTS, NULL);
+ /* Start with a blank configuration. */
+ g_key_file_load_from_data (keyfile, "", -1, 0, NULL);
+ /* Don't delete the old file, which might be recoverable. */
+ all_ok = FALSE;
}
account_tails = g_key_file_get_groups (keyfile, &n);
@@ -493,6 +596,9 @@ am_default_load_keyfile (McdAccountManagerDefault *self,
gsize m = 0;
GStrv keys = g_key_file_get_keys (keyfile, account, &m, NULL);
+ /* We're going to need to migrate this account. */
+ self->save = TRUE;
+
for (j = 0; j < m; j++)
{
gchar *key = keys[j];
@@ -516,6 +622,179 @@ am_default_load_keyfile (McdAccountManagerDefault *self,
g_strfreev (account_tails);
g_key_file_unref (keyfile);
+ return all_ok;
+}
+
+static void
+am_default_load_variant_file (McdAccountManagerDefault *self,
+ const gchar *account_tail,
+ const gchar *full_name)
+{
+ McdDefaultStoredAccount *sa;
+ gchar *text = NULL;
+ gsize len;
+ GVariant *contents = NULL;
+ GVariantIter iter;
+ const gchar *k;
+ GVariant *v;
+ GError *error = NULL;
+
+ DEBUG ("%s from %s", account_tail, full_name);
+
+ sa = lookup_stored_account (self, account_tail);
+
+ if (sa != NULL)
+ {
+ DEBUG ("Ignoring %s: account %s already %s",
+ full_name, account_tail, sa->absent ? "masked" : "loaded");
+ goto finally;
+ }
+
+ if (!g_file_get_contents (full_name, &text, &len, &error))
+ {
+ WARNING ("Unable to read account %s from %s: %s",
+ account_tail, full_name, error->message);
+ g_error_free (error);
+ goto finally;
+ }
+
+ if (len == 0)
+ {
+ DEBUG ("Empty file %s masks account %s", full_name, account_tail);
+ ensure_stored_account (self, account_tail)->absent = TRUE;
+ goto finally;
+ }
+
+ contents = g_variant_parse (G_VARIANT_TYPE_VARDICT,
+ text, text + len, NULL, &error);
+
+ if (contents == NULL)
+ {
+ WARNING ("Unable to parse account %s from %s: %s",
+ account_tail, full_name, error->message);
+ g_error_free (error);
+ goto finally;
+ }
+
+ sa = ensure_stored_account (self, account_tail);
+
+ g_variant_iter_init (&iter, contents);
+
+ while (g_variant_iter_loop (&iter, "{sv}", &k, &v))
+ {
+ if (!tp_strdiff (k, "KeyFileParameters"))
+ {
+ GVariantIter param_iter;
+ gchar *parameter;
+ gchar *param_value;
+
+ if (!g_variant_is_of_type (v, G_VARIANT_TYPE ("a{ss}")))
+ {
+ gchar *repr = g_variant_print (v, TRUE);
+
+ WARNING ("invalid KeyFileParameters found in %s, "
+ "ignoring: %s", full_name, repr);
+ g_free (repr);
+ continue;
+ }
+
+ g_variant_iter_init (¶m_iter, v);
+
+ while (g_variant_iter_next (¶m_iter, "{ss}", ¶meter,
+ ¶m_value))
+ {
+ /* steals parameter, param_value */
+ g_hash_table_insert (sa->untyped_parameters, parameter,
+ param_value);
+ }
+ }
+ else
+ {
+ /* an ordinary attribute */
+ /* FIXME: this is temporary and should not be released:
+ * it assumes that all attributes are keyfile-escaped
+ * strings */
+ if (g_variant_is_of_type (v, G_VARIANT_TYPE_STRING))
+ {
+ g_hash_table_insert (sa->attributes,
+ g_strdup (k), g_variant_dup_string (v, NULL));
+ }
+ else
+ {
+ gchar *repr = g_variant_print (v, TRUE);
+
+ WARNING ("Not a string: %s", repr);
+ g_free (repr);
+ }
+ }
+ }
+
+finally:
+ tp_clear_pointer (&contents, g_variant_unref);
+ g_free (text);
+}
+
+static void
+am_default_load_directory (McdAccountManagerDefault *self,
+ const gchar *directory)
+{
+ GDir *dir_handle;
+ const gchar *basename;
+ GRegex *regex;
+ GError *error = NULL;
+
+ dir_handle = g_dir_open (directory, 0, &error);
+
+ if (dir_handle == NULL)
+ {
+ /* We expect ENOENT. Anything else is a cause for (minor) concern. */
+ if (g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
+ DEBUG ("%s", error->message);
+ else
+ WARNING ("%s", error->message);
+
+ g_error_free (error);
+ return;
+ }
+
+ DEBUG ("Looking for accounts in %s", directory);
+
+ regex = g_regex_new ("^[A-Za-z][A-Za-z0-9_]*-" /* CM name */
+ "[A-Za-z][A-Za-z0-9_]*-" /* protocol with s/-/_/ */
+ "[A-Za-z_][A-Za-z0-9_]*\\.account$", /* account-specific part */
+ G_REGEX_DOLLAR_ENDONLY, 0, &error);
+ g_assert_no_error (error);
+
+ while ((basename = g_dir_read_name (dir_handle)) != NULL)
+ {
+ gchar *full_name;
+ gchar *account_tail;
+
+ /* skip it silently if it's obviously not an account */
+ if (!g_str_has_suffix (basename, ".account"))
+ continue;
+
+ /* We consider ourselves to have migrated to the new storage format
+ * as soon as we find something that looks as though it ought to be an
+ * account. */
+ self->loaded = TRUE;
+
+ if (!g_regex_match (regex, basename, 0, NULL))
+ {
+ WARNING ("Ignoring %s/%s: not a syntactically valid account",
+ directory, basename);
+ }
+
+ full_name = g_build_filename (directory, basename, NULL);
+ account_tail = g_strdup (basename);
+ g_strdelimit (account_tail, "-", '/');
+ g_strdelimit (account_tail, ".", '\0');
+
+ am_default_load_variant_file (self, account_tail, full_name);
+
+ g_free (account_tail);
+ g_free (full_name);
+ }
}
static GList *
@@ -525,16 +804,47 @@ _list (const McpAccountStorage *self,
GList *rval = NULL;
McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
GHashTableIter hash_iter;
+ gchar *migrate_from = NULL;
gpointer k, v;
- if (!amd->loaded && g_file_test (amd->filename, G_FILE_TEST_EXISTS))
+ if (!amd->loaded)
{
- /* If the file exists, but loading it fails, we deliberately
- * do not fall through to the "initial configuration" case,
- * because we don't want to overwrite a corrupted file
- * with an empty one until an actual write takes place. */
- am_default_load_keyfile (amd, amd->filename);
- amd->loaded = TRUE;
+ const gchar * const *iter;
+
+ am_default_load_directory (amd, amd->directory);
+
+ /* We do this even if am_default_load_directory() succeeded, and
+ * do not stop when amd->loaded becomes true. If XDG_DATA_HOME
+ * contains gabble-jabber-example_2eexample_40com.account, that doesn't
+ * mean a directory in XDG_DATA_DIRS doesn't also contain
+ * haze-msn-example_2ehotmail_40com.account or something, which
+ * should also be loaded. */
+ for (iter = g_get_system_data_dirs ();
+ iter != NULL && *iter != NULL;
+ iter++)
+ {
+ gchar *dir = account_directory_in (*iter);
+
+ am_default_load_directory (amd, dir);
+ g_free (dir);
+ }
+ }
+
+ if (!amd->loaded)
+ {
+ migrate_from = accounts_cfg_in (g_get_user_data_dir ());
+
+ if (g_file_test (migrate_from, G_FILE_TEST_EXISTS))
+ {
+ if (!am_default_load_keyfile (amd, migrate_from))
+ tp_clear_pointer (&migrate_from, g_free);
+
+ amd->loaded = TRUE;
+ }
+ else
+ {
+ tp_clear_pointer (&migrate_from, g_free);
+ }
}
if (!amd->loaded)
@@ -545,14 +855,14 @@ _list (const McpAccountStorage *self,
iter != NULL && *iter != NULL;
iter++)
{
- gchar *filename = account_filename_in (*iter);
+ /* not setting migrate_from here - XDG_DATA_DIRS are conceptually
+ * read-only, so we don't want to delete these files */
+ gchar *filename = accounts_cfg_in (*iter);
if (g_file_test (filename, G_FILE_TEST_EXISTS))
{
am_default_load_keyfile (amd, filename);
amd->loaded = TRUE;
- /* Do not set amd->save: we don't need to write it to a
- * higher-priority directory until it actually changes. */
}
g_free (filename);
@@ -564,25 +874,19 @@ _list (const McpAccountStorage *self,
if (!amd->loaded)
{
- gchar *old_filename = get_old_filename ();
+ migrate_from = get_old_filename ();
- if (g_file_test (old_filename, G_FILE_TEST_EXISTS))
+ if (g_file_test (migrate_from, G_FILE_TEST_EXISTS))
{
- am_default_load_keyfile (amd, old_filename);
+ if (!am_default_load_keyfile (amd, migrate_from))
+ tp_clear_pointer (&migrate_from, g_free);
amd->loaded = TRUE;
amd->save = TRUE;
-
- if (_commit (self, am, NULL))
- {
- DEBUG ("Migrated %s to new location: deleting old copy",
- old_filename);
- if (g_unlink (old_filename) != 0)
- g_warning ("Unable to delete %s: %s", old_filename,
- g_strerror (errno));
- }
}
-
- g_free (old_filename);
+ else
+ {
+ tp_clear_pointer (&migrate_from, g_free);
+ }
}
if (!amd->loaded)
@@ -590,9 +894,28 @@ _list (const McpAccountStorage *self,
DEBUG ("Creating initial account data");
amd->loaded = TRUE;
amd->save = TRUE;
- _commit (self, am, NULL);
}
+ if (amd->save)
+ {
+ DEBUG ("Saving initial or migrated account data");
+
+ if (_commit (self, am, NULL))
+ {
+ if (migrate_from != NULL)
+ {
+ DEBUG ("Migrated %s to new location: deleting old copy",
+ migrate_from);
+
+ if (g_unlink (migrate_from) != 0)
+ WARNING ("Unable to delete %s: %s", migrate_from,
+ g_strerror (errno));
+ }
+ }
+ }
+
+ tp_clear_pointer (&migrate_from, g_free);
+
g_hash_table_iter_init (&hash_iter, amd->accounts);
while (g_hash_table_iter_next (&hash_iter, &k, &v))
diff --git a/src/mcd-account-manager-default.h b/src/mcd-account-manager-default.h
index e48a767..e16e062 100644
--- a/src/mcd-account-manager-default.h
+++ b/src/mcd-account-manager-default.h
@@ -50,7 +50,7 @@ G_BEGIN_DECLS
typedef struct {
GObject parent;
GHashTable *accounts;
- gchar *filename;
+ gchar *directory;
gboolean save;
gboolean loaded;
} _McdAccountManagerDefault;
diff --git a/tests/twisted/account-storage/default-keyring-storage.py b/tests/twisted/account-storage/default-keyring-storage.py
index 74f3bd3..c67399e 100644
--- a/tests/twisted/account-storage/default-keyring-storage.py
+++ b/tests/twisted/account-storage/default-keyring-storage.py
@@ -61,8 +61,11 @@ def account_store(op, backend, key=None, value=None,
def test(q, bus, mc):
ctl_dir = os.environ['MC_ACCOUNT_DIR']
old_key_file_name = os.path.join(ctl_dir, 'accounts.cfg')
- new_key_file_name = os.path.join(os.environ['XDG_DATA_HOME'],
+ newer_key_file_name = os.path.join(os.environ['XDG_DATA_HOME'],
'telepathy', 'mission-control', 'accounts.cfg')
+ new_variant_file_name = os.path.join(os.environ['XDG_DATA_HOME'],
+ 'telepathy', 'mission-control',
+ 'fakecm-fakeprotocol-dontdivert_40example_2ecom0.account')
group = 'fakecm/fakeprotocol/dontdivert_40example_2ecom0'
account_manager, properties, interfaces = connect_to_mc(q, bus, mc)
@@ -95,25 +98,35 @@ def test(q, bus, mc):
account_props.Set(cs.ACCOUNT, 'DisplayName', 'Work account')
account_props.Set(cs.ACCOUNT, 'Icon', 'im-jabber')
account_props.Set(cs.ACCOUNT, 'Nickname', 'Joe Bloggs')
+ account_props.Set(cs.ACCOUNT, 'ConnectAutomatically', True)
+ account_props.Set(cs.ACCOUNT, 'AutomaticPresence',
+ (dbus.UInt32(cs.PRESENCE_EXTENDED_AWAY), 'xa',
+ 'never online'))
tell_mc_to_die(q, bus)
# .. let's check the keyfile
assert not os.path.exists(old_key_file_name)
- kf = keyfile_read(new_key_file_name)
- assert group in kf, kf
- assert kf[group]['manager'] == 'fakecm'
- assert kf[group]['protocol'] == 'fakeprotocol'
- assert kf[group]['param-account'] == params['account'], kf
- assert kf[group]['DisplayName'] == 'Work account', kf
- assert kf[group]['Icon'] == 'im-jabber', kf
- assert kf[group]['Nickname'] == 'Joe Bloggs', kf
-
- pwd = account_store('get', 'keyfile', 'param-password')
- assert pwd == params['password'], pwd
-
- # We no longer use gnome-keyring, so the password is stored as clear-text.
- assert kf[group]['param-password'] == params['password'], kf
+ assert not os.path.exists(newer_key_file_name)
+ assert 'Joe Bloggs' in open(new_variant_file_name).read()
+ assertEquals("'fakecm'", account_store('get', 'variant-file', 'manager'))
+ assertEquals("'fakeprotocol'", account_store('get', 'variant-file',
+ 'protocol'))
+ assertEquals("'Work account'", account_store('get', 'variant-file',
+ 'DisplayName'))
+ assertEquals("'im-jabber'", account_store('get', 'variant-file',
+ 'Icon'))
+ assertEquals("'Joe Bloggs'", account_store('get', 'variant-file',
+ 'Nickname'))
+ # For now, everything is a keyfile-escaped string
+ assertEquals("'true'", account_store('get', 'variant-file',
+ 'ConnectAutomatically'))
+ assertEquals("'4;xa;never online;'", account_store('get', 'variant-file',
+ 'AutomaticPresence'))
+ assertEquals("keyfile-escaped 'dontdivert at example.com'",
+ account_store('get', 'variant-file', 'param-account'))
+ assertEquals("keyfile-escaped 'secrecy'",
+ account_store('get', 'variant-file', 'param-password'))
# Reactivate MC
account_manager, properties, interfaces = resuscitate_mc(q, bus, mc)
@@ -139,29 +152,33 @@ def test(q, bus, mc):
# Check the account is correctly deleted
assert not os.path.exists(old_key_file_name)
- kf = keyfile_read(new_key_file_name)
- assert group not in kf, kf
+ assert not os.path.exists(newer_key_file_name)
+ assert not os.path.exists(new_variant_file_name)
# Tell MC to die, again
tell_mc_to_die(q, bus)
- low_prio_key_file_name = os.path.join(
+ low_prio_variant_file_name = os.path.join(
os.environ['XDG_DATA_DIRS'].split(':')[0],
- 'telepathy', 'mission-control', 'accounts.cfg')
- os.makedirs(os.path.dirname(low_prio_key_file_name), 0700)
+ 'telepathy', 'mission-control',
+ 'fakecm-fakeprotocol-dontdivert_40example_2ecom0.account')
+ os.makedirs(os.path.dirname(low_prio_variant_file_name), 0700)
# This is deliberately a lower-priority location
- os.remove(new_key_file_name)
- open(low_prio_key_file_name, 'w').write(
-r"""# Telepathy accounts
-[%s]
-manager=fakecm
-protocol=fakeprotocol
-param-account=dontdivert at example.com
-param-password=password_in_keyfile
-DisplayName=New and improved account
-AutomaticPresence=2;available;;
-""" % group)
+ open(low_prio_variant_file_name, 'w').write(
+ # For now, everything is a keyfile-escaped string, so AutomaticPresence
+ # is weird
+"""{
+'manager': <'fakecm'>,
+'protocol': <'fakeprotocol'>,
+'DisplayName': <'New and improved account'>,
+'AutomaticPresence': <'2;available;;'>,
+'KeyFileParameters': <{
+ 'account': 'dontdivert at example.com',
+ 'password': 'password_in_variant_file'
+ }>
+}
+""")
account_manager, properties, interfaces = resuscitate_mc(q, bus, mc)
account = get_fakecm_account(bus, mc, account_path)
@@ -169,8 +186,8 @@ AutomaticPresence=2;available;;
# Files in lower-priority XDG locations aren't copied until something
# actually changes, and they aren't deleted.
- assert not os.path.exists(new_key_file_name)
- assert os.path.exists(low_prio_key_file_name)
+ assert not os.path.exists(new_variant_file_name)
+ assert os.path.exists(low_prio_variant_file_name)
# Delete the password (only), like Empathy 3.0-3.4 do when migrating
account_iface.UpdateParameters({}, ['password'])
@@ -188,16 +205,16 @@ AutomaticPresence=2;available;;
# Check the account has copied (not moved! XDG_DATA_DIRS are,
# conceptually, read-only) from the old to the new name
assert not os.path.exists(old_key_file_name)
- assert os.path.exists(low_prio_key_file_name)
- kf = keyfile_read(new_key_file_name)
- assert 'param-password' not in kf[group]
- pwd = account_store('get', 'keyfile', 'param-password')
+ assert not os.path.exists(newer_key_file_name)
+ assert os.path.exists(low_prio_variant_file_name)
+ assert os.path.exists(new_variant_file_name)
+ pwd = account_store('get', 'variant-file', 'param-password')
assertEquals(None, pwd)
# Write out an account configuration in the old keyfile, to test
- # migration
- os.remove(new_key_file_name)
- os.remove(low_prio_key_file_name)
+ # migration from there
+ os.remove(new_variant_file_name)
+ os.remove(low_prio_variant_file_name)
open(old_key_file_name, 'w').write(
r"""# Telepathy accounts
[%s]
@@ -212,13 +229,12 @@ AutomaticPresence=2;available;;
account = get_fakecm_account(bus, mc, account_path)
account_iface = dbus.Interface(account, cs.ACCOUNT)
- # This time it *does* get moved (really copied+deleted) automatically
- # during MC startup
+ # This time it *does* get deleted automatically during MC startup,
+ # after copying its contents to the new name/format
assert not os.path.exists(old_key_file_name)
- assert not os.path.exists(low_prio_key_file_name)
- kf = keyfile_read(new_key_file_name)
- assert 'param-password' not in kf[group]
- assertEquals('Ye olde account', kf[group]['DisplayName'])
+ assert not os.path.exists(low_prio_variant_file_name)
+ assertEquals("'Ye olde account'",
+ account_store('get', 'variant-file', 'DisplayName'))
if __name__ == '__main__':
ctl_dir = os.environ['MC_ACCOUNT_DIR']
diff --git a/tests/twisted/account-storage/diverted-storage.py b/tests/twisted/account-storage/diverted-storage.py
index 2346b85..7aa011e 100644
--- a/tests/twisted/account-storage/diverted-storage.py
+++ b/tests/twisted/account-storage/diverted-storage.py
@@ -88,10 +88,6 @@ def test(q, bus, mc):
assert kf[group]['Icon'] == 'im-jabber', kf
assert kf[group]['Nickname'] == 'Joe Bloggs', kf
- # default keyfile should be empty
- ekf = keyfile_read(empty_key_file_name)
- assert ekf == { None: {} }, ekf
-
# Reactivate MC
account_manager, properties, interfaces = resuscitate_mc(q, bus, mc)
account = get_fakecm_account(bus, mc, account_path)
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-telepathy/telepathy-mission-control-6.git
More information about the Pkg-telepathy-commits
mailing list