[Telepathy-commits] [telepathy-salut/master] Import capability code from Gabble

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


---
 src/Makefile.am                  |    8 ++
 src/base64.c                     |  196 +++++++++++++++++++++++++++++++
 src/base64.h                     |   28 +++++
 src/debug.h                      |   36 +++---
 src/salut-capabilities.c         |   60 ++++++++++
 src/salut-capabilities.h         |   46 ++++++++
 src/salut-caps-channel-manager.c |  191 ++++++++++++++++++++++++++++++
 src/salut-caps-channel-manager.h |  140 ++++++++++++++++++++++
 src/salut-caps-hash.c            |  236 ++++++++++++++++++++++++++++++++++++++
 src/salut-caps-hash.h            |   29 +++++
 src/salut-self.h                 |    1 +
 11 files changed, 954 insertions(+), 17 deletions(-)
 create mode 100644 src/base64.c
 create mode 100644 src/base64.h
 create mode 100644 src/salut-capabilities.c
 create mode 100644 src/salut-capabilities.h
 create mode 100644 src/salut-caps-channel-manager.c
 create mode 100644 src/salut-caps-channel-manager.h
 create mode 100644 src/salut-caps-hash.c
 create mode 100644 src/salut-caps-hash.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 9c1af61..3b6d3ab 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -15,6 +15,14 @@ libexec_PROGRAMS=telepathy-salut
 noinst_PROGRAMS = write-mgr-file
 
 CORE_SOURCES =                                          \
+    base64.c                                            \
+    base64.h                                            \
+    salut-capabilities.c                                \
+    salut-capabilities.h                                \
+    salut-caps-channel-manager.c                        \
+    salut-caps-channel-manager.h                        \
+    salut-caps-hash.c                                   \
+    salut-caps-hash.h                                   \
     salut-connection-manager.c                          \
     salut-connection-manager.h                          \
     salut-contact-manager.c                             \
