[telepathy-glib/master] Add tp_account_parse_object_path

Will Thompson will.thompson at collabora.co.uk
Mon Sep 28 07:39:13 PDT 2009


Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
---
 docs/reference/telepathy-glib-sections.txt |    1 +
 telepathy-glib/account.c                   |  107 ++++++++++++++++++++++++++++
 telepathy-glib/account.h                   |    3 +
 tests/dbus/account.c                       |   89 ++++++++++++++++++++++-
 4 files changed, 197 insertions(+), 3 deletions(-)

diff --git a/docs/reference/telepathy-glib-sections.txt b/docs/reference/telepathy-glib-sections.txt
index 9097d2b..48055db 100644
--- a/docs/reference/telepathy-glib-sections.txt
+++ b/docs/reference/telepathy-glib-sections.txt
@@ -2988,6 +2988,7 @@ TpAccount
 TpAccountClass
 tp_account_new
 tp_account_init_known_interfaces
+tp_account_parse_object_path
 tp_account_is_just_connected
 tp_account_get_connection
 tp_account_ensure_connection
diff --git a/telepathy-glib/account.c b/telepathy-glib/account.c
index 8e940b5..e7b23ae 100644
--- a/telepathy-glib/account.c
+++ b/telepathy-glib/account.c
@@ -2475,3 +2475,110 @@ tp_account_get_features (TpAccount *account)
 {
   return (const GQuark *) account->priv->features_array->data;
 }
+
+static void
+set_or_free (gchar **target,
+    gchar *source)
+{
+  if (target != NULL)
+    *target = source;
+  else
+    g_free (source);
+}
+
+/**
+ * tp_parse_account_path:
+ * @object_path: a Telepathy Account's object path
+ * @cm: location at which to store the account's connection manager's name
+ * @protocol: location at which to store the account's protocol
+ * @account_id: location at which to store the account's unique identifier
+ * @error: location at which to return an error
+ *
+ * Validates and parses a Telepathy Account's object path, extracting the
+ * connection manager's name, the protocol, and the account's unique identifier
+ * from the path. This includes replacing underscores with hyphens in the
+ * protocol name, as defined in the Account specification.
+ *
+ * Any of the out parameters may be %NULL if not needed.
+ *
+ * Returns: %TRUE if @object_path was successfully parsed; %FALSE and sets
+ *          @error otherwise.
+ */
+gboolean
+tp_account_parse_object_path (const gchar *object_path,
+    gchar **cm,
+    gchar **protocol,
+    gchar **account_id,
+    GError **error)
+{
+  const gchar *suffix;
+  gchar **segments;
+
+  if (!tp_dbus_check_valid_object_path (object_path, error))
+    return FALSE;
+
+  if (!g_str_has_prefix (object_path, TP_ACCOUNT_OBJECT_PATH_BASE))
+    {
+      g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+          "Account path does not start with the right prefix: %s",
+          object_path);
+      return FALSE;
+    }
+
+  suffix = object_path + strlen (TP_ACCOUNT_OBJECT_PATH_BASE);
+
+  segments = g_strsplit (suffix, "/", 0);
+
+  if (g_strv_length (segments) != 3)
+    {
+      g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+          "Account path '%s' is malformed: should have 3 trailing components, "
+          "not %u", object_path, g_strv_length (segments));
+      goto free_segments_and_fail;
+    }
+
+  if (!g_ascii_isalpha (segments[0][0]))
+    {
+      g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+          "Account path '%s' is malformed: CM name should start with a letter",
+          object_path);
+      goto free_segments_and_fail;
+    }
+
+  if (!g_ascii_isalpha (segments[1][0]))
+    {
+      g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+          "Account path '%s' is malformed: "
+          "protocol name should start with a letter",
+          object_path);
+      goto free_segments_and_fail;
+    }
+
+  if (!g_ascii_isalpha (segments[2][0]) && segments[2][0] != '_')
+    {
+      g_set_error (error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+          "Account path '%s' is malformed: "
+          "account ID should start with a letter or underscore",
+          object_path);
+      goto free_segments_and_fail;
+    }
+
+  set_or_free (cm, segments[0]);
+
+  /* XXX: work around MC5 bug where it escapes with tp_escape_as_identifier
+   * rather than doing it properly. MC5 saves the object path in your config,
+   * so if you've ever used a buggy MC5, the path will be wrong forever.
+   */
+  g_strdelimit (segments[1], "_", '-');
+  set_or_free (protocol, segments[1]);
+
+  set_or_free (account_id, segments[2]);
+
+  /* Not g_strfreev because we stole or freed the individual strings */
+  g_free (segments);
+  return TRUE;
+
+free_segments_and_fail:
+  g_strfreev (segments);
+  return FALSE;
+}
diff --git a/telepathy-glib/account.h b/telepathy-glib/account.h
index fcc3d21..2af0077 100644
--- a/telepathy-glib/account.h
+++ b/telepathy-glib/account.h
@@ -72,6 +72,9 @@ GType tp_account_get_type (void);
 TpAccount *tp_account_new (TpDBusDaemon *bus_daemon, const gchar *object_path,
     GError **error);
 
