[telepathy-gabble/master] Represent PRESENCE_CAP_JINGLE_OMITS_CONTENT_CREATOR as a pseudo-namespace

Simon McVittie simon.mcvittie at collabora.co.uk
Tue Sep 8 04:10:05 PDT 2009


---
 src/capabilities.c   |   82 ++++++++++++++++++++++++++++++++++---------------
 src/capabilities.h   |   10 +++++-
 src/presence-cache.c |    2 +-
 3 files changed, 66 insertions(+), 28 deletions(-)

diff --git a/src/capabilities.c b/src/capabilities.c
index 35c4dcc..5c7a6bd 100644
--- a/src/capabilities.c
+++ b/src/capabilities.c
@@ -75,6 +75,12 @@ static const Feature self_advertised_features[] =
   { 0, NULL, 0}
 };
 
+static const Feature quirks[] = {
+      { 0, QUIRK_OMITS_CONTENT_CREATORS,
+        PRESENCE_CAP_JINGLE_OMITS_CONTENT_CREATOR },
+      { 0, NULL, 0 }
+};
+
 const GabbleCapabilitySet *
 gabble_capabilities_get_bundle_voice_v1 ()
 {
@@ -110,9 +116,6 @@ omits_content_creators (LmMessageNode *identity)
   gchar *end;
   int ver;
 
-  if (tp_strdiff (identity->name, "identity"))
-    return FALSE;
-
   name = lm_message_node_get_attribute (identity, "name");
 
   if (name == NULL)
@@ -183,27 +186,14 @@ struct _GabbleCapabilitySet {
 };
 
 GabblePresenceCapabilities
-capabilities_parse (GabbleCapabilitySet *cap_set,
-    LmMessageNode *query_result)
+capabilities_parse (GabbleCapabilitySet *cap_set)
 {
   GabblePresenceCapabilities ret = PRESENCE_CAP_NONE;
   const gchar *var;
   const Feature *i;
-  NodeIter ni;
   TpIntSetIter iter;
 
   g_return_val_if_fail (cap_set != NULL, 0);
-  g_return_val_if_fail (query_result != NULL, 0);
-
-  /* special case: OMITS_CONTENT_CREATOR looks at the software version,
-   * not the actual features (sad face) */
-  for (ni = node_iter (query_result); ni != NULL; ni = node_iter_next (ni))
-    {
-      LmMessageNode *child = node_iter_data (ni);
-
-      if (omits_content_creators (child))
-        ret |= PRESENCE_CAP_JINGLE_OMITS_CONTENT_CREATOR;
-    }
 
   tp_intset_iter_init (&iter, tp_handle_set_peek (cap_set->handles));
 
@@ -211,17 +201,34 @@ capabilities_parse (GabbleCapabilitySet *cap_set,
     {
       var = tp_handle_inspect (feature_handles, iter.element);
 
-      for (i = self_advertised_features; i->ns != NULL; i++)
+      if (var[0] == QUIRK_PREFIX_CHAR)
         {
-          if (!tp_strdiff (var, i->ns))
+          for (i = quirks; i->ns != NULL; i++)
             {
-              ret |= i->caps;
-              break;
+              if (!tp_strdiff (var, i->ns))
+                {
+                  ret |= i->caps;
+                  break;
+                }
             }
+
+          if (i->ns == NULL)
+            g_warning ("unknown quirk: %s", var + 1);
         }
+      else
+        {
+          for (i = self_advertised_features; i->ns != NULL; i++)
+            {
+              if (!tp_strdiff (var, i->ns))
+                {
+                  ret |= i->caps;
+                  break;
+                }
+            }
 
-      if (i->ns == NULL)
-        DEBUG ("ignoring unknown capability %s", var);
+          if (i->ns == NULL)
+            DEBUG ("ignoring unknown capability %s", var);
+        }
     }
 
   return ret;
@@ -290,6 +297,16 @@ gabble_capability_set_new_from_stanza (LmMessageNode *query_result)
     {
       LmMessageNode *child = node_iter_data (ni);
 
+      if (!tp_strdiff (child->name, "identity"))
+        {
+          if (omits_content_creators (child))
+            {
+              gabble_capability_set_add (ret, QUIRK_OMITS_CONTENT_CREATORS);
+            }
+
+          continue;
+        }
+
       if (tp_strdiff (child->name, "feature"))
         continue;
 
@@ -298,6 +315,12 @@ gabble_capability_set_new_from_stanza (LmMessageNode *query_result)
       if (NULL == var)
         continue;
 
+      if (G_UNLIKELY (var[0] == QUIRK_PREFIX_CHAR))
+        {
+          /* I think not! (It's not allowed in XML...) */
+          continue;
+        }
+
       /* TODO: only store namespaces we understand. */
       gabble_capability_set_add (ret, var);
     }
@@ -318,6 +341,10 @@ gabble_capability_set_new_from_flags (GabblePresenceCapabilities caps)
     if ((i->caps & caps) == i->caps)
       gabble_capability_set_add (ret, i->ns);
 
+  for (i = quirks; NULL != i->ns; i++)
+    if ((i->caps & caps) == i->caps)
+      gabble_capability_set_add (ret, i->ns);
+
   return ret;
 }
 
@@ -434,6 +461,7 @@ gabble_capability_set_equals (const GabbleCapabilitySet *a,
       tp_handle_set_peek (b->handles));
 }
 
+/* Does not iterate over quirks, only real features. */
 void
 gabble_capability_set_foreach (const GabbleCapabilitySet *caps,
     GFunc func, gpointer user_data)
@@ -447,7 +475,11 @@ gabble_capability_set_foreach (const GabbleCapabilitySet *caps,
 
   while (tp_intset_iter_next (&iter))
     {
-      func ((gchar *) tp_handle_inspect (feature_handles, iter.element),
-          user_data);
+      const gchar *var = tp_handle_inspect (feature_handles, iter.element);
+
+      g_return_if_fail (var != NULL);
+
+      if (var[0] != QUIRK_PREFIX_CHAR)
+        func ((gchar *) var, user_data);
     }
 }
diff --git a/src/capabilities.h b/src/capabilities.h
index 74972a8..039b888 100644
--- a/src/capabilities.h
+++ b/src/capabilities.h
@@ -40,6 +40,13 @@ struct _Feature
   GabblePresenceCapabilities caps;
 };
 
