[Telepathy-commits] [telepathy-gabble/master] Implement hash for dataforms

Alban Crequy alban.crequy at collabora.co.uk
Tue Aug 19 10:52:31 PDT 2008


20080508171942-a41c0-c9e04d3daa788ae871a0c48c7b7c0fdceadd05e8.gz
---
 src/presence.c |  144 +++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 133 insertions(+), 11 deletions(-)

diff --git a/src/presence.c b/src/presence.c
index 6f438ab..d4940be 100644
--- a/src/presence.c
+++ b/src/presence.c
@@ -478,35 +478,89 @@ feature_strcmp (gconstpointer a, gconstpointer b)
   return strcmp (left, right);
 }
 
+struct _dataform_field {
+  gchar *fieldname;
+  GPtrArray *values;
+};
+
+struct _dataform {
+  gchar *form_type;
+  GPtrArray *fields;
+};
+
+static gint
+fields_cmp (gconstpointer a, gconstpointer b)
+{
+  struct _dataform_field *left = *(struct _dataform_field **) a;
+  struct _dataform_field *right = *(struct _dataform_field **) b;
+
+  return strcmp (left->fieldname, right->fieldname);
+}
+
+static gint
+dataforms_cmp (gconstpointer a, gconstpointer b)
+{
+  struct _dataform *left = *(struct _dataform **) a;
+  struct _dataform *right = *(struct _dataform **) b;
+
+  return strcmp (left->form_type, right->form_type);
+}
+
 static gchar *
 gabble_presence_compute_xep0115_hash (
     GPtrArray *features,
-    GPtrArray *identities)
+    GPtrArray *identities,
+    GPtrArray *dataforms)
 {
   GString *s;
   gchar *str;
   gchar sha1[SHA1_HASH_SIZE];
-  unsigned int j;
+  unsigned int i, j, k;
   gchar *encoded;
 
   g_ptr_array_sort (identities, feature_strcmp);
   g_ptr_array_sort (features, feature_strcmp);
+  g_ptr_array_sort (dataforms, dataforms_cmp);
 
   s = g_string_new ("");
 
-  for (j = 0 ; j < identities->len ; j++)
+  for (i = 0 ; i < identities->len ; i++)
     {
-      s = g_string_append (s, g_ptr_array_index (identities, j));
+      s = g_string_append (s, g_ptr_array_index (identities, i));
       s = g_string_append (s, "<");
     }
 
-  for (j = 0 ; j < features->len ; j++)
+  for (i = 0 ; i < features->len ; i++)
     {
-      s = g_string_append (s, g_ptr_array_index (features, j));
+      s = g_string_append (s, g_ptr_array_index (features, i));
       s = g_string_append (s, "<");
     }
 
-  /* FIXME: add XEP-0128 data forms in the hash */
+  for (i = 0 ; i < dataforms->len ; i++)
+    {
+      struct _dataform *form = g_ptr_array_index (features, i);
+
+      s = g_string_append (s, form->form_type);
+      s = g_string_append (s, "<");
+
+      g_ptr_array_sort (form->fields, fields_cmp);
+
+      for (j = 0 ; j < form->fields->len ; j++)
+        {
+          struct _dataform_field *field = g_ptr_array_index (form->fields, j);
+
+          s = g_string_append (s, field->fieldname);
+          s = g_string_append (s, "<");
+
+          g_ptr_array_sort (field->values, fields_cmp);
+
+          for (k = 0 ; k < field->values->len ; k++)
+            {
+              s = g_string_append (s, g_ptr_array_index (field->values, k));
+              s = g_string_append (s, "<");
+            }
+        }
+    }
 
   str = g_string_free (s, FALSE);
   DEBUG ("caps string: '%s'\n", str);
@@ -529,6 +583,7 @@ gabble_presence_compute_xep0115_hash_from_lm_node (LmMessageNode *node)
 {
   GPtrArray *features = g_ptr_array_new ();
   GPtrArray *identities = g_ptr_array_new ();
+  GPtrArray *dataforms = g_ptr_array_new ();
   LmMessageNode *child;
   gchar *str;
 
@@ -569,13 +624,76 @@ gabble_presence_compute_xep0115_hash_from_lm_node (LmMessageNode *node)
 
           g_ptr_array_add (features, (gpointer) g_strdup (var));
         }
+      else if (g_str_equal (child->name, "x"))
+        {
+          const gchar *xmlns;
+          const gchar *type;
+          LmMessageNode *x_child;
+          struct _dataform *form;
+
+          xmlns = lm_message_node_get_attribute (child, "xmlns");
+          type = lm_message_node_get_attribute (child, "type");
+
+          if (! g_str_equal (xmlns, "jabber:x:data"))
+            continue;
 
+          if (! g_str_equal (type, "result"))
+            continue;
+
+          form = g_slice_new0 (struct _dataform);
+
+          for (x_child = child->children;
+               NULL != x_child;
+               x_child = x_child->next)
+            {
+              const gchar *var;
+              LmMessageNode *value_child;
+              struct _dataform_field *field;
+
+              if (! g_str_equal (x_child->name, "field"))
+                continue;
+
+              var = lm_message_node_get_attribute (x_child, "var");
+
+              if (NULL == var)
+                continue;
+
+              field = g_slice_new0 (struct _dataform_field);
+
+              for (value_child = x_child->children;
+                   NULL != value_child;
+                   value_child = value_child->next)
+                {
+                  const gchar *content;
+
+                  if (! g_str_equal (value_child->name, "value"))
+                    continue;
+
+                  if (g_str_equal (var, "FORM_TYPE"))
+                    {
+                      form->form_type = g_strdup (var);
+                    }
+                  else
+                    {
+                      content = lm_message_node_get_value (value_child);
+                      g_ptr_array_add (field->values,
+                          (gpointer) g_strdup (content));
+                    }
+                }
+
+              g_ptr_array_add (form->fields, (gpointer) field);
+            }
+
+          g_ptr_array_add (dataforms, (gpointer) form);
+        }
     }
 