diff --git a/src/base64.c b/src/base64.c
new file mode 100644
index 0000000..475b903
--- /dev/null
+++ b/src/base64.c
@@ -0,0 +1,196 @@
+/*
+ * base64.c - Base 64 encoding/decoding implementation
+ * Copyright (C) 2006 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "config.h"
+#include "base64.h"
+
+#define DEBUG_FLAG DEBUG_CAPS
+#include "debug.h"
+
+#include <ctype.h>
+#include <string.h>
+
+
+/*
+|AAAA AABB|BBBB CCCC|CCDD DDDD|
+
+0xFC = 1111 1100
+0x03 = 0000 0011
+0xF0 = 1111 0000
+0x0F = 0000 1111
+0xC0 = 1100 0000
+0x3F = 0011 1111
+
+3 input bytes = 4 output bytes;
+2 input bytes = 2 output bytes;
+1 input byte  = 1 output byte.
+*/
+
+static const gchar *encoding =
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static const guint decoding[256] =
+{
+  /* ... */
+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+   0, 0, 0,
+  /* + */
+  62,
+  /* ... */
+   0, 0, 0,
+  /* / , 0-9 */
+  63,
+  52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+  /* ... */
+   0, 0, 0, 0, 0, 0, 0,
+  /* A */
+   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12,
+  13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+  /* ... */
+   0, 0, 0, 0, 0, 0,
+  /* a */
+  26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+  39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
+};
+
+#define GET_6_BITS_0(s) (((s)[0] & 0xFC) >> 2)
+#define GET_6_BITS_1(s) (((s)[0] & 0x03) << 4) | \
+                        (((s)[1] & 0xF0) >> 4)
+#define GET_6_BITS_2(s) (((s)[1] & 0x0F) << 2) | \
+                        (((s)[2] & 0xC0) >> 6)
+#define GET_6_BITS_3(s) (((s)[2] & 0x3F) << 0)
+
+#define GET_BYTE_0(s) (((decoding[(guchar)(s)[0]] & 0x3F) << 2) | \
+                       ((decoding[(guchar)(s)[1]] & 0x30) >> 4))
+#define GET_BYTE_1(s) (((decoding[(guchar)(s)[1]] & 0x0F) << 4) | \
+                       ((decoding[(guchar)(s)[2]] & 0x3C) >> 2))
+#define GET_BYTE_2(s) (((decoding[(guchar)(s)[2]] & 0x03) << 6) | \
+                       ((decoding[(guchar)(s)[3]] & 0xFF) << 0))
+
+gchar *base64_encode (guint len, const gchar *str, gboolean split_lines)
+{
+  guint i;
+  GString *tmp;
+
+  /* TODO: calculate requisite output string length and allocate that big a
+   * GString */
+  tmp = g_string_new ("");
+
+  for (i = 0; i < len; i += 3)
+    {
+      guint c1, c2, c3, c4;
+
+      if (split_lines && i > 0 && (i * 4) % 76 == 0)
+          g_string_append_c (tmp, '\n');
+
+      switch (i + 3 - len)
+        {
+        case 1:
+          c1 = encoding[GET_6_BITS_0 (str + i)];
+          c2 = encoding[GET_6_BITS_1 (str + i)];
+          /* can't use GET_6_BITS_2 because str[i+2] is out of range */
+          c3 = encoding[(str[i + 1] & 0x0f) << 2];
+          c4 = '=';
+          break;
+        case 2:
+          c1 = encoding[GET_6_BITS_0 (str + i)];
+          /* can't use GET_6_BITS_1 because str[i+1] is out of range */
+          c2 = encoding[(str[i] & 0x03) << 4];
+          c3 = '=';
+          c4 = '=';
+          break;
+        default:
+          c1 = encoding[GET_6_BITS_0 (str + i)];
+          c2 = encoding[GET_6_BITS_1 (str + i)];
+          c3 = encoding[GET_6_BITS_2 (str + i)];
+          c4 = encoding[GET_6_BITS_3 (str + i)];
+        }
+
+      g_string_append_printf (tmp, "%c%c%c%c", c1, c2, c3, c4);
+    }
+
+  return g_string_free (tmp, FALSE);
+}
+
+GString *base64_decode (const gchar *str)
+{
+  guint i;
+  GString *tmp;
+  char group[4];
+  guint filled = 0;
+
+  for (i = 0; str[i]; i++)
+    {
+      if (str[i] != 'A' &&
+          str[i] != '=' &&
+          !isspace (str[i]) &&
+          decoding[(guchar) str[i]] == 0)
+        {
+          DEBUG ("bad character %x at byte %u", (guchar)str[i], i);
+          return NULL;
+        }
+    }
+
+  tmp = g_string_new ("");
+
+  for (i = 0; str[i]; i++)
+    {
+      if (isspace (str[i]))
+        continue;
+
+      group[filled++] = str[i];
+
+      if (filled == 4)
+        {
+          if (group[3] == '=')
+            {
+              if (group[2] == '=')
+                {
+                  g_string_append_c (tmp, GET_BYTE_0(group));
+                }
+              else
+                {
+                  g_string_append_c (tmp, GET_BYTE_0(group));
+                  g_string_append_c (tmp, GET_BYTE_1(group));
+                }
+             }
+           else
+            {
+              g_string_append_c (tmp, GET_BYTE_0(group));
+              g_string_append_c (tmp, GET_BYTE_1(group));
+              g_string_append_c (tmp, GET_BYTE_2(group));
+            }
+          filled = 0;
+        }
+    }
+
+  if (filled)
+    {
+      DEBUG ("insufficient padding at end of base64 string:\n%s", str);
+      g_string_free (tmp, TRUE);
+      return NULL;
+    }
+
+  return tmp;
+}
+
+
diff --git a/src/base64.h b/src/base64.h
new file mode 100644
index 0000000..35bd8f4
--- /dev/null
+++ b/src/base64.h
@@ -0,0 +1,28 @@
+/*
+ * base64.h - Base 64 encoding/decoding implementation
+ * Copyright (C) 2006 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __BASE64_H__
+#define __BASE64_H__
+
+#include <glib.h>
+
+gchar *base64_encode (guint len, const gchar *str, gboolean split_lines);
+GString *base64_decode (const gchar *str);
+
+#endif /* __BASE64_H__ */
diff --git a/src/debug.h b/src/debug.h
index 0d80cd8..97be397 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -14,23 +14,25 @@ typedef enum
 {
   DEBUG_PRESENCE       = 1 << 0,
   DEBUG_GROUPS         = 1 << 1,
-  DEBUG_CONTACTS       = 1 << 2,
-  DEBUG_DISCO          = 1 << 3,
-  DEBUG_PROPERTIES     = 1 << 4,
-  DEBUG_ROOMLIST       = 1 << 5,
-  DEBUG_MEDIA          = 1 << 6,
-  DEBUG_MUC            = 1 << 7,
-  DEBUG_MUC_CONNECTION = 1 << 8,
-  DEBUG_CONNECTION     = 1 << 9,
-  DEBUG_IM             = 1 << 10,
-  DEBUG_SI_BYTESTREAM_MGR = 1 << 11,
-  DEBUG_NET            = 1 << 12,
-  DEBUG_SELF           = 1 << 13,
-  DEBUG_TUBES          = 1 << 14,
-  DEBUG_XCM            = 1 << 15,
-  DEBUG_DISCOVERY      = 1 << 16,
-  DEBUG_OLPC_ACTIVITY  = 1 << 17,
-  DEBUG_FT             = 1 << 18,
+  DEBUG_CAPS           = 1 << 2,
+  DEBUG_CONTACTS       = 1 << 3,
+  DEBUG_DISCO          = 1 << 4,
+  DEBUG_PROPERTIES     = 1 << 5,
+  DEBUG_ROOMLIST       = 1 << 6,
+  DEBUG_MEDIA          = 1 << 7,
+  DEBUG_MUC            = 1 << 8,
+  DEBUG_MUC_CONNECTION = 1 << 9,
+  DEBUG_CONNECTION     = 1 << 10,
+  DEBUG_IM             = 1 << 11,
+  DEBUG_SI_BYTESTREAM_MGR     = 1 << 12,
+  DEBUG_DIRECT_BYTESTREAM_MGR = 1 << 13,
+  DEBUG_NET            = 1 << 14,
+  DEBUG_SELF           = 1 << 15,
+  DEBUG_TUBES          = 1 << 16,
+  DEBUG_XCM            = 1 << 17,
+  DEBUG_DISCOVERY      = 1 << 18,
+  DEBUG_OLPC_ACTIVITY  = 1 << 19,
+  DEBUG_FT             = 1 << 20,
 } DebugFlags;
 
 void debug_set_flags_from_env (void);
