soc.2009.telepathy: e32efd08: Break telepathy.c into smaller files. Ab...

sttwister at soc.pidgin.im sttwister at soc.pidgin.im
Tue Jun 16 14:50:32 EDT 2009


-----------------------------------------------------------------
Revision: e32efd08d7d6e23c94ba5ffd8d2577845946b1c3
Ancestor: ec8545dc30d048802c19bc685b6cf6449a24bad9
Author: sttwister at soc.pidgin.im
Date: 2009-06-16T18:48:23
Branch: im.pidgin.soc.2009.telepathy
URL: http://d.pidgin.im/viewmtn/revision/info/e32efd08d7d6e23c94ba5ffd8d2577845946b1c3

Added files:
        libpurple/protocols/telepathy/telepathy_avatar.c
        libpurple/protocols/telepathy/telepathy_avatar.h
        libpurple/protocols/telepathy/telepathy_channel.c
        libpurple/protocols/telepathy/telepathy_channel.h
        libpurple/protocols/telepathy/telepathy_channel_list.c
        libpurple/protocols/telepathy/telepathy_channel_list.h
        libpurple/protocols/telepathy/telepathy_channel_text.c
        libpurple/protocols/telepathy/telepathy_channel_text.h
        libpurple/protocols/telepathy/telepathy_connection.c
        libpurple/protocols/telepathy/telepathy_connection.h
        libpurple/protocols/telepathy/telepathy_contact.c
        libpurple/protocols/telepathy/telepathy_contact.h
Modified files:
        libpurple/protocols/telepathy/Makefile.am
        libpurple/protocols/telepathy/Makefile.mingw
        libpurple/protocols/telepathy/telepathy.c
Modified attrs:
        libpurple/protocols/telepathy/telepathy_avatar.c
        libpurple/protocols/telepathy/telepathy_avatar.h
        libpurple/protocols/telepathy/telepathy_channel.c
        libpurple/protocols/telepathy/telepathy_channel.h
        libpurple/protocols/telepathy/telepathy_channel_list.c
        libpurple/protocols/telepathy/telepathy_channel_list.h
        libpurple/protocols/telepathy/telepathy_channel_text.c
        libpurple/protocols/telepathy/telepathy_channel_text.h
        libpurple/protocols/telepathy/telepathy_connection.c
        libpurple/protocols/telepathy/telepathy_connection.h
        libpurple/protocols/telepathy/telepathy_contact.c
        libpurple/protocols/telepathy/telepathy_contact.h

ChangeLog: 

Break telepathy.c into smaller files. About time...