-  str = gabble_presence_compute_xep0115_hash (features, identities);
+  str = gabble_presence_compute_xep0115_hash (features, identities, dataforms);
 
   g_ptr_array_free (features, TRUE);
   g_ptr_array_free (identities, TRUE);
+  g_ptr_array_free (dataforms, TRUE);
+  /* TODO: also free content of dataforms */
 
   return str;
 }
@@ -588,23 +706,27 @@ gabble_presence_compute_xep0115_hash_from_self_presence (GabbleConnection *self)
   GSList *features_list = capabilities_get_features (presence->caps);
   GPtrArray *features = g_ptr_array_new ();
   GPtrArray *identities = g_ptr_array_new ();
+  GPtrArray *dataforms = g_ptr_array_new ();
   gchar *str;
   GSList *i;
 
+  /* get our features list  */
   for (i = features_list; NULL != i; i = i->next)
     {
       const Feature *feat = (const Feature *) i->data;
       g_ptr_array_add (features, (gpointer) feat->ns);
     }
 
-  g_ptr_array_sort (features, feature_strcmp);
-
+  /* XEP-0030 requires at least 1 identity. We don't need more. */
   g_ptr_array_add (features, (gpointer) "client/pc//" PACKAGE_STRING);
 
-  str = gabble_presence_compute_xep0115_hash (features, identities);
+  /* Gabble does not use dataforms, let 'dataforms' be empty */
+
+  str = gabble_presence_compute_xep0115_hash (features, identities, dataforms);
 
   g_ptr_array_free (features, TRUE);
   g_ptr_array_free (identities, TRUE);
+  g_ptr_array_free (dataforms, TRUE);
   g_slist_free (features_list);
 
   return str;
-- 
1.5.6.3




More information about the Telepathy-commits mailing list