[Telepathy-commits] [telepathy-salut/master] Implement caps_hash_compute_from_stanza() with Gibber

Alban Crequy alban.crequy at collabora.co.uk
Thu Feb 26 11:20:08 PST 2009


---
 src/salut-caps-hash.c |  246 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/salut-caps-hash.h |    3 +
 2 files changed, 249 insertions(+), 0 deletions(-)

diff --git a/src/salut-caps-hash.c b/src/salut-caps-hash.c
index dc463a2..da5b754 100644
--- a/src/salut-caps-hash.c
+++ b/src/salut-caps-hash.c
@@ -54,6 +54,27 @@ struct _DataForm {
   GPtrArray *fields;
 };
 
+typedef struct _AllCapsData AllCapsData;
+
+struct _AllCapsData {
+  GPtrArray *features;
+  GPtrArray *identities;
+  GPtrArray *dataforms;
+};
+
+typedef struct _DataformParsingContext DataformParsingContext;
+
+struct _DataformParsingContext {
+    DataForm *form;
+};
+
+typedef struct _DataformFieldParsingContext DataformFieldParsingContext;
+
+struct _DataformFieldParsingContext {
+    DataformParsingContext *dataform_context;
+    DataFormField *field;
+};
+
 static void
 sha1_bin (const gchar *bytes,
           guint len,
@@ -199,6 +220,231 @@ caps_hash_compute (
 }
 
 /**
+ * parse FORM_TYPE values of a XEP-0128 dataform
+ *
+ * helper function for _parse_dataform_field
+ */
+static gboolean
+_parse_dataform_field_form_type (GibberXmppNode *value_node, gpointer user_data)
+{
+  DataformFieldParsingContext *dataform_field_context =
+    (DataformFieldParsingContext *) user_data;
+
+  if (tp_strdiff (value_node->name, "value"))
+    return TRUE;
+
+  /* If the stanza is correctly formed, there is only one
+   * FORM_TYPE and this check is useless. Otherwise, just
+   * use the first one */
+  if (dataform_field_context->dataform_context->form->form_type == NULL)
+    dataform_field_context->dataform_context->form->form_type =
+      g_strdup (value_node->content);
+
+  return TRUE;
+}
+
+
+/**
+ * parse values of a field of a XEP-0128 dataform
+ *
+ * helper function for _parse_caps_item
+ */
+static gboolean
+_parse_dataform_field_values (GibberXmppNode *value_node, gpointer user_data)
+{
+  DataformFieldParsingContext *dataform_field_context =
+    (DataformFieldParsingContext *) user_data;
+
+  if (tp_strdiff (value_node->name, "value"))
+    return TRUE;
+
+  g_ptr_array_add (dataform_field_context->field->values,
+      g_strdup (value_node->content));
+
+  return TRUE;
+}
+
+/**
+ * parse a field of a XEP-0128 dataform
+ *
+ * helper function for _parse_caps_item
+ */
+static gboolean
+_parse_dataform_field (GibberXmppNode *field_node, gpointer user_data)
+{
+  DataformParsingContext *dataform_context =
+    (DataformParsingContext *) user_data;
+  const gchar *var;
+
+  if (! g_str_equal (field_node->name, "field"))
+    return TRUE;
+
+  var = gibber_xmpp_node_get_attribute (field_node, "var");
+
+  if (NULL == var)
+    return TRUE;
+
+  if (g_str_equal (var, "FORM_TYPE"))
+    {
+      DataformFieldParsingContext *dataform_field_context;
+      dataform_field_context = g_slice_new0 (DataformFieldParsingContext);
+      dataform_field_context->dataform_context = dataform_context;
+      dataform_field_context->field = NULL;
+
+      gibber_xmpp_node_each_child (field_node,
+          _parse_dataform_field_form_type, dataform_field_context);
+
+      g_slice_free (DataformFieldParsingContext, dataform_field_context);
+    }
+  else
+    {
+      DataformFieldParsingContext *dataform_field_context;
+      DataFormField *field = NULL;
+
+      field = g_slice_new0 (DataFormField);
+      field->values = g_ptr_array_new ();
+      field->field_name = g_strdup (var);
+
+      dataform_field_context = g_slice_new0 (DataformFieldParsingContext);
+      dataform_field_context->dataform_context = dataform_context;
+      dataform_field_context->field = field;
+
+      gibber_xmpp_node_each_child (field_node,
+          _parse_dataform_field_values, dataform_field_context);
+
+      g_slice_free (DataformFieldParsingContext, dataform_field_context);
+
+      g_ptr_array_add (dataform_context->form->fields, (gpointer) field);
+    }
+
+  return TRUE;
+}
+
+/**
+ * parse a XEP-0128 dataform
+ *
+ * helper function for _parse_caps_item
+ */
+static DataForm *
+_parse_dataform (GibberXmppNode *node)
+{
+  DataForm *form;
+  DataformParsingContext *dataform_context;
+
+  form = g_slice_new0 (DataForm);
+  form->form_type = NULL;
+  form->fields = g_ptr_array_new ();
+
+  dataform_context = g_slice_new0 (DataformParsingContext);
+  dataform_context->form = form;
+
+  gibber_xmpp_node_each_child (node, _parse_dataform_field, dataform_context);
+
+  g_slice_free (DataformParsingContext, dataform_context);
+
+  /* this should not happen if the stanza is correctly formed. */
+  if (form->form_type == NULL)
+    form->form_type = g_strdup ("");
+
+  return form;
+}
+
+/**
+ * parse a XML child node from from a received GibberXmppStanza
+ *
+ * helper function for caps_hash_compute_from_stanza
+ */
+static gboolean
+_parse_caps_item (GibberXmppNode *node, gpointer user_data)
+{
+  AllCapsData *caps_data = (AllCapsData *) user_data;
+
+  if (g_str_equal (node->name, "identity"))
+    {
+      const gchar *category;
+      const gchar *name;
+      const gchar *type;
+      const gchar *xmllang;
+
+      category = gibber_xmpp_node_get_attribute (node, "category");
+      name = gibber_xmpp_node_get_attribute (node, "name");
+      type = gibber_xmpp_node_get_attribute (node, "type");
+      xmllang = gibber_xmpp_node_get_attribute (node, "xml:lang");
+
+      if (NULL == category)
+        return FALSE;
+      if (NULL == name)
+        name = "";
+      if (NULL == type)
+        type = "";
+      if (NULL == xmllang)
+        xmllang = "";
+
+      g_ptr_array_add (caps_data->identities,
+          g_strdup_printf ("%s/%s/%s/%s", category, type, xmllang, name));
+    }
+  else if (g_str_equal (node->name, "feature"))
+    {
+      const gchar *var;
+      var = gibber_xmpp_node_get_attribute (node, "var");
+
+      if (NULL == var)
+        return FALSE;
+
+      g_ptr_array_add (caps_data->features, g_strdup (var));
+    }
+  else if (g_str_equal (node->name, "x"))
+    {
+      const gchar *xmlns;
+      const gchar *type;
+
+      xmlns = gibber_xmpp_node_get_attribute (node, "xmlns");
+      type = gibber_xmpp_node_get_attribute (node, "type");
+
+      if (tp_strdiff (xmlns, "jabber:x:data"))
+        return FALSE;
+
+      if (tp_strdiff (type, "result"))
+        return FALSE;
+
+      g_ptr_array_add (caps_data->dataforms, (gpointer) _parse_dataform (node));
+    }
+
+  return TRUE;
+}
+
+
+/**
+ * Compute the hash as defined by the XEP-0115 from a received
+ * GibberXmppStanza
+ *
+ * Returns: the hash. The called must free the returned hash with g_free().
+ */
+gchar *
+caps_hash_compute_from_stanza (GibberXmppStanza *stanza)
+{
+  GibberXmppNode *node = stanza->node;
+  gchar *str;
+  AllCapsData *caps_data;
+
+  caps_data = g_slice_new0 (AllCapsData);
+  caps_data->features = g_ptr_array_new ();
+  caps_data->identities = g_ptr_array_new ();
+  caps_data->dataforms = g_ptr_array_new ();
+
+  gibber_xmpp_node_each_child (node, _parse_caps_item, caps_data);
+
+  str = caps_hash_compute (caps_data->features, caps_data->identities,
+      caps_data->dataforms);
+
+  salut_presence_free_xep0115_hash (caps_data->features,
+      caps_data->identities, caps_data->dataforms);
+  g_slice_free (AllCapsData, caps_data);
+
+  return str;
+}
+
+/**
  * Compute our hash as defined by the XEP-0115.
  *
  * Returns: the hash. The called must free the returned hash with g_free().
diff --git a/src/salut-caps-hash.h b/src/salut-caps-hash.h
index 290c51e..0bf5371 100644
--- a/src/salut-caps-hash.h
+++ b/src/salut-caps-hash.h
@@ -24,6 +24,9 @@
 
 #include "salut-self.h"
 
+#include <gibber/gibber-xmpp-stanza.h>
+
+gchar *caps_hash_compute_from_stanza (GibberXmppStanza *stanza);
 gchar *caps_hash_compute_from_self_presence (SalutSelf *self);
 
 #endif /* __SALUT_CAPS_HASH_H__ */
-- 
1.5.6.5




More information about the telepathy-commits mailing list