-------------- next part --------------
============================================================
--- libpurple/protocols/telepathy/telepathy_avatar.c	8079ed553f9a14f3f926fffb1e9e4c086a4016d2
+++ libpurple/protocols/telepathy/telepathy_avatar.c	8079ed553f9a14f3f926fffb1e9e4c086a4016d2
@@ -0,0 +1,296 @@
+/**
+ * purple - Telepathy Protocol Plugin
+ *
+ * Copyright (C) 2009, Felix Kerekes <sttwister at soc.pidgin.im>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#include "telepathy_avatar.h"
+
+#include "debug.h"
+
+#include "telepathy_connection.h"
+#include "telepathy_contact.h"
+
+void
+request_avatars_cb (TpConnection *proxy,
+                    const GError *error,
+                    gpointer user_data,
+                    GObject *weak_object)
+{
+	if (error != NULL)
+	{
+		purple_debug_error("telepathy", "RequestAvatars error: %s\n", error->message);
+	}
+}
+
+void
+get_known_avatar_tokens_cb (TpConnection *proxy,
+                            GHashTable *out_Tokens,
+                            const GError *error,
+                            gpointer user_data,
+                            GObject *weak_object)
+{
+	if (error != NULL)
+	{
+		purple_debug_error("telepathy", "GetAvatarTokens error: %s\n", error->message);
+	}
+	else
+	{
+		GHashTableIter iter;
+		guint key;
+		gpointer value;
+
+		g_hash_table_iter_init(&iter, out_Tokens);
+
+		while (g_hash_table_iter_next(&iter, (gpointer)&key, &value))
+		{
+			purple_debug_info("telepathy", "Known token: %u -> (%s)\n", key, (gchar *)value);	
+		}
+	}
+}
+
+void
+avatar_retrieved_cb (TpConnection *proxy,
+                     guint arg_Contact,
+                     const gchar *arg_Token,
+                     const GArray *arg_Avatar,
+                     const gchar *arg_Type,
+                     gpointer user_data,
+                     GObject *weak_object)
+{
+	telepathy_connection *data = user_data;
+	PurpleBuddyIcon *icon;
+	telepathy_contact *contact_data = g_hash_table_lookup(data->contacts, (gpointer)arg_Contact);
+	TpContact *contact;
+	gpointer avatar;
+
+	if (contact_data == NULL)
+	{
+		purple_debug_warning("telepathy", "Updated avatar for handle %u which has no contact_data struct cached!\n", arg_Contact);
+		return;
+	}
+
+	contact = contact_data->contact;
+
+	if (contact == NULL)
+	{
+		purple_debug_warning("telepathy", "Retrieved avatar for handle %u which has no TpContact proxy cached!\n", arg_Contact);
+		return;
+	}
+
+	purple_debug_info("telepathy", "Got avatar token for %u: (%s - %s)\n", arg_Contact, arg_Token, arg_Type);	
+
+	avatar = g_memdup(arg_Avatar->data, arg_Avatar->len);
+
+	icon = purple_buddy_icon_new(data->acct, tp_contact_get_identifier(contact), avatar, arg_Avatar->len, arg_Token);
+}
+
+void
+avatar_updated_cb (TpConnection *proxy,
+                   guint arg_Contact,
+                   const gchar *arg_New_Avatar_Token,
+                   gpointer user_data,
+                   GObject *weak_object)
+{
+	telepathy_connection *data = user_data;
+	telepathy_contact *contact_data = g_hash_table_lookup(data->contacts, (gpointer)arg_Contact);
+	TpContact *contact;
+	PurpleBuddy *buddy;
+	PurpleBuddyIcon *icon;
+
+	purple_debug_warning("telepathy", "Avatar token updated for %u: (%s)\n", arg_Contact, arg_New_Avatar_Token);	
+
+	if (contact_data == NULL)
+	{
+		purple_debug_warning("telepathy", "Updated avatar for handle %u which has no contact_data struct cached!\n", arg_Contact);
+		return;
+	}
+
+	contact = contact_data->contact;
+
+	if (contact == NULL)
+	{
+		purple_debug_warning("telepathy", "Updated avatar for handle %u which has no TpContact proxy chaced!\n", arg_Contact);
+		return;
+	}
+
+	buddy = purple_find_buddy(data->acct, tp_contact_get_identifier(contact));
+
+	if (buddy == NULL)
+	{
+		purple_debug_warning("telepathy", "AvatarUpdated: There's no buddy named %s\n", tp_contact_get_identifier(contact));
+		return;
+	}
+
+	/* clear the avatar in case of an empty token */
+	if (*arg_New_Avatar_Token == 0)
+	{
+		purple_buddy_icons_set_for_user(data->acct, tp_contact_get_identifier(contact), NULL, 0, "");
+		return;
+	}
+
+
+	icon = purple_buddy_get_icon(buddy);
+
+	if (g_strcmp0(purple_buddy_icon_get_checksum(icon), arg_New_Avatar_Token) != 0)
+	{
+		/* updated the buddy avatar */
+		GArray *avatar_handles;
+
+		purple_debug_info("telepathy", "Avatar for %u (%s) has changed! Calling RequestAvatars\n", arg_Contact, tp_contact_get_identifier(contact));
+
+		avatar_handles = g_array_new(FALSE, FALSE, sizeof(guint));
+
+		g_array_append_val(avatar_handles, arg_Contact);
+
+		tp_cli_connection_interface_avatars_call_request_avatars(data->connection, -1,
+				avatar_handles,
+				request_avatars_cb, data,
+				NULL, NULL);
+
+		g_array_free(avatar_handles, TRUE);
+	}
+}
+
+void
+get_avatar_properties_cb (TpProxy *proxy,
+                          GHashTable *out_Properties,
+                          const GError *error,
+                          gpointer user_data,
+                          GObject *weak_object)
+{
+	if (error != NULL)
+	{
+		purple_debug_error("telepathy", "Error getting avatar properties: %s\n", error->message);
+	}
+	else
+	{
+		telepathy_connection *data = user_data;
+		PurplePlugin *plugin = purple_connection_get_prpl(data->gc);
+		PurplePluginProtocolInfo *prpl_info = plugin->info->extra_info;
+
+
+		GHashTableIter iter;
+		gpointer key, value;
+
+		PurpleBuddyIconSpec icon_spec = NO_BUDDY_ICONS;
+		icon_spec.scale_rules = PURPLE_ICON_SCALE_SEND;
+
+		purple_debug_info("telepathy", "Got avatar properties!\n");
+
+		g_hash_table_iter_init(&iter, out_Properties);
+
+		/* iterate over all properties */
+		while (g_hash_table_iter_next(&iter, &key, &value))
+		{
+			gchar *name = key;
+			GValue *val = value;
+
+			if (g_strcmp0("SupportedAvatarMIMETypes", name) == 0)
+			{
+				/* This parameter is of dbus type "as"
+				 * It's exposed as a GValue holding a (gchar **)
+				 * Or is it now??? wtf!?
+				 */
+
+				gchar *format = NULL;
+
+				int i;
+				gchar **arr = g_value_get_boxed(val);
+
+				for (i = 0; arr[i] != NULL; ++i)
+				{
+					const gchar *mime_type = arr[i];
+
+					int j;
+
+					/* We want to get the part after the / 
+					 * Split the string using / as a delimiter and use the last part
+					 */
+					gchar **split = g_strsplit(mime_type, "/", 0);
+					gchar *old = format;
+
+					/* j will be the last non-NULL token */
+					for (j = 0; split[j] != NULL; ++j);
+					--j;
+
+
+					/* if this is the first type, don't prepend a comma */
+					if (i == 0)
+						format = g_strdup(split[j]);
+					else
+						format = g_strdup_printf("%s,%s", format, split[j]);
+
+					g_free(old);
+					g_strfreev(split);
+				}
+
+				purple_debug_info("telepathy", "    Supported types: %s\n", format);
+
+				icon_spec.format = format;
+			}
+			else if (g_strcmp0("MinimumAvatarWidth", name) == 0)
+			{
+				icon_spec.min_width = g_value_get_uint(val);
+			}
+			else if (g_strcmp0("MinimumAvatarHeight", name) == 0)
+			{
+				icon_spec.min_height = g_value_get_uint(val);
+			}
+			else if (g_strcmp0("MaximumAvatarWidth", name) == 0)
+			{
+				icon_spec.max_width = g_value_get_uint(val);
+			}
+			else if (g_strcmp0("MaximumAvatarHeight", name) == 0)
+			{
+				icon_spec.max_height = g_value_get_uint(val);
+			}
+			else if (g_strcmp0("MaximumAvatarBytes", name) == 0)
+			{
+				icon_spec.max_filesize = g_value_get_uint(val);
+			}
+		}
+
+		prpl_info->icon_spec = icon_spec;
+	}
+}
+
+void
+set_avatar_cb (TpConnection *proxy,
+               const gchar *out_Token,
+               const GError *error,
+               gpointer user_data,
+               GObject *weak_object)
+{
+	if (error != NULL)
+	{
+		purple_debug_error("telepathy", "SetAvatar error: %s\n", error->message);
+	}
+}
+
+void
+clear_avatar_cb (TpConnection *proxy,
+                 const GError *error,
+                 gpointer user_data,
+                 GObject *weak_object)
+{
+	if (error != NULL)
+	{
+		purple_debug_error("telepathy", "ClearAvatar error: %s\n", error->message);
+	}
+}
+
============================================================
--- libpurple/protocols/telepathy/telepathy_avatar.h	048d468f7657812529d266cf20f8afccc7e80364
+++ libpurple/protocols/telepathy/telepathy_avatar.h	048d468f7657812529d266cf20f8afccc7e80364
@@ -0,0 +1,76 @@
+/**
+ * purple - Telepathy Protocol Plugin
+ *
+ * Copyright (C); 2009, Felix Kerekes <sttwister at soc.pidgin.im>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option); any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#ifndef _TELEPATHY_AVATAR_H_
+#define _TELEPATHY_AVATAR_H_
+
+#include <telepathy-glib/connection.h>
+
+void
+request_avatars_cb (TpConnection *proxy,
+                    const GError *error,
+                    gpointer user_data,
+                    GObject *weak_object);
+
+void
+get_known_avatar_tokens_cb (TpConnection *proxy,
+                            GHashTable *out_Tokens,
+                            const GError *error,
+                            gpointer user_data,
+                            GObject *weak_object);
+
+void
+avatar_retrieved_cb (TpConnection *proxy,
+                     guint arg_Contact,
+                     const gchar *arg_Token,
+                     const GArray *arg_Avatar,
+                     const gchar *arg_Type,
+                     gpointer user_data,
+                     GObject *weak_object);
+
+void
+avatar_updated_cb (TpConnection *proxy,
+                   guint arg_Contact,
+                   const gchar *arg_New_Avatar_Token,
+                   gpointer user_data,
+                   GObject *weak_object);
+
+void
+get_avatar_properties_cb (TpProxy *proxy,
+                          GHashTable *out_Properties,
+                          const GError *error,
+                          gpointer user_data,
+                          GObject *weak_object);
+
+void
+set_avatar_cb (TpConnection *proxy,
+               const gchar *out_Token,
+               const GError *error,
+               gpointer user_data,
+               GObject *weak_object);
+
+void
+clear_avatar_cb (TpConnection *proxy,
+                 const GError *error,
+                 gpointer user_data,
+                 GObject *weak_object);
+
+
+#endif /* _TELEPATHY_AVATAR_H_ */
============================================================
--- libpurple/protocols/telepathy/telepathy_channel.c	bfd65c2c37f142efbd42435199415da13ba532a0
+++ libpurple/protocols/telepathy/telepathy_channel.c	bfd65c2c37f142efbd42435199415da13ba532a0
@@ -0,0 +1,162 @@
+/**
+ * purple - Telepathy Protocol Plugin
+ *
+ * Copyright (C) 2009, Felix Kerekes <sttwister at soc.pidgin.im>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#include "telepathy_channel.h"
+
+#include <telepathy-glib/interfaces.h>
+
+#include "internal.h"
+
+#include "debug.h"
+
+#include "telepathy_avatar.h"
+#include "telepathy_channel_list.h"
+#include "telepathy_channel_text.h"
+#include "telepathy_contact.h"
+
+void
+channel_ready_cb (TpChannel *channel,
+                  const GError *error,
+                  gpointer user_data)
+{
+	if (error != NULL)
+	{
+		purple_debug_error("telepathy", "Channel ready error: %s\n", error->message);
+	}
+	else
+	{
+		GQuark handle_Type;
+
+		handle_Type = tp_channel_get_channel_type_id(channel);
+
+		if (handle_Type == TP_IFACE_QUARK_CHANNEL_TYPE_CONTACT_LIST)
+		{
+			handle_list_channel(channel, user_data);
+		}
+		else if (handle_Type == TP_IFACE_QUARK_CHANNEL_TYPE_TEXT)
+		{
+			handle_text_channel(channel, user_data);
+		}
+	}
+}
+
+void
+channel_invalidated_cb (TpProxy *self,
+                        guint    domain,
+                        gint     code,
+                        gchar   *message,
+                        gpointer user_data)
+{
+	purple_debug_info("telepathy", "Channel invalidated: %s\n", message);	
+
+	g_object_unref(self);
+}
+
+void
+handle_new_channel (telepathy_connection *data,
+                    const GValueArray *channel_Properties)
+{
+	char *object_Path = g_value_get_boxed(g_value_array_get_nth((GValueArray *)channel_Properties, 0));
+	GHashTable *map = g_value_get_boxed(g_value_array_get_nth((GValueArray *)channel_Properties, 1));
+
+	GError *error = NULL;
+	TpConnection *connection = data->connection;
+	TpChannel *channel = tp_channel_new_from_properties(connection, object_Path, map, &error);
+
+	if (error != NULL)
+	{
+		purple_debug_error("telepathy", "Error while creating TpChannel: %s\n", error->message);
+		g_error_free(error);
+		return;
+	}
+	
+	purple_debug_info("telepathy", "New channel: %s\n", object_Path);
+
+	tp_channel_call_when_ready(channel, channel_ready_cb, data);
+
+	g_signal_connect(channel, "invalidated", G_CALLBACK (channel_invalidated_cb), data);
+}
+
+void
+new_channels_cb (TpConnection *proxy,
+                 const GPtrArray *arg_Channels,
+                 gpointer user_data,
+                 GObject *weak_object)
+{
+	int i;
+	telepathy_connection *data = user_data;
+
+	if (data->listing_channels)
+		return;
+
+	purple_debug_info("telepathy", "NewChannels:\n");
+
+	for (i = 0; i < arg_Channels->len; i++)
+	{
+		GValueArray *channel = g_ptr_array_index(arg_Channels, i);
+
+		handle_new_channel(user_data, channel);
+	}
+}
+
+void
+ensure_channel_cb (TpConnection *proxy,
+                   gboolean out_Yours,
+                   const gchar *out_Channel,
+                   GHashTable *out_Properties,
+                   const GError *error,
+                   gpointer user_data,
+                   GObject *weak_object)
+{
+	if (error != NULL)
+	{
+		purple_debug_error("telepathy", "EnsureChannel error: %s\n", error->message);
+	}
+}
+
+void
+get_channels_cb (TpProxy *proxy,
+                 const GValue *out_Value,
+                 const GError *error,
+                 gpointer user_data,
+                 GObject *weak_object)
+{
+	if (error != NULL)
+	{
+		purple_debug_error("telepathy", "Get Channels error: %s\n", error->message);
+	}
+	else
+	{
+		telepathy_connection *data = user_data;
+
+		/* unpack the a(oa{sv}) struct */
+		const GPtrArray *channels = g_value_get_boxed(out_Value);
+		int i;
+
+		data->listing_channels = FALSE;
+
+		for (i = 0; i < channels->len; i++)
+		{
+			const GValueArray *channel = g_ptr_array_index(channels, i);
+			handle_new_channel(user_data, channel);
+		}
+
+	}
+}
============================================================
--- libpurple/protocols/telepathy/telepathy_channel.h	826f04d11dd59ace93e28ce1c4d7b495230938cd
+++ libpurple/protocols/telepathy/telepathy_channel.h	826f04d11dd59ace93e28ce1c4d7b495230938cd
@@ -0,0 +1,68 @@
+/**
+ * purple - Telepathy Protocol Plugin
+ *
+ * Copyright (C) 2009, Felix Kerekes <sttwister at soc.pidgin.im>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#ifndef _TELEPATHY_CHANNEL_H_
+#define _TELEPATHY_CHANNEL_H_
+
+#include <glib.h>
+
+#include <telepathy-glib/channel.h>
+
+#include "telepathy_connection.h"
+
+void
+channel_ready_cb (TpChannel *channel,
+                  const GError *error,
+                  gpointer user_data);
+
+void
+channel_invalidated_cb (TpProxy *self,
+                        guint    domain,
+                        gint     code,
+                        gchar   *message,
+                        gpointer user_data);
+
+void
+handle_new_channel (telepathy_connection *data,
+                    const GValueArray *channel_Properties);
+
+void
+new_channels_cb (TpConnection *proxy,
+                 const GPtrArray *arg_Channels,
+                 gpointer user_data,
+                 GObject *weak_object);
+
+void
+ensure_channel_cb (TpConnection *proxy,
+                   gboolean out_Yours,
+                   const gchar *out_Channel,
+                   GHashTable *out_Properties,
+                   const GError *error,
+                   gpointer user_data,
+                   GObject *weak_object);
+
+void
+get_channels_cb (TpProxy *proxy,
+                 const GValue *out_Value,
+                 const GError *error,
+                 gpointer user_data,
+                 GObject *weak_object);
+
+#endif /* _TELEPATHY_CHANNEL_H_ */
============================================================
--- libpurple/protocols/telepathy/telepathy_channel_list.c	dea5894e4316434a1a8f6553717e8dea3d76757f
+++ libpurple/protocols/telepathy/telepathy_channel_list.c	dea5894e4316434a1a8f6553717e8dea3d76757f
@@ -0,0 +1,97 @@
+/**
+ * purple - Telepathy Protocol Plugin
+ *
+ * Copyright (C) 2009, Felix Kerekes <sttwister at soc.pidgin.im>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#include "telepathy_channel_list.h"
+
+#include "debug.h"
+
+#include "telepathy_avatar.h"
+#include "telepathy_contact.h"
+
+void
+handle_list_channel (TpChannel *channel,
+                     telepathy_connection *data)
+{
+	TpConnection *connection = data->connection;
+	const TpIntSet *members;
+	TpIntSetIter iter;
+	GArray *handles;
+
+	const TpContactFeature features[] = {
+		TP_CONTACT_FEATURE_ALIAS,
+		TP_CONTACT_FEATURE_PRESENCE
+	};
+
+	guint handle;
+	guint handle_type;
+
+	handle = tp_channel_get_handle(channel, &handle_type);
+
+	members = tp_channel_group_get_members(channel);
+
+	if (members == NULL)
+	{
+		purple_debug_error("telepathy", "Error while getting member list\n");
+		return;
+	}
+
+	iter.set = members;
+	iter.element = (guint)(-1);
+
+	handles = tp_intset_to_array (members);
+
+	/* we want to create a TpContact for each member of this channel */
+	if (handles->len)
+	{
+		/* this struct is needed to pass both the connection data and the channel proxy */
+		telepathy_group *group = g_new0(telepathy_group, 1);
+
+		group->channel = channel;
+		group->connection_data = data;
+
+		if (handle_type == TP_HANDLE_TYPE_GROUP)
+		{
+			/* this is a user-defined group */
+			tp_connection_get_contacts_by_handle (connection,
+					handles->len, (const TpHandle *) handles->data,
+					G_N_ELEMENTS (features), features,
+					group_contacts_ready_cb,
+					group, NULL, NULL);
+		}
+		else
+		{
+			tp_connection_get_contacts_by_handle (connection,
+					handles->len, (const TpHandle *) handles->data,
+					G_N_ELEMENTS (features), features,
+					contacts_ready_cb,
+					group, NULL, NULL);
+		}
+
+	}
+
+	tp_cli_connection_interface_avatars_call_get_known_avatar_tokens(data->connection, -1,
+			handles,
+			get_known_avatar_tokens_cb, data,
+			NULL, NULL);
+
+	g_array_free (handles, TRUE);
+
+}
+
============================================================
--- libpurple/protocols/telepathy/telepathy_channel_list.h	889f520fc1896209dc1f214ed12dacc588876258
+++ libpurple/protocols/telepathy/telepathy_channel_list.h	889f520fc1896209dc1f214ed12dacc588876258
@@ -0,0 +1,40 @@
+/**
+ * purple - Telepathy Protocol Plugin
+ *
+ * Copyright (C) 2009, Felix Kerekes <sttwister at soc.pidgin.im>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#ifndef _TELEPATHY_CHANNEL_LIST_H_
+#define _TELEPATHY_CHANNEL_LIST_H_
+
+#include <telepathy-glib/channel.h>
+
+#include "telepathy_connection.h"
+
+typedef struct
+{
+	telepathy_connection *connection_data;
+	TpChannel *channel;
+
+} telepathy_group;
+
+
+void
+handle_list_channel (TpChannel *channel,
+                     telepathy_connection *data);
+
+#endif /* _TELEPATHY_CHANNEL_LIST_H_ */
============================================================
--- libpurple/protocols/telepathy/telepathy_channel_text.c	32d4445150ef43b626735b3073040d42677bf89b
+++ libpurple/protocols/telepathy/telepathy_channel_text.c	32d4445150ef43b626735b3073040d42677bf89b
@@ -0,0 +1,442 @@
+/**
+ * purple - Telepathy Protocol Plugin
+ *
+ * Copyright (C) 2009, Felix Kerekes <sttwister at soc.pidgin.im>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#include "telepathy_channel_text.h"
+
+#include <telepathy-glib/interfaces.h>
+
+#include "internal.h"
+
+#include "debug.h"
+
+#include "telepathy_connection.h"
+#include "telepathy_contact.h"
+
+void
+destroy_text_channel(telepathy_text_channel *tp_channel)
+{
+	g_free(tp_channel);
+}
+
+void
+write_message_to_conversation (const gchar *from,
+                               guint timestamp,
+			       const gchar *msg,
+			       gpointer user_data)
+{
+	telepathy_connection *data = user_data;
+
+	/* if a conversation was not yet establish, create a new one */
+	PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, data->acct);
+	PurpleConvIm *im;
+
+	/* escape HTML special characters */
+	gchar *escaped_message = g_markup_escape_text(msg, -1);
+
+	/* also change \n to <br> */
+	gchar *final_message = purple_strdup_withhtml(escaped_message);
+	g_free(escaped_message);
+
+	if (conv == NULL)
+	{
+	    conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, data->acct, from);
+	}
+	im = purple_conversation_get_im_data(conv);
+
+	purple_debug_info("telepathy", "Contact %s says \"%s\" (escaped: \"%s\")\n", from, msg, final_message);
+
+	/* transmit the message to the UI */
+	purple_conv_im_write(im, from, final_message, 0, timestamp);
+
+	g_free(final_message);
+}
+
+void
+acknowledge_pending_messages_cb (TpChannel *proxy,
+                                 const GError *error,
+				 gpointer user_data,
+				 GObject *weak_object)
+{
+	if (error != NULL)
+	{
+		purple_debug_error("telepathy", "AcknowledgePendingMessages error: %s\n", error->message);
+	}
+}
+
+void
+list_pending_messages_cb  (TpChannel *proxy,
+                           const GPtrArray *out_Pending_Messages,
+                           const GError *error,
+                           gpointer user_data,
+                           GObject *weak_object)
+{
+	if (error != NULL)
+	{
+		purple_debug_error("telepathy", "ListPendingMessages error: %s\n", error->message);
+	}
+	else
+	{
+		telepathy_connection *data = user_data;
+		GArray *message_IDs;
+
+		int i;
+
+		GHashTable *properties = tp_channel_borrow_immutable_properties(proxy);
+		gchar *who = (gchar *)tp_asv_get_string(properties, TP_IFACE_CHANNEL ".TargetID");
+
+		telepathy_text_channel *tp_channel = g_hash_table_lookup(data->text_Channels, who);
+
+		if (tp_channel == NULL)
+		{
+			purple_debug_warning("telepathy", "Received message from %s, but there's no channel struct for the buddy!\n", who);
+		}
+		else
+		{
+			/* we should now allow received_cb to handle incoming messages */
+			tp_channel->received_Pending_Messages = TRUE;
+		}
+
+		/* this will hold the IDs of message that will be acknowledged */
+		message_IDs = g_array_new(FALSE, FALSE, sizeof(guint));
+
+		for (i = 0; i<out_Pending_Messages->len; ++i)
+		{
+			/* unpack the relevant info from (uuuuus) */
+			GValueArray *arr = g_ptr_array_index(out_Pending_Messages, i);
+			guint msg_id = g_value_get_uint(g_value_array_get_nth(arr, 0));
+			guint timestamp = g_value_get_uint(g_value_array_get_nth(arr, 1));
+			guint flags = g_value_get_uint(g_value_array_get_nth(arr, 4));
+			gchar *msg = (gchar *)g_value_get_string(g_value_array_get_nth(arr, 5));
+			
+			/* get the identifier from channel instead of contact since contact might not be ready for offline messages */
+			gchar *from = (gchar *)tp_channel_get_identifier(proxy);
+
+			/* drop message if it's not text */
+			if ((flags & TP_CHANNEL_TEXT_MESSAGE_FLAG_NON_TEXT_CONTENT) == 0)
+				write_message_to_conversation(from, timestamp, msg, user_data);
+
+			/* add the id to the array of acknowledge messages */
+			g_array_append_val(message_IDs, msg_id);
+		}
+
+		/* acknowledge the messages now */
+		tp_cli_channel_type_text_call_acknowledge_pending_messages(proxy, -1, message_IDs,
+				acknowledge_pending_messages_cb, user_data, NULL, NULL);
+
+		g_array_free(message_IDs, TRUE);
+
+	}
+}
+
+void
+received_cb (TpChannel *proxy,
+             guint arg_ID,
+             guint arg_Timestamp,
+             guint arg_Sender,
+             guint arg_Type,
+             guint arg_Flags,
+             const gchar *arg_Text,
+             gpointer user_data,
+             GObject *weak_object)
+{
+	telepathy_connection *data = user_data;
+
+	GHashTable *properties = tp_channel_borrow_immutable_properties(proxy);
+	gchar *who = (gchar *)tp_asv_get_string(properties, TP_IFACE_CHANNEL ".TargetID");
+
+	telepathy_text_channel *tp_channel = g_hash_table_lookup(data->text_Channels, who);
+
+	if (tp_channel == NULL)
+	{
+		purple_debug_warning("telepathy", "Received message from %s, but there's no channel struct for the buddy!\n", who);
+	}
+	else
+	{
+		GArray *message_IDs;
+
+		/* will this message get caught by ListPendingMessages? */
+		if (!tp_channel->received_Pending_Messages)
+			return;
+
+		/* drop this message if it's not text */
+		if ((arg_Flags & TP_CHANNEL_TEXT_MESSAGE_FLAG_NON_TEXT_CONTENT) == 0)
+			write_message_to_conversation(who, arg_Timestamp, arg_Text, user_data);
+
+		/* acknowledge receiving the message */
+		message_IDs = g_array_new(FALSE, FALSE, sizeof(guint));
+
+		g_array_append_val(message_IDs, arg_ID);
+
+		tp_cli_channel_type_text_call_acknowledge_pending_messages(proxy, -1, message_IDs,
+				acknowledge_pending_messages_cb, user_data, NULL, NULL);
+
+		g_array_free(message_IDs, TRUE);
+
+	}
+}
+
+void
+send_error_cb (TpChannel *proxy,
+               guint arg_Error,
+               guint arg_Timestamp,
+               guint arg_Type,
+               const gchar *arg_Text,
+               gpointer user_data,
+               GObject *weak_object)
+{
+	telepathy_connection *data = user_data;
+
+	const gchar *who = tp_channel_get_identifier(proxy);
+
+	const gchar *error_reason = NULL;
+	gchar *error_message;
+	gchar *error_message2;
+
+	switch (arg_Error)
+	{
+		case TP_CHANNEL_TEXT_SEND_ERROR_UNKNOWN:
+			error_reason = _("Unknown error");
+		break;
+
+		case TP_CHANNEL_TEXT_SEND_ERROR_OFFLINE:
+			error_reason = _("Contact is offline");
+		break;
+
+		case TP_CHANNEL_TEXT_SEND_ERROR_INVALID_CONTACT:
+			error_reason = _("Contact is invalid");
+		break;
+
+		case TP_CHANNEL_TEXT_SEND_ERROR_PERMISSION_DENIED:
+			error_reason = _("Permission denied");
+		break;
+
+		case TP_CHANNEL_TEXT_SEND_ERROR_TOO_LONG:
+			error_reason = _("The message is too long");
+		break;
+
+		case TP_CHANNEL_TEXT_SEND_ERROR_NOT_IMPLEMENTED:
+			error_reason = _("Not implemented");
+		break;
+	}
+
+	error_message = g_strdup_printf(_("There was an error sending your message to %s"), who);
+	error_message2 = g_strdup_printf("%s: %s", error_message, error_reason);
+
+	/* display the error in the conversation */
+	if (!purple_conv_present_error(who, data->acct, error_message2))
+	{
+		/* display as a popup if there is no active conversation with the user */
+		purple_notify_error(purple_connections_get_handle(),
+				_("Error sending message"),
+				error_message,
+				error_reason);
+	}
+
+	g_free(error_message2);
+	g_free(error_message);
+
+	purple_debug_error("telepathy", "SendError: %s\n", error_reason);
+}
+
+void
+send_cb (TpChannel *proxy,
+         const GError *error,
+         gpointer user_data,
+         GObject *weak_object)
+{
+	if (error != NULL)
+	{
+		telepathy_connection *data = user_data;
+
+		const gchar *who = tp_channel_get_identifier(proxy);
+
+		gchar *error_message = g_strdup_printf(_("There was an error sending your message to %s"), who);
+		gchar *error_message2 = g_strdup_printf("%s: %s", error_message, error->message);
+
+		/* display the error in the conversation */
+		if (!purple_conv_present_error(who, data->acct, error_message2))
+		{
+			/* display as a popup if there is no active conversation with the user */
+			purple_notify_error(purple_connections_get_handle(),
+					_("Error sending message"),
+					error_message,
+					error->message);
+		}
+
+		g_free(error_message2);
+		g_free(error_message);
+			
+		purple_debug_error("telepathy", "Send error: %s\n", error->message);
+	}
+}
+
+void
+text_channel_invalidated_cb (TpProxy *self,
+                             guint    domain,
+                             gint     code,
+                             gchar   *message,
+                             gpointer user_data)
+{
+	telepathy_connection *data = user_data;
+
+	/* remove the cached TpChannel proxy when the channel closes */
+	const gchar *who = tp_channel_get_identifier((TpChannel *)self);
+
+	telepathy_text_channel *tp_channel = NULL;
+	
+	if (data->text_Channels)
+		tp_channel = g_hash_table_lookup(data->text_Channels, who);
+
+	purple_debug_info("telepathy", "Text channel with %s closed!\n", who);
+
+	if (tp_channel)
+	{
+		tp_channel->channel = NULL;
+	}
+}
+
+void
+chat_state_changed_cb (TpChannel *proxy,
+                       guint arg_Contact,
+                       guint arg_State,
+                       gpointer user_data,
+                       GObject *weak_object)
+{
+	telepathy_connection *data = user_data;
+
+	telepathy_contact *contact_data = g_hash_table_lookup(data->contacts, (gpointer)arg_Contact);
+
+	PurpleTypingState state;
+	const gchar *name;
+
+	if (contact_data == NULL)
+	{
+		purple_debug_warning("telepathy", "Chat state changed for %u who isn't cached!\n", arg_Contact);
+		return;
+	}
+
+	name = tp_contact_get_identifier(contact_data->contact);
+
+	purple_debug_info("telepathy", "Chat state changed for %s\n", name);
+
+	switch (arg_State)
+	{
+		case TP_CHANNEL_CHAT_STATE_PAUSED:
+			state = PURPLE_TYPED;
+		break;
+
+		case TP_CHANNEL_CHAT_STATE_COMPOSING:
+			state = PURPLE_TYPING;
+		break;
+
+		default:
+			state = PURPLE_NOT_TYPING;
+		break;
+	}
+
+	if (state == PURPLE_NOT_TYPING)
+	{
+		serv_got_typing_stopped(data->gc, name);
+	}
+	else
+	{
+		serv_got_typing(data->gc, name, -1, state);
+	}
+}
+
+void
+handle_text_channel (TpChannel *channel,
+                     telepathy_connection *data)
+{
+	GError *error = NULL;
+
+	GHashTable *properties = tp_channel_borrow_immutable_properties(channel);
+	gchar *who = (gchar *)tp_asv_get_string(properties, TP_IFACE_CHANNEL ".TargetID");
+
+	telepathy_text_channel *tp_channel;
+
+	purple_debug_info("telepathy", "Saving TpChannel proxy for %s\n", who);
+
+	tp_channel = g_hash_table_lookup(data->text_Channels, who);
+
+	/* if tp_channel exists, then we requested this channel, else it's an incoming request so we must cache it */
+	if (tp_channel == NULL)
+	{
+		tp_channel = g_new0(telepathy_text_channel, 1);
+		g_hash_table_insert(data->text_Channels, who, tp_channel);
+	}
+
+	tp_channel->channel = channel;
+
+	tp_cli_channel_interface_chat_state_connect_to_chat_state_changed(channel, chat_state_changed_cb, data, NULL, NULL, &error);
+
+	if (error != NULL)
+	{
+		purple_debug_error("telepathy", "Error connecting to ChatStateChanged signal: %s\n", error->message);
+	}
+
+	tp_cli_channel_type_text_connect_to_received(channel, received_cb, data, NULL, NULL, &error);
+
+	if (error != NULL)
+	{
+		purple_debug_error("telepathy", "Error connecting to Received signal: %s\n", error->message);
+	}
+
+	tp_channel->received_Pending_Messages = FALSE;
+
+	g_signal_connect(channel, "invalidated", G_CALLBACK(text_channel_invalidated_cb), data);
+
+	/* the Clear parameter is deprecated, we need to use AcknowledgePendingMessages */
+	tp_cli_channel_type_text_call_list_pending_messages(channel, -1, FALSE, list_pending_messages_cb, data, NULL, NULL);
+
+	/* send pending messages */
+	while (tp_channel->pending_Messages != NULL)
+	{
+		purple_debug_info("telepathy", "Sending pending message \"%s\" to %s\n", (gchar *)tp_channel->pending_Messages->data, who);
+
+		tp_cli_channel_type_text_call_send(channel, -1, TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, tp_channel->pending_Messages->data, send_cb, data, NULL, NULL);
+
+		/* the message was duped */
+		g_free(tp_channel->pending_Messages->data);
+
+		tp_channel->pending_Messages = g_list_delete_link(tp_channel->pending_Messages, tp_channel->pending_Messages);
+	}
+
+	tp_cli_channel_type_text_connect_to_send_error(channel, send_error_cb, data, NULL, NULL, &error);
+
+	if (error != NULL)
+	{
+		purple_debug_error("telepathy", "Error connecting to SendError signal: %s\n", error->message);
+		g_error_free(error);
+	}
+}
+
+void
+set_chat_state_cb (TpChannel *proxy,
+                   const GError *error,
+                   gpointer user_data,
+                   GObject *weak_object)
+{
+	if (error != NULL)
+	{
+		purple_debug_error("telepathy", "SetChatState error: %s\n", error->message);
+	}
+}
+
============================================================
--- libpurple/protocols/telepathy/telepathy_channel_text.h	5f8653276d3406e59f03892e33ab0ede95f16daf
+++ libpurple/protocols/telepathy/telepathy_channel_text.h	5f8653276d3406e59f03892e33ab0ede95f16daf
@@ -0,0 +1,111 @@
+/**
+ * purple - Telepathy Protocol Plugin
+ *
+ * Copyright (C) 2009, Felix Kerekes <sttwister at soc.pidgin.im>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#ifndef _TELEPATHY_CHANNEL_TEXT_H_
+#define _TELEPATHY_CHANNEL_TEXT_H_
+
+#include <glib.h>
+
+#include <telepathy-glib/channel.h>
+
+#include "telepathy_connection.h"
+
+typedef struct
+{
+	GList *pending_Messages;
+	TpChannel *channel;
+
+	/* This flag avoids having a message processed twice via both Received signal and ListPendingMessages */
+	gboolean received_Pending_Messages;
+} telepathy_text_channel;
+
+void
+destroy_text_channel(telepathy_text_channel *tp_channel);
+
+void
+write_message_to_conversation (const gchar *from,
+                               guint timestamp,
+			       const gchar *msg,
+			       gpointer user_data);
+
+void
+acknowledge_pending_messages_cb (TpChannel *proxy,
+                                 const GError *error,
+				 gpointer user_data,
+				 GObject *weak_object);
+
+void
+list_pending_messages_cb  (TpChannel *proxy,
+                           const GPtrArray *out_Pending_Messages,
+                           const GError *error,
+                           gpointer user_data,
+                           GObject *weak_object);
+
+void
+received_cb (TpChannel *proxy,
+             guint arg_ID,
+             guint arg_Timestamp,
+             guint arg_Sender,
+             guint arg_Type,
+             guint arg_Flags,
+             const gchar *arg_Text,
+             gpointer user_data,
+             GObject *weak_object);
+
+void
+send_error_cb (TpChannel *proxy,
+               guint arg_Error,
+               guint arg_Timestamp,
+               guint arg_Type,
+               const gchar *arg_Text,
+               gpointer user_data,
+               GObject *weak_object);
+
+void
+send_cb (TpChannel *proxy,
+         const GError *error,
+         gpointer user_data,
+         GObject *weak_object);
+
+void
+text_channel_invalidated_cb (TpProxy *self,
+                             guint    domain,
+                             gint     code,
+                             gchar   *message,
+                             gpointer user_data);
+
+void
+chat_state_changed_cb (TpChannel *proxy,
+                       guint arg_Contact,
+                       guint arg_State,
+                       gpointer user_data,
+                       GObject *weak_object);
+
+void
+handle_text_channel (TpChannel *channel,
+                     telepathy_connection *data);
+
+void
+set_chat_state_cb (TpChannel *proxy,
+                   const GError *error,
+                   gpointer user_data,
+                   GObject *weak_object);
+
+#endif /* _TELEPATHY_CHANNEL_TEXT_H_ */
============================================================
--- libpurple/protocols/telepathy/telepathy_connection.c	f3c079f3499d8926582ed5dac3d782932756d700
+++ libpurple/protocols/telepathy/telepathy_connection.c	f3c079f3499d8926582ed5dac3d782932756d700
@@ -0,0 +1,333 @@
+/**
+ * purple - Telepathy Protocol Plugin
+ *
+ * Copyright (C) 2009, Felix Kerekes <sttwister at soc.pidgin.im>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#include "telepathy_connection.h"
+
+#include <telepathy-glib/interfaces.h>
+
+#include "internal.h"
+
+#include "connection.h"
+#include "debug.h"
+
+#include "telepathy_avatar.h"
+#include "telepathy_channel.h"
+#include "telepathy_channel_text.h"
+#include "telepathy_contact.h"
+
+void
+status_changed_cb (TpConnection *proxy,
+                   guint arg_Status,
+                   guint arg_Reason,
+                   gpointer user_data,
+                   GObject *weak_object)
+{
+	telepathy_connection *data = user_data;
+
+	if (arg_Status == TP_CONNECTION_STATUS_CONNECTED)
+	{
+		purple_debug_info("telepathy", "Connected!\n");
+
+		purple_connection_update_progress(data->gc, _("Connected"),
+				1,   /* which connection step this is */
+				2);  /* total number of steps */
+
+		purple_connection_set_state(data->gc, PURPLE_CONNECTED);
+
+		data->text_Channels = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) destroy_text_channel);
+		data->contacts = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) destroy_contact);
+	}
+	else if (arg_Status == TP_CONNECTION_STATUS_DISCONNECTED)
+	{
+		gchar *reason = NULL;
+		PurpleConnectionError error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
+		purple_debug_info("telepathy", "Disconnected! Reason: %d\n", arg_Reason);
+
+		switch (arg_Reason)
+		{
+			case TP_CONNECTION_STATUS_REASON_NETWORK_ERROR:
+				reason = "Network error";
+				error = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
+			break;
+
+			case TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED:
+				reason = "Authentication failed";
+				error = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
+			break;
+
+			case TP_CONNECTION_STATUS_REASON_ENCRYPTION_ERROR:
+				reason = "Encryption error";
+				error = PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR;
+			break;
+
+			case TP_CONNECTION_STATUS_REASON_NAME_IN_USE:
+				reason = "Name in use";
+				error = PURPLE_CONNECTION_ERROR_NAME_IN_USE;
+			break;
+
+			case TP_CONNECTION_STATUS_REASON_CERT_NOT_PROVIDED:
+				reason = "SSL Certificate not provided";
+				error = PURPLE_CONNECTION_ERROR_CERT_NOT_PROVIDED;
+			break;
+
+			case TP_CONNECTION_STATUS_REASON_CERT_UNTRUSTED:
+				reason = "SSL Certificate is isnged by an untrusted certifying authority";
+				error = PURPLE_CONNECTION_ERROR_CERT_UNTRUSTED;
+			break;
+
+			case TP_CONNECTION_STATUS_REASON_CERT_EXPIRED:
+				reason = "SSL Certificate expired";
+				error = PURPLE_CONNECTION_ERROR_CERT_EXPIRED;
+			break;
+
+			case TP_CONNECTION_STATUS_REASON_CERT_NOT_ACTIVATED:
+				reason = "SSL Certificate is not yet valid";
+				error = PURPLE_CONNECTION_ERROR_CERT_NOT_ACTIVATED;
+			break;
+
+			case TP_CONNECTION_STATUS_REASON_CERT_HOSTNAME_MISMATCH:
+				reason = "SSL Certificate hostname mismatch";
+				error = PURPLE_CONNECTION_ERROR_CERT_HOSTNAME_MISMATCH;
+			break;
+
+			case TP_CONNECTION_STATUS_REASON_CERT_FINGERPRINT_MISMATCH:
+				reason = "SSL Certificate fingerprint mismatch";
+				error = PURPLE_CONNECTION_ERROR_CERT_FINGERPRINT_MISMATCH;
+			break;
+
+			case TP_CONNECTION_STATUS_REASON_CERT_SELF_SIGNED:
+				reason = "SSL Certificate is self-signed";
+				error = PURPLE_CONNECTION_ERROR_CERT_SELF_SIGNED;
+			break;
+
+			case TP_CONNECTION_STATUS_REASON_CERT_OTHER_ERROR:
+				reason = "Error while validating the server's SSL Certificate";
+				error = PURPLE_CONNECTION_ERROR_CERT_OTHER_ERROR;
+			break;
+		}
+
+		if (data)
+		{
+			purple_connection_set_protocol_data(data->gc, NULL);
+
+			if (reason != NULL && data->gc)
+				purple_connection_error_reason(data->gc, error, reason);
+
+			if (data->connection != NULL)
+			{
+				g_object_unref(data->connection);
+				data->connection = NULL;
+			}
+
+			if (data->text_Channels != NULL)
+			{
+				g_hash_table_destroy(data->text_Channels);
+				data->text_Channels = NULL;
+			}
+			if (data->contacts != NULL)
+			{
+				g_hash_table_destroy(data->contacts);
+				data->contacts = NULL;
+			}
+
+			g_free(data);
+		}
+
+	}
+	else if (arg_Status == TP_CONNECTION_STATUS_CONNECTING)
+	{
+		purple_debug_info("telepathy", "Connecting! Reason: %d\n", arg_Reason);
+		purple_connection_set_state(data->gc, PURPLE_CONNECTING);
+		purple_connection_update_progress(data->gc, _("Connecting"),
+				0,   /* which connection step this is */
+				2);  /* total number of steps */
+
+	}
+}
+
+void
+set_presence_cb (TpConnection *proxy,
+                 const GError *error,
+                 gpointer user_data,
+                 GObject *weak_object)
+{
+	if (error != NULL)
+	{
+		purple_debug_error("telepathy", "SetStatus error: %s\n", error->message);
+	}
+}
+
+void
+connection_connect_cb (TpConnection *proxy,
+                       const GError *error,
+                       gpointer user_data,
+                       GObject *weak_object)
+{
+	/* if this fails, something must be broken somewhere */
+	if (error != NULL)
+	{
+		purple_debug_error("telepathy", "Connect error: %s\n", error->message);
+	}
+}
+
+void
+request_connection_cb (TpConnectionManager *proxy,
+                       const gchar *out_Bus_Name,
+                       const gchar *out_Object_Path,
+                       const GError *error,
+                       gpointer user_data,
+                       GObject *weak_object)
+{
+	PurpleConnection *gc = user_data;
+
+	if (error != NULL)
+	{
+		purple_debug_info("telepathy", "RequestConnection error: %s\n", error->message);
+
+		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, error->message);
+	}
+	else
+	{
+		GError *error = NULL;
+		telepathy_connection *connection_data;
+
+		TpDBusDaemon *daemon = tp_dbus_daemon_dup(&error);
+		
+		if (error != NULL)
+		{
+			purple_debug_error("telepathy", "Error creating dbus daemon: %s\n", error->message);
+			g_error_free(error);
+			return;
+		}
+
+		connection_data = g_new0(telepathy_connection, 1);
+
+		/* get the connection proxy straight out of the dbus interface */
+		connection_data->connection = tp_connection_new(daemon, out_Bus_Name, out_Object_Path, &error);
+		connection_data->gc = gc;
+		connection_data->acct = purple_connection_get_account(gc);
+		purple_connection_set_protocol_data(gc, connection_data);
+
+		if (error != NULL)
+		{
+			purple_debug_error("telepathy", "Error creating TpConnection object: %s\n", error->message);
+			g_error_free(error);
+
+			g_object_unref(connection_data->connection);
+			connection_data->connection = NULL;
+			g_free(connection_data);
+			return;
+		}
+
+		tp_connection_call_when_ready(connection_data->connection, connection_ready_cb, connection_data);
+
+		/* this will indicate any connection status change, also providing a reason */
+		tp_cli_connection_connect_to_status_changed(connection_data->connection, status_changed_cb, connection_data, NULL, NULL, &error);
+
+		if (error != NULL)
+		{
+			purple_debug_error("telepathy", "Error conencting to StatusChanged: %s\n", error->message);
+			g_error_free(error);
+
+			tp_cli_connection_call_disconnect(connection_data->connection, -1, NULL, NULL, NULL, NULL);
+			g_object_unref(connection_data->connection);
+			connection_data->connection = NULL;
+			g_free(connection_data);
+		}
+		else
+		{
+			/* do some magic now :) */
+			tp_cli_connection_call_connect(connection_data->connection, -1, connection_connect_cb, connection_data, NULL, NULL);
+		}
+
+		if (daemon != NULL)
+			g_object_unref(daemon);
+	}
+}
+
+void
+connection_ready_cb (TpConnection *connection,
+                     const GError *error,
+                     gpointer user_data)
+{
+	if (error != NULL)
+	{
+		purple_debug_info("telepathy", "Connection ready error: %s\n", error->message);
+	}
+	else
+	{
+		char **interfaces, **ptr;
+		GError *error = NULL;
+		telepathy_connection *data = user_data;
+
+		purple_debug_info("telepathy", "Connection is ready. Interfaces implemented:\n");
+
+		/* query interfaces */
+		g_object_get(connection, "interfaces", &interfaces, NULL);
+		for (ptr = interfaces; ptr && *ptr; ptr++)
+		{
+			purple_debug_info("telepathy", "  %s\n", *ptr);
+		}
+		g_strfreev(interfaces);
+
+		tp_cli_connection_interface_requests_connect_to_new_channels(connection, new_channels_cb, user_data, NULL, NULL, &error);
+
+		if (error != NULL)
+		{
+			purple_debug_error("telepathy", "Error while connecting to NewChannels signal: %s\n", error->message);
+			g_error_free(error);
+			error = NULL;
+			return;
+		}
+
+		data->listing_channels = TRUE;
+			
+		/* query the Channels property of the Requests interface */
+		tp_cli_dbus_properties_call_get(connection, -1, TP_IFACE_CONNECTION_INTERFACE_REQUESTS, "Channels", get_channels_cb, user_data, NULL, NULL);
+
+
+		/* query supported avatar formats */
+		tp_cli_dbus_properties_call_get_all(connection, -1, TP_IFACE_CONNECTION_INTERFACE_AVATARS, get_avatar_properties_cb, user_data, NULL, NULL);
+
+		/* this will be fired when an avatar for a buddy has been received */
+		tp_cli_connection_interface_avatars_connect_to_avatar_retrieved(connection,
+				avatar_retrieved_cb, data,
+				NULL, NULL,
+				&error);
+		
+		if (error != NULL)
+		{
+			purple_debug_error("telepathy", "Error connecting to AvatarRetrieved signal: %s\n", error->message);
+			g_error_free(error);
+		}
+
+		tp_cli_connection_interface_avatars_connect_to_avatar_updated(connection,
+				avatar_updated_cb, data,
+				NULL, NULL,
+				&error);
+
+		if (error != NULL)
+		{
+			purple_debug_error("telepathy", "Error connecting to AvatarUpdated signal: %s\n", error->message);
+			g_error_free(error);
+		}
+
+	}
+}
============================================================
--- libpurple/protocols/telepathy/telepathy_connection.h	5d102e163e859228142e40a25054c14af7a10ab1
+++ libpurple/protocols/telepathy/telepathy_connection.h	5d102e163e859228142e40a25054c14af7a10ab1
@@ -0,0 +1,82 @@
+/**
+ * purple - Telepathy Protocol Plugin
+ *
+ * Copyright (C) 2009, Felix Kerekes <sttwister at soc.pidgin.im>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#ifndef _TELEPATHY_CONNECTION_H_
+#define _TELEPATHY_CONNECTION_H_
+
+#include <glib.h>
+
+#include <telepathy-glib/channel.h>
+#include <telepathy-glib/connection-manager.h>
+#include <telepathy-glib/connection.h>
+#include <telepathy-glib/contact.h>
+
+#include "connection.h"
+
+typedef struct
+{
+	TpConnection *connection;
+	PurpleConnection *gc;
+	PurpleAccount *acct;
+
+	/* This flag avoids having a channel processed twice via both NewChannels and quering the Channels property */
+	gboolean listing_channels;
+
+	/* This will hold pointers to telepathy_text_channel for buddies that have an active conversation */
+	GHashTable *text_Channels;
+	
+	/* This will map contact handles to telepathy_contact */
+	GHashTable *contacts;
+	
+} telepathy_connection;
+
+void
+status_changed_cb (TpConnection *proxy,
+                   guint arg_Status,
+		   guint arg_Reason,
+		   gpointer user_data,
+		   GObject *weak_object);
+
+void
+set_presence_cb (TpConnection *proxy,
+                 const GError *error,
+                 gpointer user_data,
+                 GObject *weak_object);
+
+void
+connection_connect_cb (TpConnection *proxy,
+                       const GError *error,
+                       gpointer user_data,
+                       GObject *weak_object);
+
+void
+request_connection_cb (TpConnectionManager *proxy,
+                       const gchar *out_Bus_Name,
+                       const gchar *out_Object_Path,
+                       const GError *error,
+                       gpointer user_data,
+                       GObject *weak_object);
+
+void
+connection_ready_cb (TpConnection *connection,
+                     const GError *error,
+                     gpointer user_data);
+
+#endif /* _TELEPATHY_CONNECTION_H_ */
============================================================
--- libpurple/protocols/telepathy/telepathy_contact.c	05502690e0f19e4758b11c66149d8dee0aa83303
+++ libpurple/protocols/telepathy/telepathy_contact.c	05502690e0f19e4758b11c66149d8dee0aa83303
@@ -0,0 +1,215 @@
+/**
+ * purple - Telepathy Protocol Plugin
+ *
+ * Copyright (C) 2009, Felix Kerekes <sttwister at soc.pidgin.im>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#include "telepathy_contact.h"
+
+#include "debug.h"
+
+#include "telepathy_avatar.h"
+#include "telepathy_channel_list.h"
+
+void
+destroy_contact(telepathy_contact *contact_data)
+{
+	g_object_unref(contact_data->contact);
+	g_free(contact_data);
+}
+
+void
+contact_notify_cb (TpContact *contact,
+		   GParamSpec *pspec,
+		   gpointer user_data)
+{
+	telepathy_connection *data = user_data;
+
+	const gchar *name = tp_contact_get_identifier(contact);
+	const gchar *presence_status = tp_contact_get_presence_status(contact);
+	const gchar *presence_message = tp_contact_get_presence_message(contact);
+	const gchar *alias = tp_contact_get_alias(contact);
+
+	PurpleBuddy *buddy = purple_find_buddy(data->acct, tp_contact_get_identifier(contact));
+
+	if (buddy == NULL)
+	{
+		purple_debug_warning("telepathy", "Received TpContact notify for non-existent buddy (%s)!\n", name);
+		return;
+	}
+
+	purple_blist_alias_buddy(buddy, alias);
+
+	purple_prpl_got_user_status(data->acct, name, presence_status,
+			"message", presence_message, NULL);
+}
+
+void
+handle_contacts (telepathy_connection *connection_data,
+                 guint n_contacts,
+		 TpContact * const *contacts,
+		 guint n_failed,
+		 PurpleGroup *group)
+{
+	int i;
+	GArray *avatar_handles = g_array_new(FALSE, FALSE, sizeof(guint));
+
+	purple_debug_info("telepathy", "Contacts ready: %u (%u failed)\n", n_contacts, n_failed);
+
+	for (i = 0; i<n_contacts; ++i)
+	{
+		TpContact *contact = contacts[i];
+		PurpleBuddy *buddy;
+		guint handle;
+		telepathy_contact *contact_data;
+
+		/* the buddy might already be stored locally */
+		buddy = purple_find_buddy(connection_data->acct, tp_contact_get_identifier(contact));
+
+		if (buddy == NULL)
+		{
+			/* Buddy was not stored locally */
+			buddy = purple_buddy_new(connection_data->acct, tp_contact_get_identifier(contact), tp_contact_get_alias(contact));
+			purple_blist_add_buddy(buddy, NULL, group, NULL);
+		}
+		else
+		{
+			PurpleGroup *buddy_group = purple_buddy_get_group(buddy);
+			PurplePresence *presence = purple_buddy_get_presence(buddy);
+
+			/* is this buddy in the right group */
+			if (group != NULL && buddy_group != group)
+			{
+				purple_debug_info("telepathy", "Contact %s is not in the right group, moving him to %s\n",
+						tp_contact_get_identifier(contact), purple_group_get_name(group));
+
+				/* we should move the buddy to the right group */
+				purple_blist_remove_buddy(buddy);
+
+				buddy = purple_buddy_new(connection_data->acct, tp_contact_get_identifier(contact), tp_contact_get_alias(contact));
+				purple_blist_add_buddy(buddy, NULL, group, NULL);
+			}
+
+
+			/* we should check if it has statuses for the presence,
+			* since the prpl was not yet loaded when status_types was being called
+			*/
+			if (presence != NULL)
+			{
+				if (purple_presence_get_statuses(presence) == NULL)
+				{
+					purple_presence_add_list(presence, purple_prpl_get_statuses(connection_data->acct, presence));
+				}
+			}
+		}
+
+		/* save the contact data to be later accessible by using only the handle */
+		handle = tp_contact_get_handle(contact);
+
+		contact_data = g_hash_table_lookup(connection_data->contacts, (gpointer)handle);
+
+		if (contact_data == NULL)
+		{
+			contact_data = g_new0(telepathy_contact, 1);
+			contact_data-> contact = contact;
+
+			g_hash_table_insert(connection_data->contacts, (gpointer)handle, contact_data);
+
+			/* the notify signal will fire for any changed parameter of the contact (status, presence, avatar, alias etc.) */
+			g_object_ref(contact);
+			g_signal_connect(contact, "notify", G_CALLBACK (contact_notify_cb), connection_data);
+			contact_notify_cb (contact, NULL, connection_data);
+		}
+
+		if (!contact_data->requested_avatar)
+		{
+			g_array_append_val(avatar_handles, handle);
+			contact_data->requested_avatar = TRUE;
+		}
+	}
+
+	tp_cli_connection_interface_avatars_call_request_avatars(connection_data->connection, -1,
+			avatar_handles,
+			request_avatars_cb, connection_data,
+			NULL, NULL);
+
+	g_array_free(avatar_handles, TRUE);
+}
+
+/* this the ContactsReady callback for group channels */
+void
+group_contacts_ready_cb (TpConnection *connection,
+                         guint n_contacts,
+                         TpContact * const *contacts,
+                         guint n_failed,
+                         const TpHandle *failed,
+                         const GError *error,
+                         gpointer user_data,
+                         GObject *weak_object)
+{
+	telepathy_group *data = user_data;
+
+	if (error != NULL)
+	{
+		purple_debug_error("telepathy", "Contacts ready error: %s\n", error->message);
+	}
+	else
+	{
+		PurpleGroup *group;
+
+		const gchar *group_name = tp_channel_get_identifier(data->channel);
+		group = purple_find_group(group_name);
+
+		if (group == NULL)
+		{
+			group = purple_group_new(group_name);
+			purple_blist_add_group(group, NULL);
+		}
+
+		handle_contacts(data->connection_data, n_contacts, contacts, n_failed, group);
+	}
+
+	/* this isn't used anywhere else except this callback */
+	g_free(data);
+}
+
+/* this the ContactsReady callback for list channels */
+void
+contacts_ready_cb (TpConnection *connection,
+                   guint n_contacts,
+                   TpContact * const *contacts,
+                   guint n_failed,
+                   const TpHandle *failed,
+                   const GError *error,
+                   gpointer user_data,
+                   GObject *weak_object)
+{
+	telepathy_group *data = user_data;
+
+	if (error != NULL)
+	{
+		purple_debug_error("telepathy", "Contacts ready error: %s\n", error->message);
+	}
+	else
+	{
+		handle_contacts(data->connection_data, n_contacts, contacts, n_failed, NULL);
+	}
+
+	/* this isn't used anywhere else except this callback */
+	g_free(data);
+}
+
============================================================
--- libpurple/protocols/telepathy/telepathy_contact.h	95d4b16d635c033886107217341da3e29c397329
+++ libpurple/protocols/telepathy/telepathy_contact.h	95d4b16d635c033886107217341da3e29c397329
@@ -0,0 +1,72 @@
+/**
+ * purple - Telepathy Protocol Plugin
+ *
+ * Copyright (C); 2009, Felix Kerekes <sttwister at soc.pidgin.im>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option); any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#ifndef _TELEPATHY_CONTACT_H_
+#define _TELEPATHY_CONTACT_H_
+
+#include <telepathy-glib/contact.h>
+
+#include "telepathy_connection.h"
+
+typedef struct
+{
+	TpContact *contact;
+
+	gboolean requested_avatar;
+} telepathy_contact;
+
+void
+destroy_contact(telepathy_contact *contact_data);
+
+void
+contact_notify_cb (TpContact *contact,
+		   GParamSpec *pspec,
+		   gpointer user_data);
+
+void
+handle_contacts (telepathy_connection *connection_data,
+                 guint n_contacts,
+		 TpContact * const *contacts,
+		 guint n_failed,
+		 PurpleGroup *group);
+
+/* this the ContactsReady callback for group channels */
+void
+group_contacts_ready_cb (TpConnection *connection,
+                         guint n_contacts,
+                         TpContact * const *contacts,
+                         guint n_failed,
+                         const TpHandle *failed,
+                         const GError *error,
+                         gpointer user_data,
+                         GObject *weak_object);
+
+/* this the ContactsReady callback for list channels */
+void
+contacts_ready_cb (TpConnection *connection,
+                   guint n_contacts,
+                   TpContact * const *contacts,
+                   guint n_failed,
+                   const TpHandle *failed,
+                   const GError *error,
+                   gpointer user_data,
+                   GObject *weak_object);
+
+#endif /* _TELEPATHY_CONTACT_H_ */
============================================================
--- libpurple/protocols/telepathy/Makefile.am	9084a1a81d3abd8c1c34d13271e194bc8dda3d83
+++ libpurple/protocols/telepathy/Makefile.am	edcf56f9ef554e4a09fc722f263fc08735e970bb
@@ -3,7 +3,14 @@ pkgdir = $(libdir)/purple-$(PURPLE_MAJOR
 
 pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
 
-TELEPATHYSOURCES = telepathy.c
+TELEPATHYSOURCES = \
+	telepathy.c \
+	telepathy_avatar.c \
+	telepathy_channel.c \
+	telepathy_channel_list.c \
+	telepathy_channel_text.c \
+	telepathy_connection.c \
+	telepathy_contact.c
 
 AM_CFLAGS = $(st)
 
============================================================
--- libpurple/protocols/telepathy/Makefile.mingw	b110ba9c3c0d85bf0d12445f5dc0606926905b5b
+++ libpurple/protocols/telepathy/Makefile.mingw	1380667637d60efc3f54357b12c07a4a36a5b402
@@ -37,7 +37,13 @@ LIB_PATHS +=		-L$(GTK_TOP)/lib \
 ##
 ##  SOURCES, OBJECTS
 ##
-C_SRC =			telepathy.c
+C_SRC =			telepathy.c \
+			telepathy_avatar.c \
+			telepathy_channel.c \
+			telepathy_channel_list.c \
+			telepathy_channel_text.c \
+			telepathy_connection.c \
+			telepathy_contact.c
 
 OBJECTS = $(C_SRC:%.c=%.o)
 
============================================================
--- libpurple/protocols/telepathy/telepathy.c	badfa5c36462e3257efb74e98eabbf56f4d205de
+++ libpurple/protocols/telepathy/telepathy.c	2fd9b36e01f333c263d79b7fa9bce00efe276617
@@ -38,6 +38,12 @@
 #include "util.h"
 #include "version.h"
 
+#include "telepathy_avatar.h"
+#include "telepathy_channel.h"
+#include "telepathy_channel_text.h"
+#include "telepathy_connection.h"
+#include "telepathy_contact.h"
+
 #define TELEPATHY_ID "prpl-telepathy"
 #define TELEPATHY_DISPLAY_VERSION "1.0"
 
@@ -54,60 +60,6 @@ typedef struct
 
 typedef struct
 {
-	TpConnection *connection;
-	PurpleConnection *gc;
-	PurpleAccount *acct;
-
-	/* This flag avoids having a channel processed twice via both NewChannels and quering the Channels property */
-	gboolean listing_channels;
-
-	/* This will hold pointers to telepathy_text_channel for buddies that have an active conversation */
-	GHashTable *text_Channels;
-	
-	/* This will map contact handles to telepathy_contact */
-	GHashTable *contacts;
-	
-} telepathy_connection;
-
-typedef struct
-{
-	GList *pending_Messages;
-	TpChannel *channel;
-
-	/* This flag avoids having a message processed twice via both Received signal and ListPendingMessages */
-	gboolean received_Pending_Messages;
-} telepathy_text_channel;
-
-static void
-destroy_text_channel(telepathy_text_channel *tp_channel)
-{
-	g_free(tp_channel);
-}
-
-typedef struct
-{
-	TpContact *contact;
-
-	gboolean requested_avatar;
-} telepathy_contact;
-
-
-static void
-destroy_contact(telepathy_contact *contact_data)
-{
-	g_object_unref(contact_data->contact);
-	g_free(contact_data);
-}
-
-typedef struct
-{
-	telepathy_connection *connection_data;
-	TpChannel *channel;
-
-} telepathy_group;
-
-typedef struct
-{
 	const gchar *telepathy_name;
 	const gchar *dbus_type;
 	const gchar *human_name;
@@ -274,1297 +226,6 @@ static void
 }
 
 static void
-contact_notify_cb (TpContact *contact,
-		   GParamSpec *pspec,
-		   gpointer user_data)
-{
-	telepathy_connection *data = user_data;
-
-	const gchar *name = tp_contact_get_identifier(contact);
-	const gchar *presence_status = tp_contact_get_presence_status(contact);
-	const gchar *presence_message = tp_contact_get_presence_message(contact);
-	const gchar *alias = tp_contact_get_alias(contact);
-
-	PurpleBuddy *buddy = purple_find_buddy(data->acct, tp_contact_get_identifier(contact));
-
-	if (buddy == NULL)
-	{
-		purple_debug_warning("telepathy", "Received TpContact notify for non-existent buddy (%s)!\n", name);
-		return;
-	}
-
-	purple_blist_alias_buddy(buddy, alias);
-
-	purple_prpl_got_user_status(data->acct, name, presence_status,
-			"message", presence_message, NULL);
-}
-
-static void
-request_avatars_cb (TpConnection *proxy,
-                    const GError *error,
-                    gpointer user_data,
-                    GObject *weak_object)
-{
-	if (error != NULL)
-	{
-		purple_debug_error("telepathy", "RequestAvatars error: %s\n", error->message);
-	}
-}
-
-static void
-handle_contacts (telepathy_connection *connection_data,
-                 guint n_contacts,
-		 TpContact * const *contacts,
-		 guint n_failed,
-		 PurpleGroup *group)
-{
-	int i;
-	GArray *avatar_handles = g_array_new(FALSE, FALSE, sizeof(guint));
-
-	purple_debug_info("telepathy", "Contacts ready: %u (%u failed)\n", n_contacts, n_failed);
-
-	for (i = 0; i<n_contacts; ++i)
-	{
-		TpContact *contact = contacts[i];
-		PurpleBuddy *buddy;
-		guint handle;
-		telepathy_contact *contact_data;
-
-		/* the buddy might already be stored locally */
-		buddy = purple_find_buddy(connection_data->acct, tp_contact_get_identifier(contact));
-
-		if (buddy == NULL)
-		{
-			/* Buddy was not stored locally */
-			buddy = purple_buddy_new(connection_data->acct, tp_contact_get_identifier(contact), tp_contact_get_alias(contact));
-			purple_blist_add_buddy(buddy, NULL, group, NULL);
-		}
-		else
-		{
-			PurpleGroup *buddy_group = purple_buddy_get_group(buddy);
-			PurplePresence *presence = purple_buddy_get_presence(buddy);
-
-			/* is this buddy in the right group */
-			if (group != NULL && buddy_group != group)
-			{
-				purple_debug_info("telepathy", "Contact %s is not in the right group, moving him to %s\n",
-						tp_contact_get_identifier(contact), purple_group_get_name(group));
-
-				/* we should move the buddy to the right group */
-				purple_blist_remove_buddy(buddy);
-
-				buddy = purple_buddy_new(connection_data->acct, tp_contact_get_identifier(contact), tp_contact_get_alias(contact));
-				purple_blist_add_buddy(buddy, NULL, group, NULL);
-			}
-
-
-			/* we should check if it has statuses for the presence,
-			* since the prpl was not yet loaded when status_types was being called
-			*/
-			if (presence != NULL)
-			{
-				if (purple_presence_get_statuses(presence) == NULL)
-				{
-					purple_presence_add_list(presence, purple_prpl_get_statuses(connection_data->acct, presence));
-				}
-			}
-		}
-
-		/* save the contact data to be later accessible by using only the handle */
-		handle = tp_contact_get_handle(contact);
-
-		contact_data = g_hash_table_lookup(connection_data->contacts, (gpointer)handle);
-
-		if (contact_data == NULL)
-		{
-			contact_data = g_new0(telepathy_contact, 1);
-			contact_data-> contact = contact;
-
-			g_hash_table_insert(connection_data->contacts, (gpointer)handle, contact_data);
-
-			/* the notify signal will fire for any changed parameter of the contact (status, presence, avatar, alias etc.) */
-			g_object_ref(contact);
-			g_signal_connect(contact, "notify", G_CALLBACK (contact_notify_cb), connection_data);
-			contact_notify_cb (contact, NULL, connection_data);
-		}
-
-		if (!contact_data->requested_avatar)
-		{
-			g_array_append_val(avatar_handles, handle);
-			contact_data->requested_avatar = TRUE;
-		}
-	}
-
-	tp_cli_connection_interface_avatars_call_request_avatars(connection_data->connection, -1,
-			avatar_handles,
-			request_avatars_cb, connection_data,
-			NULL, NULL);
-
-	g_array_free(avatar_handles, TRUE);
-}
-
-/* this the ContactsReady callback for group channels */
-static void
-group_contacts_ready_cb (TpConnection *connection,
-                         guint n_contacts,
-                         TpContact * const *contacts,
-                         guint n_failed,
-                         const TpHandle *failed,
-                         const GError *error,
-                         gpointer user_data,
-                         GObject *weak_object)
-{
-	telepathy_group *data = user_data;
-
-	if (error != NULL)
-	{
-		purple_debug_error("telepathy", "Contacts ready error: %s\n", error->message);
-	}
-	else
-	{
-		PurpleGroup *group;
-
-		const gchar *group_name = tp_channel_get_identifier(data->channel);
-		group = purple_find_group(group_name);
-
-		if (group == NULL)
-		{
-			group = purple_group_new(group_name);
-			purple_blist_add_group(group, NULL);
-		}
-
-		handle_contacts(data->connection_data, n_contacts, contacts, n_failed, group);
-	}
-
-	/* this isn't used anywhere else except this callback */
-	g_free(data);
-}
-
-/* this the ContactsReady callback for list channels */
-static void
-contacts_ready_cb (TpConnection *connection,
-                   guint n_contacts,
-                   TpContact * const *contacts,
-                   guint n_failed,
-                   const TpHandle *failed,
-                   const GError *error,
-                   gpointer user_data,
-                   GObject *weak_object)
-{
-	telepathy_group *data = user_data;
-
-	if (error != NULL)
-	{
-		purple_debug_error("telepathy", "Contacts ready error: %s\n", error->message);
-	}
-	else
-	{
-		handle_contacts(data->connection_data, n_contacts, contacts, n_failed, NULL);
-	}
-
-	/* this isn't used anywhere else except this callback */
-	g_free(data);
-}
-
-static void
-get_known_avatar_tokens_cb (TpConnection *proxy,
-                            GHashTable *out_Tokens,
-                            const GError *error,
-                            gpointer user_data,
-                            GObject *weak_object)
-{
-	if (error != NULL)
-	{
-		purple_debug_error("telepathy", "GetAvatarTokens error: %s\n", error->message);
-	}
-	else
-	{
-		GHashTableIter iter;
-		guint key;
-		gpointer value;
-
-		g_hash_table_iter_init(&iter, out_Tokens);
-
-		while (g_hash_table_iter_next(&iter, (gpointer)&key, &value))
-		{
-			purple_debug_info("telepathy", "Known token: %u -> (%s)\n", key, (gchar *)value);	
-		}
-	}
-}
-
-static void
-avatar_retrieved_cb (TpConnection *proxy,
-                     guint arg_Contact,
-                     const gchar *arg_Token,
-                     const GArray *arg_Avatar,
-                     const gchar *arg_Type,
-                     gpointer user_data,
-                     GObject *weak_object)
-{
-	telepathy_connection *data = user_data;
-	PurpleBuddyIcon *icon;
-	telepathy_contact *contact_data = g_hash_table_lookup(data->contacts, (gpointer)arg_Contact);
-	TpContact *contact;
-	gpointer avatar;
-
-	if (contact_data == NULL)
-	{
-		purple_debug_warning("telepathy", "Updated avatar for handle %u which has no contact_data struct cached!\n", arg_Contact);
-		return;
-	}
-
-	contact = contact_data->contact;
-
-	if (contact == NULL)
-	{
-		purple_debug_warning("telepathy", "Retrieved avatar for handle %u which has no TpContact proxy cached!\n", arg_Contact);
-		return;
-	}
-
-	purple_debug_info("telepathy", "Got avatar token for %u: (%s - %s)\n", arg_Contact, arg_Token, arg_Type);	
-
-	avatar = g_memdup(arg_Avatar->data, arg_Avatar->len);
-
-	icon = purple_buddy_icon_new(data->acct, tp_contact_get_identifier(contact), avatar, arg_Avatar->len, arg_Token);
-}
-
-static void
-avatar_updated_cb (TpConnection *proxy,
-                   guint arg_Contact,
-                   const gchar *arg_New_Avatar_Token,
-                   gpointer user_data,
-                   GObject *weak_object)
-{
-	telepathy_connection *data = user_data;
-	telepathy_contact *contact_data = g_hash_table_lookup(data->contacts, (gpointer)arg_Contact);
-	TpContact *contact;
-	PurpleBuddy *buddy;
-	PurpleBuddyIcon *icon;
-
-	purple_debug_warning("telepathy", "Avatar token updated for %u: (%s)\n", arg_Contact, arg_New_Avatar_Token);	
-
-	if (contact_data == NULL)
-	{
-		purple_debug_warning("telepathy", "Updated avatar for handle %u which has no contact_data struct cached!\n", arg_Contact);
-		return;
-	}
-
-	contact = contact_data->contact;
-
-	if (contact == NULL)
-	{
-		purple_debug_warning("telepathy", "Updated avatar for handle %u which has no TpContact proxy chaced!\n", arg_Contact);
-		return;
-	}
-
-	buddy = purple_find_buddy(data->acct, tp_contact_get_identifier(contact));
-
-	if (buddy == NULL)
-	{
-		purple_debug_warning("telepathy", "AvatarUpdated: There's no buddy named %s\n", tp_contact_get_identifier(contact));
-		return;
-	}
-
-	/* clear the avatar in case of an empty token */
-	if (*arg_New_Avatar_Token == 0)
-	{
-		purple_buddy_icons_set_for_user(data->acct, tp_contact_get_identifier(contact), NULL, 0, "");
-		return;
-	}
-
-
-	icon = purple_buddy_get_icon(buddy);
-
-	if (g_strcmp0(purple_buddy_icon_get_checksum(icon), arg_New_Avatar_Token) != 0)
-	{
-		/* updated the buddy avatar */
-		GArray *avatar_handles;
-
-		purple_debug_info("telepathy", "Avatar for %u (%s) has changed! Calling RequestAvatars\n", arg_Contact, tp_contact_get_identifier(contact));
-
-		avatar_handles = g_array_new(FALSE, FALSE, sizeof(guint));
-
-		g_array_append_val(avatar_handles, arg_Contact);
-
-		tp_cli_connection_interface_avatars_call_request_avatars(data->connection, -1,
-				avatar_handles,
-				request_avatars_cb, data,
-				NULL, NULL);
-
-		g_array_free(avatar_handles, TRUE);
-	}
-}
-
-static void
-handle_list_channel (TpChannel *channel,
-                     telepathy_connection *data)
-{
-	TpConnection *connection = data->connection;
-	const TpIntSet *members;
-	TpIntSetIter iter;
-	GArray *handles;
-
-	static const TpContactFeature features[] = {
-		TP_CONTACT_FEATURE_ALIAS,
-		TP_CONTACT_FEATURE_PRESENCE
-	};
-
-	guint handle;
-	guint handle_type;
-
-	handle = tp_channel_get_handle(channel, &handle_type);
-
-	members = tp_channel_group_get_members(channel);
-
-	if (members == NULL)
-	{
-		purple_debug_error("telepathy", "Error while getting member list\n");
-		return;
-	}
-
-	iter.set = members;
-	iter.element = (guint)(-1);
-
-	handles = tp_intset_to_array (members);
-
-	/* we want to create a TpContact for each member of this channel */
-	if (handles->len)
-	{
-		/* this struct is needed to pass both the connection data and the channel proxy */
-		telepathy_group *group = g_new0(telepathy_group, 1);
-
-		group->channel = channel;
-		group->connection_data = data;
-
-		if (handle_type == TP_HANDLE_TYPE_GROUP)
-		{
-			/* this is a user-defined group */
-			tp_connection_get_contacts_by_handle (connection,
-					handles->len, (const TpHandle *) handles->data,
-					G_N_ELEMENTS (features), features,
-					group_contacts_ready_cb,
-					group, NULL, NULL);
-		}
-		else
-		{
-			tp_connection_get_contacts_by_handle (connection,
-					handles->len, (const TpHandle *) handles->data,
-					G_N_ELEMENTS (features), features,
-					contacts_ready_cb,
-					group, NULL, NULL);
-		}
-
-	}
-
-	tp_cli_connection_interface_avatars_call_get_known_avatar_tokens(data->connection, -1,
-			handles,
-			get_known_avatar_tokens_cb, data,
-			NULL, NULL);
-
-	g_array_free (handles, TRUE);
-
-}
-
-static void
-write_message_to_conversation (const gchar *from,
-                               guint timestamp,
-			       const gchar *msg,
-			       gpointer user_data)
-{
-	telepathy_connection *data = user_data;
-
-	/* if a conversation was not yet establish, create a new one */
-	PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, data->acct);
-	PurpleConvIm *im;
-
-	/* escape HTML special characters */
-	gchar *escaped_message = g_markup_escape_text(msg, -1);
-
-	/* also change \n to <br> */
-	gchar *final_message = purple_strdup_withhtml(escaped_message);
-	g_free(escaped_message);
-
-	if (conv == NULL)
-	{
-	    conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, data->acct, from);
-	}
-	im = purple_conversation_get_im_data(conv);
-
-	purple_debug_info("telepathy", "Contact %s says \"%s\" (escaped: \"%s\")\n", from, msg, final_message);
-
-	/* transmit the message to the UI */
-	purple_conv_im_write(im, from, final_message, 0, timestamp);
-
-	g_free(final_message);
-}
-
-static void
-acknowledge_pending_messages_cb (TpChannel *proxy,
-                                 const GError *error,
-				 gpointer user_data,
-				 GObject *weak_object)
-{
-	if (error != NULL)
-	{
-		purple_debug_error("telepathy", "AcknowledgePendingMessages error: %s\n", error->message);
-	}
-}
-
-static void
-list_pending_messages_cb  (TpChannel *proxy,
-                           const GPtrArray *out_Pending_Messages,
-                           const GError *error,
-                           gpointer user_data,
-                           GObject *weak_object)
-{
-	if (error != NULL)
-	{
-		purple_debug_error("telepathy", "ListPendingMessages error: %s\n", error->message);
-	}
-	else
-	{
-		telepathy_connection *data = user_data;
-		GArray *message_IDs;
-
-		int i;
-
-		GHashTable *properties = tp_channel_borrow_immutable_properties(proxy);
-		gchar *who = (gchar *)tp_asv_get_string(properties, TP_IFACE_CHANNEL ".TargetID");
-
-		telepathy_text_channel *tp_channel = g_hash_table_lookup(data->text_Channels, who);
-
-		if (tp_channel == NULL)
-		{
-			purple_debug_warning("telepathy", "Received message from %s, but there's no channel struct for the buddy!\n", who);
-		}
-		else
-		{
-			/* we should now allow received_cb to handle incoming messages */
-			tp_channel->received_Pending_Messages = TRUE;
-		}
-
-		/* this will hold the IDs of message that will be acknowledged */
-		message_IDs = g_array_new(FALSE, FALSE, sizeof(guint));
-
-		for (i = 0; i<out_Pending_Messages->len; ++i)
-		{
-			/* unpack the relevant info from (uuuuus) */
-			GValueArray *arr = g_ptr_array_index(out_Pending_Messages, i);
-			guint msg_id = g_value_get_uint(g_value_array_get_nth(arr, 0));
-			guint timestamp = g_value_get_uint(g_value_array_get_nth(arr, 1));
-			guint flags = g_value_get_uint(g_value_array_get_nth(arr, 4));
-			gchar *msg = (gchar *)g_value_get_string(g_value_array_get_nth(arr, 5));
-			
-			/* get the identifier from channel instead of contact since contact might not be ready for offline messages */
-			gchar *from = (gchar *)tp_channel_get_identifier(proxy);
-
-			/* drop message if it's not text */
-			if ((flags & TP_CHANNEL_TEXT_MESSAGE_FLAG_NON_TEXT_CONTENT) == 0)
-				write_message_to_conversation(from, timestamp, msg, user_data);
-
-			/* add the id to the array of acknowledge messages */
-			g_array_append_val(message_IDs, msg_id);
-		}
-
-		/* acknowledge the messages now */
-		tp_cli_channel_type_text_call_acknowledge_pending_messages(proxy, -1, message_IDs,
-				acknowledge_pending_messages_cb, user_data, NULL, NULL);
-
-		g_array_free(message_IDs, TRUE);
-
-	}
-}
-
-static void
-received_cb (TpChannel *proxy,
-             guint arg_ID,
-             guint arg_Timestamp,
-             guint arg_Sender,
-             guint arg_Type,
-             guint arg_Flags,
-             const gchar *arg_Text,
-             gpointer user_data,
-             GObject *weak_object)
-{
-	telepathy_connection *data = user_data;
-
-	GHashTable *properties = tp_channel_borrow_immutable_properties(proxy);
-	gchar *who = (gchar *)tp_asv_get_string(properties, TP_IFACE_CHANNEL ".TargetID");
-
-	telepathy_text_channel *tp_channel = g_hash_table_lookup(data->text_Channels, who);
-
-	if (tp_channel == NULL)
-	{
-		purple_debug_warning("telepathy", "Received message from %s, but there's no channel struct for the buddy!\n", who);
-	}
-	else
-	{
-		GArray *message_IDs;
-
-		/* will this message get caught by ListPendingMessages? */
-		if (!tp_channel->received_Pending_Messages)
-			return;
-
-		/* drop this message if it's not text */
-		if ((arg_Flags & TP_CHANNEL_TEXT_MESSAGE_FLAG_NON_TEXT_CONTENT) == 0)
-			write_message_to_conversation(who, arg_Timestamp, arg_Text, user_data);
-
-		/* acknowledge receiving the message */
-		message_IDs = g_array_new(FALSE, FALSE, sizeof(guint));
-
-		g_array_append_val(message_IDs, arg_ID);
-
-		tp_cli_channel_type_text_call_acknowledge_pending_messages(proxy, -1, message_IDs,
-				acknowledge_pending_messages_cb, user_data, NULL, NULL);
-
-		g_array_free(message_IDs, TRUE);
-
-	}
-}
-
-static void
-send_error_cb (TpChannel *proxy,
-               guint arg_Error,
-               guint arg_Timestamp,
-               guint arg_Type,
-               const gchar *arg_Text,
-               gpointer user_data,
-               GObject *weak_object)
-{
-	telepathy_connection *data = user_data;
-
-	const gchar *who = tp_channel_get_identifier(proxy);
-
-	const gchar *error_reason = NULL;
-	gchar *error_message;
-	gchar *error_message2;
-
-	switch (arg_Error)
-	{
-		case TP_CHANNEL_TEXT_SEND_ERROR_UNKNOWN:
-			error_reason = _("Unknown error");
-		break;
-
-		case TP_CHANNEL_TEXT_SEND_ERROR_OFFLINE:
-			error_reason = _("Contact is offline");
-		break;
-
-		case TP_CHANNEL_TEXT_SEND_ERROR_INVALID_CONTACT:
-			error_reason = _("Contact is invalid");
-		break;
-
-		case TP_CHANNEL_TEXT_SEND_ERROR_PERMISSION_DENIED:
-			error_reason = _("Permission denied");
-		break;
-
-		case TP_CHANNEL_TEXT_SEND_ERROR_TOO_LONG:
-			error_reason = _("The message is too long");
-		break;
-
-		case TP_CHANNEL_TEXT_SEND_ERROR_NOT_IMPLEMENTED:
-			error_reason = _("Not implemented");
-		break;
-	}
-
-	error_message = g_strdup_printf(_("There was an error sending your message to %s"), who);
-	error_message2 = g_strdup_printf("%s: %s", error_message, error_reason);
-
-	/* display the error in the conversation */
-	if (!purple_conv_present_error(who, data->acct, error_message2))
-	{
-		/* display as a popup if there is no active conversation with the user */
-		purple_notify_error(purple_connections_get_handle(),
-				_("Error sending message"),
-				error_message,
-				error_reason);
-	}
-
-	g_free(error_message2);
-	g_free(error_message);
-
-	purple_debug_error("telepathy", "SendError: %s\n", error_reason);
-}
-
-static void
-send_cb (TpChannel *proxy,
-         const GError *error,
-         gpointer user_data,
-         GObject *weak_object)
-{
-	if (error != NULL)
-	{
-		telepathy_connection *data = user_data;
-
-		const gchar *who = tp_channel_get_identifier(proxy);
-
-		gchar *error_message = g_strdup_printf(_("There was an error sending your message to %s"), who);
-		gchar *error_message2 = g_strdup_printf("%s: %s", error_message, error->message);
-
-		/* display the error in the conversation */
-		if (!purple_conv_present_error(who, data->acct, error_message2))
-		{
-			/* display as a popup if there is no active conversation with the user */
-			purple_notify_error(purple_connections_get_handle(),
-					_("Error sending message"),
-					error_message,
-					error->message);
-		}
-
-		g_free(error_message2);
-		g_free(error_message);
-			
-		purple_debug_error("telepathy", "Send error: %s\n", error->message);
-	}
-}
-
-static void
-text_channel_invalidated_cb (TpProxy *self,
-                             guint    domain,
-                             gint     code,
-                             gchar   *message,
-                             gpointer user_data)
-{
-	telepathy_connection *data = user_data;
-
-	/* remove the cached TpChannel proxy when the channel closes */
-	const gchar *who = tp_channel_get_identifier((TpChannel *)self);
-
-	telepathy_text_channel *tp_channel = NULL;
-	
-	if (data->text_Channels)
-		tp_channel = g_hash_table_lookup(data->text_Channels, who);
-
-	purple_debug_info("telepathy", "Text channel with %s closed!\n", who);
-
-	if (tp_channel)
-	{
-		tp_channel->channel = NULL;
-	}
-}
-
-static void
-chat_state_changed_cb (TpChannel *proxy,
-                       guint arg_Contact,
-                       guint arg_State,
-                       gpointer user_data,
-                       GObject *weak_object)
-{
-	telepathy_connection *data = user_data;
-
-	telepathy_contact *contact_data = g_hash_table_lookup(data->contacts, (gpointer)arg_Contact);
-
-	PurpleTypingState state;
-	const gchar *name;
-
-	if (contact_data == NULL)
-	{
-		purple_debug_warning("telepathy", "Chat state changed for %u who isn't cached!\n", arg_Contact);
-		return;
-	}
-
-	name = tp_contact_get_identifier(contact_data->contact);
-
-	purple_debug_info("telepathy", "Chat state changed for %s\n", name);
-
-	switch (arg_State)
-	{
-		case TP_CHANNEL_CHAT_STATE_PAUSED:
-			state = PURPLE_TYPED;
-		break;
-
-		case TP_CHANNEL_CHAT_STATE_COMPOSING:
-			state = PURPLE_TYPING;
-		break;
-
-		default:
-			state = PURPLE_NOT_TYPING;
-		break;
-	}
-
-	if (state == PURPLE_NOT_TYPING)
-	{
-		serv_got_typing_stopped(data->gc, name);
-	}
-	else
-	{
-		serv_got_typing(data->gc, name, -1, state);
-	}
-}
-
-static void
-handle_text_channel (TpChannel *channel,
-                     telepathy_connection *data)
-{
-	GError *error = NULL;
-
-	GHashTable *properties = tp_channel_borrow_immutable_properties(channel);
-	gchar *who = (gchar *)tp_asv_get_string(properties, TP_IFACE_CHANNEL ".TargetID");
-
-	telepathy_text_channel *tp_channel;
-
-	purple_debug_info("telepathy", "Saving TpChannel proxy for %s\n", who);
-
-	tp_channel = g_hash_table_lookup(data->text_Channels, who);
-
-	/* if tp_channel exists, then we requested this channel, else it's an incoming request so we must cache it */
-	if (tp_channel == NULL)
-	{
-		tp_channel = g_new0(telepathy_text_channel, 1);
-		g_hash_table_insert(data->text_Channels, who, tp_channel);
-	}
-
-	tp_channel->channel = channel;
-
-	tp_cli_channel_interface_chat_state_connect_to_chat_state_changed(channel, chat_state_changed_cb, data, NULL, NULL, &error);
-
-	if (error != NULL)
-	{
-		purple_debug_error("telepathy", "Error connecting to ChatStateChanged signal: %s\n", error->message);
-	}
-
-	tp_cli_channel_type_text_connect_to_received(channel, received_cb, data, NULL, NULL, &error);
-
-	if (error != NULL)
-	{
-		purple_debug_error("telepathy", "Error connecting to Received signal: %s\n", error->message);
-	}
-
-	tp_channel->received_Pending_Messages = FALSE;
-
-	g_signal_connect(channel, "invalidated", G_CALLBACK(text_channel_invalidated_cb), data);
-
-	/* the Clear parameter is deprecated, we need to use AcknowledgePendingMessages */
-	tp_cli_channel_type_text_call_list_pending_messages(channel, -1, FALSE, list_pending_messages_cb, data, NULL, NULL);
-
-	/* send pending messages */
-	while (tp_channel->pending_Messages != NULL)
-	{
-		purple_debug_info("telepathy", "Sending pending message \"%s\" to %s\n", (gchar *)tp_channel->pending_Messages->data, who);
-
-		tp_cli_channel_type_text_call_send(channel, -1, TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, tp_channel->pending_Messages->data, send_cb, data, NULL, NULL);
-
-		/* the message was duped */
-		g_free(tp_channel->pending_Messages->data);
-
-		tp_channel->pending_Messages = g_list_delete_link(tp_channel->pending_Messages, tp_channel->pending_Messages);
-	}
-
-	tp_cli_channel_type_text_connect_to_send_error(channel, send_error_cb, data, NULL, NULL, &error);
-
-	if (error != NULL)
-	{
-		purple_debug_error("telepathy", "Error connecting to SendError signal: %s\n", error->message);
-		g_error_free(error);
-	}
-}
-
-static void
-channel_ready_cb (TpChannel *channel,
-                  const GError *error,
-                  gpointer user_data)
-{
-	if (error != NULL)
-	{
-		purple_debug_error("telepathy", "Channel ready error: %s\n", error->message);
-	}
-	else
-	{
-		GQuark handle_Type;
-
-		handle_Type = tp_channel_get_channel_type_id(channel);
-
-		if (handle_Type == TP_IFACE_QUARK_CHANNEL_TYPE_CONTACT_LIST)
-		{
-			handle_list_channel(channel, user_data);
-		}
-		else if (handle_Type == TP_IFACE_QUARK_CHANNEL_TYPE_TEXT)
-		{
-			handle_text_channel(channel, user_data);
-		}
-	}
-}
-
-static void
-channel_invalidated_cb (TpProxy *self,
-                        guint    domain,
-                        gint     code,
-                        gchar   *message,
-                        gpointer user_data)
-{
-	purple_debug_info("telepathy", "Channel invalidated: %s\n", message);	
-
-	g_object_unref(self);
-}
-
-static void
-handle_new_channel (telepathy_connection *data,
-                    const GValueArray *channel_Properties)
-{
-	char *object_Path = g_value_get_boxed(g_value_array_get_nth((GValueArray *)channel_Properties, 0));
-	GHashTable *map = g_value_get_boxed(g_value_array_get_nth((GValueArray *)channel_Properties, 1));
-
-	GError *error = NULL;
-	TpConnection *connection = data->connection;
-	TpChannel *channel = tp_channel_new_from_properties(connection, object_Path, map, &error);
-
-	if (error != NULL)
-	{
-		purple_debug_error("telepathy", "Error while creating TpChannel: %s\n", error->message);
-		g_error_free(error);
-		return;
-	}
-	
-	purple_debug_info("telepathy", "New channel: %s\n", object_Path);
-
-	tp_channel_call_when_ready(channel, channel_ready_cb, data);
-
-	g_signal_connect(channel, "invalidated", G_CALLBACK (channel_invalidated_cb), data);
-}
-
-static void
-new_channels_cb (TpConnection *proxy,
-                 const GPtrArray *arg_Channels,
-                 gpointer user_data,
-                 GObject *weak_object)
-{
-	int i;
-	telepathy_connection *data = user_data;
-
-	if (data->listing_channels)
-		return;
-
-	purple_debug_info("telepathy", "NewChannels:\n");
-
-	for (i = 0; i < arg_Channels->len; i++)
-	{
-		GValueArray *channel = g_ptr_array_index(arg_Channels, i);
-
-		handle_new_channel(user_data, channel);
-	}
-}
-
-static void
-get_channels_cb (TpProxy *proxy,
-                 const GValue *out_Value,
-                 const GError *error,
-                 gpointer user_data,
-                 GObject *weak_object)
-{
-	if (error != NULL)
-	{
-		purple_debug_error("telepathy", "Get Channels error: %s\n", error->message);
-	}
-	else
-	{
-		telepathy_connection *data = user_data;
-
-		/* unpack the a(oa{sv}) struct */
-		const GPtrArray *channels = g_value_get_boxed(out_Value);
-		int i;
-
-		data->listing_channels = FALSE;
-
-		for (i = 0; i < channels->len; i++)
-		{
-			const GValueArray *channel = g_ptr_array_index(channels, i);
-			handle_new_channel(user_data, channel);
-		}
-
-	}
-}
-
-static void
-get_avatar_properties_cb (TpProxy *proxy,
-                          GHashTable *out_Properties,
-                          const GError *error,
-                          gpointer user_data,
-                          GObject *weak_object)
-{
-	if (error != NULL)
-	{
-		purple_debug_error("telepathy", "Error getting avatar properties: %s\n", error->message);
-	}
-	else
-	{
-		telepathy_connection *data = user_data;
-		PurplePlugin *plugin = purple_connection_get_prpl(data->gc);
-		PurplePluginProtocolInfo *prpl_info = plugin->info->extra_info;
-
-
-		GHashTableIter iter;
-		gpointer key, value;
-
-		PurpleBuddyIconSpec icon_spec = NO_BUDDY_ICONS;
-		icon_spec.scale_rules = PURPLE_ICON_SCALE_SEND;
-
-		purple_debug_info("telepathy", "Got avatar properties!\n");
-
-		g_hash_table_iter_init(&iter, out_Properties);
-
-		/* iterate over all properties */
-		while (g_hash_table_iter_next(&iter, &key, &value))
-		{
-			gchar *name = key;
-			GValue *val = value;
-
-			if (g_strcmp0("SupportedAvatarMIMETypes", name) == 0)
-			{
-				/* This parameter is of dbus type "as"
-				 * It's exposed as a GValue holding a (gchar **)
-				 * Or is it now??? wtf!?
-				 */
-
-				gchar *format = NULL;
-
-				int i;
-				gchar **arr = g_value_get_boxed(val);
-
-				for (i = 0; arr[i] != NULL; ++i)
-				{
-					const gchar *mime_type = arr[i];
-
-					int j;
-
-					/* We want to get the part after the / 
-					 * Split the string using / as a delimiter and use the last part
-					 */
-					gchar **split = g_strsplit(mime_type, "/", 0);
-					gchar *old = format;
-
-					/* j will be the last non-NULL token */
-					for (j = 0; split[j] != NULL; ++j);
-					--j;
-
-
-					/* if this is the first type, don't prepend a comma */
-					if (i == 0)
-						format = g_strdup(split[j]);
-					else
-						format = g_strdup_printf("%s,%s", format, split[j]);
-
-					g_free(old);
-					g_strfreev(split);
-				}
-
-				purple_debug_info("telepathy", "    Supported types: %s\n", format);
-
-				icon_spec.format = format;
-			}
-			else if (g_strcmp0("MinimumAvatarWidth", name) == 0)
-			{
-				icon_spec.min_width = g_value_get_uint(val);
-			}
-			else if (g_strcmp0("MinimumAvatarHeight", name) == 0)
-			{
-				icon_spec.min_height = g_value_get_uint(val);
-			}
-			else if (g_strcmp0("MaximumAvatarWidth", name) == 0)
-			{
-				icon_spec.max_width = g_value_get_uint(val);
-			}
-			else if (g_strcmp0("MaximumAvatarHeight", name) == 0)
-			{
-				icon_spec.max_height = g_value_get_uint(val);
-			}
-			else if (g_strcmp0("MaximumAvatarBytes", name) == 0)
-			{
-				icon_spec.max_filesize = g_value_get_uint(val);
-			}
-		}
-
-		prpl_info->icon_spec = icon_spec;
-	}
-}
-
-static void
-connection_ready_cb (TpConnection *connection,
-                     const GError *error,
-                     gpointer user_data)
-{
-	if (error != NULL)
-	{
-		purple_debug_info("telepathy", "Connection ready error: %s\n", error->message);
-	}
-	else
-	{
-		char **interfaces, **ptr;
-		GError *error = NULL;
-		telepathy_connection *data = user_data;
-
-		purple_debug_info("telepathy", "Connection is ready. Interfaces implemented:\n");
-
-		/* query interfaces */
-		g_object_get(connection, "interfaces", &interfaces, NULL);
-		for (ptr = interfaces; ptr && *ptr; ptr++)
-		{
-			purple_debug_info("telepathy", "  %s\n", *ptr);
-		}
-		g_strfreev(interfaces);
-
-		tp_cli_connection_interface_requests_connect_to_new_channels(connection, new_channels_cb, user_data, NULL, NULL, &error);
-
-		if (error != NULL)
-		{
-			purple_debug_error("telepathy", "Error while connecting to NewChannels signal: %s\n", error->message);
-			g_error_free(error);
-			error = NULL;
-			return;
-		}
-
-		data->listing_channels = TRUE;
-			
-		/* query the Channels property of the Requests interface */
-		tp_cli_dbus_properties_call_get(connection, -1, TP_IFACE_CONNECTION_INTERFACE_REQUESTS, "Channels", get_channels_cb, user_data, NULL, NULL);
-
-
-		/* query supported avatar formats */
-		tp_cli_dbus_properties_call_get_all(connection, -1, TP_IFACE_CONNECTION_INTERFACE_AVATARS, get_avatar_properties_cb, user_data, NULL, NULL);
-
-		/* this will be fired when an avatar for a buddy has been received */
-		tp_cli_connection_interface_avatars_connect_to_avatar_retrieved(connection,
-				avatar_retrieved_cb, data,
-				NULL, NULL,
-				&error);
-		
-		if (error != NULL)
-		{
-			purple_debug_error("telepathy", "Error connecting to AvatarRetrieved signal: %s\n", error->message);
-			g_error_free(error);
-		}
-
-		tp_cli_connection_interface_avatars_connect_to_avatar_updated(connection,
-				avatar_updated_cb, data,
-				NULL, NULL,
-				&error);
-
-		if (error != NULL)
-		{
-			purple_debug_error("telepathy", "Error connecting to AvatarUpdated signal: %s\n", error->message);
-			g_error_free(error);
-		}
-
-	}
-}
-
-static void
-status_changed_cb (TpConnection *proxy,
-                   guint arg_Status,
-                   guint arg_Reason,
-                   gpointer user_data,
-                   GObject *weak_object)
-{
-	telepathy_connection *data = user_data;
-
-	if (arg_Status == TP_CONNECTION_STATUS_CONNECTED)
-	{
-		purple_debug_info("telepathy", "Connected!\n");
-
-		purple_connection_update_progress(data->gc, _("Connected"),
-				1,   /* which connection step this is */
-				2);  /* total number of steps */
-
-		purple_connection_set_state(data->gc, PURPLE_CONNECTED);
-
-		data->text_Channels = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) destroy_text_channel);
-		data->contacts = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) destroy_contact);
-	}
-	else if (arg_Status == TP_CONNECTION_STATUS_DISCONNECTED)
-	{
-		gchar *reason = NULL;
-		PurpleConnectionError error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
-		purple_debug_info("telepathy", "Disconnected! Reason: %d\n", arg_Reason);
-
-		switch (arg_Reason)
-		{
-			case TP_CONNECTION_STATUS_REASON_NETWORK_ERROR:
-				reason = "Network error";
-				error = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-			break;
-
-			case TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED:
-				reason = "Authentication failed";
-				error = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
-			break;
-
-			case TP_CONNECTION_STATUS_REASON_ENCRYPTION_ERROR:
-				reason = "Encryption error";
-				error = PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR;
-			break;
-
-			case TP_CONNECTION_STATUS_REASON_NAME_IN_USE:
-				reason = "Name in use";
-				error = PURPLE_CONNECTION_ERROR_NAME_IN_USE;
-			break;
-
-			case TP_CONNECTION_STATUS_REASON_CERT_NOT_PROVIDED:
-				reason = "SSL Certificate not provided";
-				error = PURPLE_CONNECTION_ERROR_CERT_NOT_PROVIDED;
-			break;
-
-			case TP_CONNECTION_STATUS_REASON_CERT_UNTRUSTED:
-				reason = "SSL Certificate is isnged by an untrusted certifying authority";
-				error = PURPLE_CONNECTION_ERROR_CERT_UNTRUSTED;
-			break;
-
-			case TP_CONNECTION_STATUS_REASON_CERT_EXPIRED:
-				reason = "SSL Certificate expired";
-				error = PURPLE_CONNECTION_ERROR_CERT_EXPIRED;
-			break;
-
-			case TP_CONNECTION_STATUS_REASON_CERT_NOT_ACTIVATED:
-				reason = "SSL Certificate is not yet valid";
-				error = PURPLE_CONNECTION_ERROR_CERT_NOT_ACTIVATED;
-			break;
-
-			case TP_CONNECTION_STATUS_REASON_CERT_HOSTNAME_MISMATCH:
-				reason = "SSL Certificate hostname mismatch";
-				error = PURPLE_CONNECTION_ERROR_CERT_HOSTNAME_MISMATCH;
-			break;
-
-			case TP_CONNECTION_STATUS_REASON_CERT_FINGERPRINT_MISMATCH:
-				reason = "SSL Certificate fingerprint mismatch";
-				error = PURPLE_CONNECTION_ERROR_CERT_FINGERPRINT_MISMATCH;
-			break;
-
-			case TP_CONNECTION_STATUS_REASON_CERT_SELF_SIGNED:
-				reason = "SSL Certificate is self-signed";
-				error = PURPLE_CONNECTION_ERROR_CERT_SELF_SIGNED;
-			break;
-
-			case TP_CONNECTION_STATUS_REASON_CERT_OTHER_ERROR:
-				reason = "Error while validating the server's SSL Certificate";
-				error = PURPLE_CONNECTION_ERROR_CERT_OTHER_ERROR;
-			break;
-		}
-
-		if (data)
-		{
-			purple_connection_set_protocol_data(data->gc, NULL);
-
-			if (reason != NULL && data->gc)
-				purple_connection_error_reason(data->gc, error, reason);
-
-			if (data->connection != NULL)
-			{
-				g_object_unref(data->connection);
-				data->connection = NULL;
-			}
-
-			if (data->text_Channels != NULL)
-			{
-				g_hash_table_destroy(data->text_Channels);
-				data->text_Channels = NULL;
-			}
-			if (data->contacts != NULL)
-			{
-				g_hash_table_destroy(data->contacts);
-				data->contacts = NULL;
-			}
-
-			g_free(data);
-		}
-
-	}
-	else if (arg_Status == TP_CONNECTION_STATUS_CONNECTING)
-	{
-		purple_debug_info("telepathy", "Connecting! Reason: %d\n", arg_Reason);
-		purple_connection_set_state(data->gc, PURPLE_CONNECTING);
-		purple_connection_update_progress(data->gc, _("Connecting"),
-				0,   /* which connection step this is */
-				2);  /* total number of steps */
-
-	}
-}
-
-static void
-connection_connect_cb (TpConnection *proxy,
-                       const GError *error,
-                       gpointer user_data,
-                       GObject *weak_object)
-{
-	/* if this fails, something must be broken somewhere */
-	if (error != NULL)
-	{
-		purple_debug_error("telepathy", "Connect error: %s\n", error->message);
-	}
-}
-
-static void
-request_connection_cb (TpConnectionManager *proxy,
-                       const gchar *out_Bus_Name,
-                       const gchar *out_Object_Path,
-                       const GError *error,
-                       gpointer user_data,
-                       GObject *weak_object)
-{
-	PurpleConnection *gc = user_data;
-
-	if (error != NULL)
-	{
-		purple_debug_info("telepathy", "RequestConnection error: %s\n", error->message);
-
-		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, error->message);
-	}
-	else
-	{
-		GError *error = NULL;
-		telepathy_connection *connection_data;
-
-		TpDBusDaemon *daemon = tp_dbus_daemon_dup(&error);
-		
-		if (error != NULL)
-		{
-			purple_debug_error("telepathy", "Error creating dbus daemon: %s\n", error->message);
-			g_error_free(error);
-			return;
-		}
-
-		connection_data = g_new0(telepathy_connection, 1);
-
-		/* get the connection proxy straight out of the dbus interface */
-		connection_data->connection = tp_connection_new(daemon, out_Bus_Name, out_Object_Path, &error);
-		connection_data->gc = gc;
-		connection_data->acct = purple_connection_get_account(gc);
-		purple_connection_set_protocol_data(gc, connection_data);
-
-		if (error != NULL)
-		{
-			purple_debug_error("telepathy", "Error creating TpConnection object: %s\n", error->message);
-			g_error_free(error);
-
-			g_object_unref(connection_data->connection);
-			connection_data->connection = NULL;
-			g_free(connection_data);
-			return;
-		}
-
-		tp_connection_call_when_ready(connection_data->connection, connection_ready_cb, connection_data);
-
-		/* this will indicate any connection status change, also providing a reason */
-		tp_cli_connection_connect_to_status_changed(connection_data->connection, status_changed_cb, connection_data, NULL, NULL, &error);
-
-		if (error != NULL)
-		{
-			purple_debug_error("telepathy", "Error conencting to StatusChanged: %s\n", error->message);
-			g_error_free(error);
-
-			tp_cli_connection_call_disconnect(connection_data->connection, -1, NULL, NULL, NULL, NULL);
-			g_object_unref(connection_data->connection);
-			connection_data->connection = NULL;
-			g_free(connection_data);
-		}
-		else
-		{
-			/* do some magic now :) */
-			tp_cli_connection_call_connect(connection_data->connection, -1, connection_connect_cb, connection_data, NULL, NULL);
-		}
-
-		if (daemon != NULL)
-			g_object_unref(daemon);
-	}
-}
-
-static void
 telepathy_login(PurpleAccount *acct)
 {
 	PurpleConnection *gc = purple_account_get_connection(acct);
@@ -1649,21 +310,6 @@ telepathy_close(PurpleConnection *gc)
 	}
 }
 