+/* Pseudo-capabilities for buggy or strange implementations, represented as
+ * strings starting with a character not allowed in XML (the ASCII beep :-) */
+#define QUIRK_PREFIX_CHAR '\x07'
+#define QUIRK_PREFIX "\x07"
+/* Gabble 0.7.x with 16 <= x < 29 omits @creator on <content/> */
+#define QUIRK_OMITS_CONTENT_CREATORS "\x07omits-content-creators"
+
 /**
  * GabbleCapabilitySet:
  *
@@ -108,8 +115,7 @@ void capabilities_fill_cache (GabblePresenceCache *cache);
  */
 GabblePresenceCapabilities capabilities_get_initial_caps (void);
 
-GabblePresenceCapabilities capabilities_parse (GabbleCapabilitySet *cap_set,
-    LmMessageNode *query_result);
+GabblePresenceCapabilities capabilities_parse (GabbleCapabilitySet *cap_set);
 
 typedef GabblePresenceCapabilities (*TypeFlagsToCapsFunc) (guint typeflags);
 typedef guint (*CapsToTypeFlagsFunc) (GabblePresenceCapabilities caps);
diff --git a/src/presence-cache.c b/src/presence-cache.c
index ad131f8..fee574f 100644
--- a/src/presence-cache.c
+++ b/src/presence-cache.c
@@ -955,7 +955,7 @@ _caps_disco_cb (GabbleDisco *disco,
     }
 
   cap_set = gabble_capability_set_new_from_stanza (query_result);
-  caps = capabilities_parse (cap_set, query_result);
+  caps = capabilities_parse (cap_set);
 
   /* Only 'sha-1' is mandatory to implement by XEP-0115. If the remote contact
    * uses another hash algorithm, don't check the hash and fallback to the old
-- 
1.5.6.5




More information about the telepathy-commits mailing list