diff --git a/src/salut-capabilities.c b/src/salut-capabilities.c
new file mode 100644
index 0000000..1d722f5
--- /dev/null
+++ b/src/salut-capabilities.c
@@ -0,0 +1,60 @@
+/*
+ * capabilities.c - Connection.Interface.Capabilities constants and utilities
+ * Copyright (C) 2005-2008 Collabora Ltd.
+ * Copyright (C) 2005-2008 Nokia Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "config.h"
+#include "salut-capabilities.h"
+
+#include <gibber/gibber-namespaces.h>
+#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/channel-manager.h>
+
+#include "salut-caps-channel-manager.h"
+
+static const Feature self_advertised_features[] =
+{
+  { FEATURE_FIXED, GIBBER_XMPP_NS_SI},
+  { FEATURE_FIXED, GIBBER_XMPP_NS_IBB},
+  { FEATURE_FIXED, GIBBER_TELEPATHY_NS_TUBES},
+
+  { 0, NULL}
+};
+
+GSList *
+capabilities_get_features (GHashTable *per_channel_manager_caps)
+{
+  GHashTableIter channel_manager_iter;
+  SalutCapsChannelManager *manager;
+  gpointer cap;
+  GSList *features = NULL;
+
+  if (per_channel_manager_caps != NULL)
+    {
+      g_hash_table_iter_init (&channel_manager_iter, per_channel_manager_caps);
+      while (g_hash_table_iter_next (&channel_manager_iter,
+                 (gpointer *) &manager, &cap))
+        {
+          salut_caps_channel_manager_get_feature_list (manager, cap,
+              &features);
+        }
+    }
+
+  return features;
+}
+
diff --git a/src/salut-capabilities.h b/src/salut-capabilities.h
new file mode 100644
index 0000000..e35e726
--- /dev/null
+++ b/src/salut-capabilities.h
@@ -0,0 +1,46 @@
+/*
+ * salut-capabilities.h - Capabilities constants and utilities
+ * Copyright (C) 2005-2008 Collabora Ltd.
+ * Copyright (C) 2005-2008 Nokia Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __SALUT_CAPABILITIES__H__
+#define __SALUT_CAPABILITIES__H__
+
+#include <glib-object.h>
+
+typedef struct _Feature Feature;
+
+struct _Feature
+{
+  enum {
+    FEATURE_FIXED,
+    FEATURE_OPTIONAL,
+  } feature_type;
+  const gchar *ns;
+};
+
+/*
+ * capabilities_get_features
+ *
+ * Return a linked list of const Feature structs corresponding to the given
+ * caps.
+ */
+GSList *capabilities_get_features (GHashTable *per_channel_manager_caps);
+
+#endif  /* __SALUT_CAPABILITIES__H__ */
+
diff --git a/src/salut-caps-channel-manager.c b/src/salut-caps-channel-manager.c
new file mode 100644
index 0000000..b79f236
--- /dev/null
+++ b/src/salut-caps-channel-manager.c
@@ -0,0 +1,191 @@
+/*
+ * caps-channel-manager.c - interface holding capabilities functions for
+ * channel managers
+ *
+ * Copyright (C) 2008 Collabora Ltd.
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "config.h"
+#include "salut-caps-channel-manager.h"
+
+#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/channel-manager.h>
+
+
+GType
+salut_caps_channel_manager_get_type (void)
+{
+  static GType type = 0;
+
+  if (G_UNLIKELY (type == 0))
+    {
+      static const GTypeInfo info = {
+        sizeof (SalutCapsChannelManagerIface),
+        NULL,   /* base_init */
+        NULL,   /* base_finalize */
+        NULL,   /* class_init */
+        NULL,   /* class_finalize */
+        NULL,   /* class_data */
+        0,
+        0,      /* n_preallocs */
+        NULL    /* instance_init */
+      };
+
+      type = g_type_register_static (G_TYPE_INTERFACE,
+          "SalutCapsChannelManager", &info, 0);
+
+      g_type_interface_add_prerequisite (type, TP_TYPE_CHANNEL_MANAGER);
+    }
+
+  return type;
+}
+
+/* Virtual-method wrappers */
+
+void salut_caps_channel_manager_get_contact_capabilities (
+    SalutCapsChannelManager *caps_manager,
+    SalutConnection *conn,
+    TpHandle handle,
+    GPtrArray *arr)
+{
+  SalutCapsChannelManagerIface *iface =
+    SALUT_CAPS_CHANNEL_MANAGER_GET_INTERFACE (caps_manager);
+  SalutCapsChannelManagerGetContactCapsFunc method = iface->get_contact_caps;
+
+  if (method != NULL)
+    {
+      method (caps_manager, conn, handle, arr);
+    }
+  /* ... else assume there is not caps for this kind of channels */
+}
+
+void salut_caps_channel_manager_get_feature_list (
+    SalutCapsChannelManager *caps_manager,
+    gpointer specific_caps,
+    GSList **features)
+{
+  SalutCapsChannelManagerIface *iface =
+    SALUT_CAPS_CHANNEL_MANAGER_GET_INTERFACE (caps_manager);
+  SalutCapsChannelManagerGetFeatureListFunc method = iface->get_feature_list;
+
+  if (method != NULL)
+    {
+      method (caps_manager, specific_caps, features);
+    }
+  /* ... else nothing to do */
+}
+
+gpointer salut_caps_channel_manager_parse_capabilities (
+    SalutCapsChannelManager *caps_manager,
+    GibberXmppStanza *child)
+{
+  SalutCapsChannelManagerIface *iface =
+    SALUT_CAPS_CHANNEL_MANAGER_GET_INTERFACE (caps_manager);
+  SalutCapsChannelManagerParseCapsFunc method = iface->parse_caps;
+
+  if (method != NULL)
+    {
+      return method (caps_manager, child);
+    }
+  /* ... else assume there is not caps for this kind of channels */
+  return NULL;
+}
+
+void salut_caps_channel_manager_free_capabilities (
+    SalutCapsChannelManager *caps_manager,
+    gpointer specific_caps)
+{
+  SalutCapsChannelManagerIface *iface =
+    SALUT_CAPS_CHANNEL_MANAGER_GET_INTERFACE (caps_manager);
+  SalutCapsChannelManagerFreeCapsFunc method = iface->free_caps;
+
+  if (method != NULL)
+    {
+      method (caps_manager, specific_caps);
+    }
+  /* ... else assume there is no need to free */
+}
+
+void salut_caps_channel_manager_copy_capabilities (
+    SalutCapsChannelManager *caps_manager,
+    gpointer *specific_caps_out,
+    gpointer specific_caps_in)
+{
+  SalutCapsChannelManagerIface *iface =
+    SALUT_CAPS_CHANNEL_MANAGER_GET_INTERFACE (caps_manager);
+  SalutCapsChannelManagerCopyCapsFunc method = iface->copy_caps;
+
+  if (method != NULL)
+    {
+      method (caps_manager, specific_caps_out, specific_caps_in);
+    }
+  else
+    *specific_caps_out = NULL;
+}
+
+void salut_caps_channel_manager_update_capabilities (
+    SalutCapsChannelManager *caps_manager,
+    gpointer specific_caps_out,
+    gpointer specific_caps_in)
+{
+  SalutCapsChannelManagerIface *iface =
+    SALUT_CAPS_CHANNEL_MANAGER_GET_INTERFACE (caps_manager);
+  SalutCapsChannelManagerCopyCapsFunc method = iface->update_caps;
+
+  /* cannot be called if not implemented */
+  g_assert (method != NULL);
+  method (caps_manager, specific_caps_out, specific_caps_in);
+}
+
+gboolean salut_caps_channel_manager_capabilities_diff (
+    SalutCapsChannelManager *caps_manager,
+    TpHandle handle,
+    gpointer specific_old_caps,
+    gpointer specific_new_caps)
+{
+  SalutCapsChannelManagerIface *iface =
+    SALUT_CAPS_CHANNEL_MANAGER_GET_INTERFACE (caps_manager);
+  SalutCapsChannelManagerCapsDiffFunc method = iface->caps_diff;
+
+  if (method != NULL)
+    {
+      return method (caps_manager, handle, specific_old_caps,
+          specific_new_caps);
+    }
+  /* ... else, nothing to do */
+  return FALSE;
+}
+
+void
+salut_caps_channel_manager_add_capability (
+    SalutCapsChannelManager *caps_manager,
+    SalutConnection *conn,
+    TpHandle handle,
+    GHashTable *cap)
+{
+  SalutCapsChannelManagerIface *iface =
+    SALUT_CAPS_CHANNEL_MANAGER_GET_INTERFACE (caps_manager);
+  SalutCapsChannelManagerAddCapFunc method = iface->add_cap;
+
+  if (method != NULL)
+    {
+      method (caps_manager, conn, handle, cap);
+    }
+  /* ... else, nothing to do */
+}
+
diff --git a/src/salut-caps-channel-manager.h b/src/salut-caps-channel-manager.h
new file mode 100644
index 0000000..9c7d3a1
--- /dev/null
+++ b/src/salut-caps-channel-manager.h
@@ -0,0 +1,140 @@
+/*
+ * caps-channel-manager.h - interface holding capabilities functions for
+ * channel managers
+ *
+ * Copyright (C) 2008 Collabora Ltd.
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef SALUT_CAPS_CHANNEL_MANAGER_H
+#define SALUT_CAPS_CHANNEL_MANAGER_H
+
+#include <glib-object.h>
+#include <gibber/gibber-xmpp-stanza.h>
+#include <telepathy-glib/exportable-channel.h>
+#include <telepathy-glib/handle.h>
+
+#include "salut-connection.h"
+
+G_BEGIN_DECLS
+
+#define SALUT_TYPE_CAPS_CHANNEL_MANAGER \
+  (salut_caps_channel_manager_get_type ())
+
+#define SALUT_CAPS_CHANNEL_MANAGER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+  SALUT_TYPE_CAPS_CHANNEL_MANAGER, SalutCapsChannelManager))
+
+#define SALUT_IS_CAPS_CHANNEL_MANAGER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+  SALUT_TYPE_CAPS_CHANNEL_MANAGER))
+
+#define SALUT_CAPS_CHANNEL_MANAGER_GET_INTERFACE(obj) \
+  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), \
+  SALUT_TYPE_CAPS_CHANNEL_MANAGER, SalutCapsChannelManagerIface))
+
+typedef struct _SalutCapsChannelManager SalutCapsChannelManager;
+typedef struct _SalutCapsChannelManagerIface SalutCapsChannelManagerIface;
+
+
+/* virtual methods */
+
+/* May be moved to TpChannelManager later */
+typedef void (*SalutCapsChannelManagerGetContactCapsFunc) (
+    SalutCapsChannelManager *manager, SalutConnection *conn, TpHandle handle,
+    GPtrArray *arr);
+
+typedef void (*SalutCapsChannelManagerAddCapFunc) (
+    SalutCapsChannelManager *manager, SalutConnection *conn, TpHandle handle,
+    GHashTable *cap);
+
+/* Specific to Salut */
+typedef void (*SalutCapsChannelManagerGetFeatureListFunc) (
+    SalutCapsChannelManager *manager, gpointer specific_caps,
+    GSList **features);
+
+typedef gpointer (*SalutCapsChannelManagerParseCapsFunc) (
+    SalutCapsChannelManager *manager, GibberXmppStanza *children);
+
+typedef void (*SalutCapsChannelManagerFreeCapsFunc) (
+    SalutCapsChannelManager *manager, gpointer specific_caps);
+
+typedef void (*SalutCapsChannelManagerCopyCapsFunc) (
+    SalutCapsChannelManager *manager, gpointer *specific_caps_out,
+    gpointer specific_caps_in);
+
+typedef void (*SalutCapsChannelManagerUpdateCapsFunc) (
+    SalutCapsChannelManager *manager, gpointer *specific_caps_out,
+    gpointer specific_caps_in);
+
+typedef gboolean (*SalutCapsChannelManagerCapsDiffFunc) (
+    SalutCapsChannelManager *manager, TpHandle handle,
+    gpointer specific_old_caps, gpointer specific_new_caps);
+
+
+void salut_caps_channel_manager_get_contact_capabilities (
+    SalutCapsChannelManager *manager, SalutConnection *conn, TpHandle handle,
+    GPtrArray *arr);
+
+void salut_caps_channel_manager_get_feature_list (
+    SalutCapsChannelManager *manager, gpointer specific_caps,
+    GSList **features);
+
+gpointer salut_caps_channel_manager_parse_capabilities (
+    SalutCapsChannelManager *manager, GibberXmppStanza *children);
+
+void salut_caps_channel_manager_free_capabilities (SalutCapsChannelManager *manager,
+    gpointer specific_caps);
+
+void salut_caps_channel_manager_copy_capabilities (SalutCapsChannelManager *manager,
+    gpointer *specific_caps_out, gpointer specific_caps_in);
+
+void salut_caps_channel_manager_update_capabilities (
+    SalutCapsChannelManager *manager, gpointer specific_caps_out,
+    gpointer specific_caps_in);
+
+gboolean salut_caps_channel_manager_capabilities_diff (
+    SalutCapsChannelManager *manager, TpHandle handle,
+    gpointer specific_old_caps, gpointer specific_new_caps);
+
+void salut_caps_channel_manager_add_capability (
+    SalutCapsChannelManager *manager, SalutConnection *conn, TpHandle handle,
+    GHashTable *cap);
+
+
+struct _SalutCapsChannelManagerIface {
+    GTypeInterface parent;
+
+    SalutCapsChannelManagerGetContactCapsFunc get_contact_caps;
+    SalutCapsChannelManagerAddCapFunc add_cap;
+
+    SalutCapsChannelManagerGetFeatureListFunc get_feature_list;
+    SalutCapsChannelManagerParseCapsFunc parse_caps;
+    SalutCapsChannelManagerFreeCapsFunc free_caps;
+    SalutCapsChannelManagerCopyCapsFunc copy_caps;
+    SalutCapsChannelManagerUpdateCapsFunc update_caps;
+    SalutCapsChannelManagerCapsDiffFunc caps_diff;
+
+    GCallback _future[8];
+    gpointer priv;
+};
+
+GType salut_caps_channel_manager_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/src/salut-caps-hash.c b/src/salut-caps-hash.c
new file mode 100644
index 0000000..dc463a2
--- /dev/null
+++ b/src/salut-caps-hash.c
@@ -0,0 +1,236 @@
+/*
+ * salut-caps-hash.c - Computing verification string hash (XEP-0115 v1.5)
+ * Copyright (C) 2006-2008 Collabora Ltd.
+ * Copyright (C) 2006-2008 Nokia Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/* Computing verification string hash (XEP-0115 v1.5)
+ *
+ * Salut does not do anything with dataforms (XEP-0128) included in
+ * capabilities.  However, it needs to parse them in order to compute the hash
+ * according to XEP-0115.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#define DEBUG_FLAG SALUT_DEBUG_PRESENCE
+
+#include "base64.h"
+#include "debug.h"
+#include "salut-capabilities.h"
+#include "salut-caps-hash.h"
+#include "salut-self.h"
+#include "sha1/sha1.h"
+
+typedef struct _DataFormField DataFormField;
+
+struct _DataFormField {
+  gchar *field_name;
+  /* array of strings */
+  GPtrArray *values;
+};
+
+typedef struct _DataForm DataForm;
+
+struct _DataForm {
+  gchar *form_type;
+  /* array of DataFormField */
+  GPtrArray *fields;
+};
+
+static void
+sha1_bin (const gchar *bytes,
+          guint len,
+          guchar out[SHA1_HASH_SIZE])
+{
+  SHA1Context sc;
+
+  SHA1Init (&sc);
+  SHA1Update (&sc, bytes, len);
+  SHA1Final (&sc, (uint8_t *) out);
+}
+
+static gint
+char_cmp (gconstpointer a, gconstpointer b)
+{
+  gchar *left = *(gchar **) a;
+  gchar *right = *(gchar **) b;
+
+  return strcmp (left, right);
+}
+
+static gint
+fields_cmp (gconstpointer a, gconstpointer b)
+{
+  DataFormField *left = *(DataFormField **) a;
+  DataFormField *right = *(DataFormField **) b;
+
+  return strcmp (left->field_name, right->field_name);
+}
+
+static gint
+dataforms_cmp (gconstpointer a, gconstpointer b)
+{
+  DataForm *left = *(DataForm **) a;
+  DataForm *right = *(DataForm **) b;
+
+  return strcmp (left->form_type, right->form_type);
+}
+
+static void
+_free_field (gpointer data, gpointer user_data)
+{
+  DataFormField *field = data;
+
+  g_free (field->field_name);
+  g_ptr_array_foreach (field->values, (GFunc) g_free, NULL);
+
+  g_slice_free (DataFormField, field);
+}
+
+static void
+_free_form (gpointer data, gpointer user_data)
+{
+  DataForm *form = data;
+
+  g_free (form->form_type);
+
+  g_ptr_array_foreach (form->fields, _free_field, NULL);
+
+  g_slice_free (DataForm, form);
+}
+
+static void
+salut_presence_free_xep0115_hash (
+    GPtrArray *features,
+    GPtrArray *identities,
+    GPtrArray *dataforms)
+{
+  g_ptr_array_foreach (features, (GFunc) g_free, NULL);
+  g_ptr_array_foreach (identities, (GFunc) g_free, NULL);
+  g_ptr_array_foreach (dataforms, _free_form, NULL);
+
+  g_ptr_array_free (features, TRUE);
+  g_ptr_array_free (identities, TRUE);
+  g_ptr_array_free (dataforms, TRUE);
+}
+
+static gchar *
+caps_hash_compute (
+    GPtrArray *features,
+    GPtrArray *identities,
+    GPtrArray *dataforms)
+{
+  GString *s;
+  gchar sha1[SHA1_HASH_SIZE];
+  guint i;
+  gchar *encoded;
+
+  g_ptr_array_sort (identities, char_cmp);
+  g_ptr_array_sort (features, char_cmp);
+  g_ptr_array_sort (dataforms, dataforms_cmp);
+
+  s = g_string_new ("");
+
+  for (i = 0 ; i < identities->len ; i++)
+    {
+      g_string_append (s, g_ptr_array_index (identities, i));
+      g_string_append_c (s, '<');
+    }
+
+  for (i = 0 ; i < features->len ; i++)
+    {
+      g_string_append (s, g_ptr_array_index (features, i));
+      g_string_append_c (s, '<');
+    }
+
+  for (i = 0 ; i < dataforms->len ; i++)
+    {
+      guint j;
+      DataForm *form = g_ptr_array_index (dataforms, i);
+
+      g_assert (form->form_type != NULL);
+
+      g_string_append (s, form->form_type);
+      g_string_append_c (s, '<');
+
+      g_ptr_array_sort (form->fields, fields_cmp);
+
+      for (j = 0 ; j < form->fields->len ; j++)
+        {
+          guint k;
+          DataFormField *field = g_ptr_array_index (form->fields, j);
+
+          g_string_append (s, field->field_name);
+          g_string_append_c (s, '<');
+
+          g_ptr_array_sort (field->values, char_cmp);
+
+          for (k = 0 ; k < field->values->len ; k++)
+            {
+              g_string_append (s, g_ptr_array_index (field->values, k));
+              g_string_append_c (s, '<');
+            }
+        }
+    }
+
+  sha1_bin (s->str, s->len, (guchar *) sha1);
+  g_string_free (s, TRUE);
+
+  encoded = base64_encode (SHA1_HASH_SIZE, sha1, FALSE);
+
+  return encoded;
+}
+
+/**
+ * Compute our hash as defined by the XEP-0115.
+ *
+ * Returns: the hash. The called must free the returned hash with g_free().
+ */
+gchar *
+caps_hash_compute_from_self_presence (SalutSelf *self)
+{
+  GSList *features_list = capabilities_get_features (
+      self->per_channel_manager_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, g_strdup (feat->ns));
+    }
+
+  /* XEP-0030 requires at least 1 identity. We don't need more. */
+  g_ptr_array_add (identities, g_strdup ("client/pc//" PACKAGE_STRING));
+
+  /* Salut does not use dataforms, let 'dataforms' be empty */
+
+  str = caps_hash_compute (features, identities, dataforms);
+
+  salut_presence_free_xep0115_hash (features, identities, dataforms);
+  g_slist_free (features_list);
+
+  return str;
+}
+
diff --git a/src/salut-caps-hash.h b/src/salut-caps-hash.h
new file mode 100644
index 0000000..290c51e
--- /dev/null
+++ b/src/salut-caps-hash.h
@@ -0,0 +1,29 @@
+/*
+ * salut-caps-hash.h - Headers for computing verification string hash
+ *                     (XEP-0115 v1.5)
+ * Copyright (C) 2008 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#ifndef __SALUT_CAPS_HASH_H__
+#define __SALUT_CAPS_HASH_H__
+
+#include "salut-self.h"
+
+gchar *caps_hash_compute_from_self_presence (SalutSelf *self);
+
+#endif /* __SALUT_CAPS_HASH_H__ */
diff --git a/src/salut-self.h b/src/salut-self.h
index 244827c..7ddb2a5 100644
--- a/src/salut-self.h
+++ b/src/salut-self.h
@@ -75,6 +75,7 @@ struct _SalutSelf {
     TpHandle olpc_cur_act_room;
     gchar *olpc_color;
 #endif
+    GHashTable *per_channel_manager_caps;
     gchar *node;
     gchar *hash;
     gchar *ver;
-- 
1.5.6.5




More information about the telepathy-commits mailing list