-static void
-ensure_channel_cb (TpConnection *proxy,
-                   gboolean out_Yours,
-                   const gchar *out_Channel,
-                   GHashTable *out_Properties,
-                   const GError *error,
-                   gpointer user_data,
-                   GObject *weak_object)
-{
-	if (error != NULL)
-	{
-		purple_debug_error("telepathy", "EnsureChannel error: %s\n", error->message);
-	}
-}
-
 static int
 telepathy_send_im (PurpleConnection *gc,
                    const char *who,
@@ -1718,18 +364,6 @@ telepathy_send_im (PurpleConnection *gc,
 	return 1;
 }
 
-static void
-set_chat_state_cb (TpChannel *proxy,
-                   const GError *error,
-                   gpointer user_data,
-                   GObject *weak_object)
-{
-	if (error != NULL)
-	{
-		purple_debug_error("telepathy", "SetChatState error: %s\n", error->message);
-	}
-}
-
 static unsigned int
 telepathy_send_typing (PurpleConnection *gc, const char *name, PurpleTypingState state)
 {
@@ -1781,18 +415,6 @@ static void
 }
 
 static void
-set_presence_cb (TpConnection *proxy,
-                 const GError *error,
-                 gpointer user_data,
-                 GObject *weak_object)
-{
-	if (error != NULL)
-	{
-		purple_debug_error("telepathy", "SetStatus error: %s\n", error->message);
-	}
-}
-
-static void
 telepathy_set_status (PurpleAccount *account, PurpleStatus *status)
 {
 	PurpleConnection *gc = purple_account_get_connection(account);
@@ -1811,31 +433,6 @@ static void
 }
 
 static void
-set_avatar_cb (TpConnection *proxy,
-               const gchar *out_Token,
-               const GError *error,
-               gpointer user_data,
-               GObject *weak_object)
-{
-	if (error != NULL)
-	{
-		purple_debug_error("telepathy", "SetAvatar error: %s\n", error->message);
-	}
-}
-
-static void
-clear_avatar_cb (TpConnection *proxy,
-                 const GError *error,
-                 gpointer user_data,
-                 GObject *weak_object)
-{
-	if (error != NULL)
-	{
-		purple_debug_error("telepathy", "ClearAvatar error: %s\n", error->message);
-	}
-}
-
-static void
 telepathy_set_buddy_icon (PurpleConnection *gc, PurpleStoredImage *img)
 {
 	telepathy_connection *data = purple_connection_get_protocol_data(gc);


More information about the Commits mailing list