+gboolean tp_account_parse_object_path (const gchar *object_path,
+    gchar **cm, gchar **protocol, gchar **account_id, GError **error);
+
 void tp_account_init_known_interfaces (void);
 
 gboolean tp_account_is_just_connected (TpAccount *account);
diff --git a/tests/dbus/account.c b/tests/dbus/account.c
index aeb8762..accc15f 100644
--- a/tests/dbus/account.c
+++ b/tests/dbus/account.c
@@ -10,6 +10,62 @@
 
 #include <telepathy-glib/account.h>
 #include <telepathy-glib/debug.h>
+#include <telepathy-glib/defs.h>
+
+static void
+test_parse_failure (gconstpointer test_data)
+{
+  GError *error = NULL;
+
+  g_assert (!tp_account_parse_object_path (test_data, NULL, NULL, NULL,
+      &error));
+  g_assert (error != NULL);
+  g_error_free (error);
+}
+
+typedef struct {
+    const gchar *path;
+    const gchar *cm;
+    const gchar *protocol;
+    const gchar *account_id;
+} TestParseData;
+
+static TestParseData *
+test_parse_data_new (const gchar *path,
+    const gchar *cm,
+    const gchar *protocol,
+    const gchar *account_id)
+{
+  TestParseData *t = g_slice_new (TestParseData);
+
+  t->path = path;
+  t->cm = cm;
+  t->protocol = protocol;
+  t->account_id = account_id;
+
+  return t;
+}
+
+static void
+test_parse_success (gconstpointer test_data)
+{
+  TestParseData *t = (TestParseData *) test_data;
+  gchar *cm, *protocol, *account_id;
+  GError *error = NULL;
+
+  g_assert (tp_account_parse_object_path (t->path, &cm, &protocol, &account_id,
+      &error));
+  g_assert_no_error (error);
+  g_assert_cmpstr (cm, ==, t->cm);
+  g_assert_cmpstr (protocol, ==, t->protocol);
+  g_assert_cmpstr (account_id, ==, t->account_id);
+
+  g_free (cm);
+  g_free (protocol);
+  g_free (account_id);
+
+  g_slice_free (TestParseData, t);
+}
 
 typedef struct {
     GMainLoop *mainloop;
@@ -23,9 +79,6 @@ static void
 setup (Test *test,
        gconstpointer data)
 {
-  g_type_init ();
-  tp_debug_set_flags ("all");
-
   test->mainloop = g_main_loop_new (NULL, FALSE);
   test->dbus = tp_dbus_daemon_dup (NULL);
   g_assert (test->dbus != NULL);
@@ -70,9 +123,39 @@ int
 main (int argc,
       char **argv)
 {
+  g_type_init ();
+  tp_debug_set_flags ("all");
+
   g_test_init (&argc, &argv, NULL);
   g_test_bug_base ("http://bugs.freedesktop.org/show_bug.cgi?id=");
 
+  g_test_add_data_func ("/account/parse/spaces",
+      "this is not an object path", test_parse_failure);
+  g_test_add_data_func ("/account/parse/no-prefix",
+      "/this/is/not/an/account/path", test_parse_failure);
+  g_test_add_data_func ("/account/parse/too-few-components",
+      "/org/freedesktop/Telepathy/Account/wrong", test_parse_failure);
+  g_test_add_data_func ("/account/parse/too-many-components",
+      "/org/freedesktop/Telepathy/Account/a/b/c/d", test_parse_failure);
+  g_test_add_data_func ("/account/parse/illegal-components",
+      "/org/freedesktop/Telepathy/Account/1/2/3", test_parse_failure);
+
+  g_test_add_data_func ("/account/parse/legal",
+      test_parse_data_new (
+          TP_ACCOUNT_OBJECT_PATH_BASE "gabble/jabber/badgers",
+          "gabble", "jabber", "badgers"),
+      test_parse_success);
+  g_test_add_data_func ("/account/parse/hyphenated-protocol",
+      test_parse_data_new (
+          TP_ACCOUNT_OBJECT_PATH_BASE "salut/local_xmpp/badgers",
+          "salut", "local-xmpp", "badgers"),
+      test_parse_success);
+  g_test_add_data_func ("/account/parse/underscored-account",
+      test_parse_data_new (
+          TP_ACCOUNT_OBJECT_PATH_BASE "haze/msn/_thisseemsunlikely",
+          "haze", "msn", "_thisseemsunlikely"),
+      test_parse_success);
+
   g_test_add ("/account/new", Test, NULL, setup, test_new, teardown);
 
   return g_test_run ();
-- 
1.5.6.5




More information about the telepathy-commits mailing list