[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