/pidgin/main: 68d162284480: XMPP: adjust facebook roster quirks

Tomasz Wasilczyk twasilczyk at pidgin.im
Wed May 7 09:54:56 EDT 2014


Changeset: 68d162284480d3158697c68f3021dbd242dd19f6
Author:	 Tomasz Wasilczyk <twasilczyk at pidgin.im>
Date:	 2014-05-07 15:54 +0200
Branch:	 default
URL: https://hg.pidgin.im/pidgin/main/rev/68d162284480

Description:

XMPP: adjust facebook roster quirks

diffstat:

 libpurple/protocols/jabber/Makefile.am       |    2 +
 libpurple/protocols/jabber/facebook_roster.c |  130 +++++++++++++++++++++++++++
 libpurple/protocols/jabber/facebook_roster.h |   35 +++++++
 libpurple/protocols/jabber/jabber.h          |    2 +
 libpurple/protocols/jabber/libfacebook.c     |   19 +++-
 libpurple/protocols/jabber/roster.c          |    8 +
 6 files changed, 195 insertions(+), 1 deletions(-)

diffs (265 lines):

diff --git a/libpurple/protocols/jabber/Makefile.am b/libpurple/protocols/jabber/Makefile.am
--- a/libpurple/protocols/jabber/Makefile.am
+++ b/libpurple/protocols/jabber/Makefile.am
@@ -27,6 +27,8 @@ JABBERSOURCES = \
 			  data.h \
 			  disco.c \
 			  disco.h \
+			  facebook_roster.c \
+			  facebook_roster.h \
 			  google/gmail.c \
 			  google/gmail.h \
 			  google/google.c \
diff --git a/libpurple/protocols/jabber/facebook_roster.c b/libpurple/protocols/jabber/facebook_roster.c
new file mode 100644
--- /dev/null
+++ b/libpurple/protocols/jabber/facebook_roster.c
@@ -0,0 +1,130 @@
+/**
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * 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 "facebook_roster.h"
+
+#include "roster.h"
+
+void
+jabber_facebook_roster_cleanup(JabberStream *js, PurpleXmlNode *query)
+{
+	PurpleAccount *account = purple_connection_get_account(js->gc);
+	PurpleXmlNode *item;
+	GSList *local_buddies;
+	GHashTable *remove_buddies;
+	GHashTableIter it;
+	PurpleBuddy *buddy;
+	const gchar *jid;
+
+	/* mark all local buddies as "to be removed" */
+	remove_buddies = g_hash_table_new_full(g_str_hash, g_str_equal,
+		g_free, NULL);
+	local_buddies = purple_blist_find_buddies(account, NULL);
+	for (; local_buddies; local_buddies = g_slist_delete_link(
+		local_buddies, local_buddies))
+	{
+		buddy = local_buddies->data;
+
+		g_hash_table_insert(remove_buddies, g_strdup(jabber_normalize(
+			account, purple_buddy_get_name(buddy))), buddy);
+	}
+
+	/* un-mark all remote buddies */
+	for (item = purple_xmlnode_get_child(query, "item"); item;
+		item = purple_xmlnode_get_next_twin(item))
+	{
+		jid = purple_xmlnode_get_attrib(item, "jid");
+
+		g_hash_table_remove(remove_buddies,
+			jabber_normalize(account, jid));
+	}
+
+	/* remove all not-remote buddies */
+	g_hash_table_iter_init(&it, remove_buddies);
+	while (g_hash_table_iter_next(&it, (gpointer*)&jid, (gpointer*)&buddy)) {
+		const gchar *alias = purple_buddy_get_local_alias(buddy);
+		item = purple_xmlnode_new_child(query, "item");
+		purple_xmlnode_set_namespace(item,
+			purple_xmlnode_get_namespace(query));
+		purple_xmlnode_set_attrib(item, "jid", jid);
+		purple_xmlnode_set_attrib(item, "subscription", "remove");
+		if (alias)
+			purple_xmlnode_set_attrib(item, "name", alias);
+	}
+
+	g_hash_table_destroy(remove_buddies);
+}
+
+gboolean
+jabber_facebook_roster_incoming(JabberStream *js, PurpleXmlNode *item)
+{
+	PurpleAccount *account = purple_connection_get_account(js->gc);
+	const gchar *jid, *subscription;
+	gchar *jid_norm;
+	PurpleBuddy *buddy;
+	PurpleGroup *buddy_group;
+	PurpleXmlNode *group;
+	const gchar *alias;
+
+	subscription = purple_xmlnode_get_attrib(item, "subscription");
+
+	/* Skip entries added with jabber_facebook_roster_cleanup */
+	if (g_strcmp0(subscription, "remove") == 0)
+		return TRUE;
+
+	jid = purple_xmlnode_get_attrib(item, "jid");
+	jid_norm = g_strdup(jabber_normalize(account, jid));
+	buddy = purple_blist_find_buddy(account, jid);
+	g_free(jid_norm);
+
+	/* Facebook forces "Facebook Friends" group */
+	while ((group = purple_xmlnode_get_child(item, "group")) != NULL)
+		purple_xmlnode_free(group);
+	group = purple_xmlnode_new_child(item, "group");
+	purple_xmlnode_set_namespace(group, purple_xmlnode_get_namespace(item));
+
+	/* We don't have that buddy on the list, add him to the default group */
+	if (!buddy) {
+		purple_xmlnode_insert_data(group,
+			JABBER_ROSTER_DEFAULT_GROUP, -1);
+		return TRUE;
+	}
+
+	/* Facebook forces buddy real name as alias */
+	alias = purple_buddy_get_local_alias(buddy);
+	if (alias)
+		purple_xmlnode_set_attrib(item, "name", alias);
+
+	/* Add buddy to his group */
+	buddy_group = purple_buddy_get_group(buddy);
+	if (buddy_group == purple_blist_get_default_group())
+		buddy_group = NULL;
+	if (buddy_group) {
+		purple_xmlnode_insert_data(group,
+			purple_group_get_name(buddy_group), -1);
+	} else {
+		purple_xmlnode_insert_data(group,
+			JABBER_ROSTER_DEFAULT_GROUP, -1);
+	}
+
+	return TRUE;
+}
diff --git a/libpurple/protocols/jabber/facebook_roster.h b/libpurple/protocols/jabber/facebook_roster.h
new file mode 100644
--- /dev/null
+++ b/libpurple/protocols/jabber/facebook_roster.h
@@ -0,0 +1,35 @@
+/**
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * 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 PURPLE_XMPP_FACEBOOK_ROSTER_H_
+#define PURPLE_XMPP_FACEBOOK_ROSTER_H_
+
+#include "jabber.h"
+
+/* removes deleted buddies from the list */
+void
+jabber_facebook_roster_cleanup(JabberStream *js, PurpleXmlNode *query);
+
+/* ignores facebook roster quirks */
+gboolean
+jabber_facebook_roster_incoming(JabberStream *js, PurpleXmlNode *item);
+
+#endif /* PURPLE_XMPP_FACEBOOK_ROSTER_H_ */
diff --git a/libpurple/protocols/jabber/jabber.h b/libpurple/protocols/jabber/jabber.h
--- a/libpurple/protocols/jabber/jabber.h
+++ b/libpurple/protocols/jabber/jabber.h
@@ -49,6 +49,8 @@ typedef enum {
 	JABBER_CAP_ITEMS          = 1 << 14,
 	JABBER_CAP_ROSTER_VERSIONING = 1 << 15,
 
+	JABBER_CAP_FACEBOOK       = 1 << 16,
+
 	JABBER_CAP_RETRIEVED      = 1 << 31
 } JabberCapabilities;
 
diff --git a/libpurple/protocols/jabber/libfacebook.c b/libpurple/protocols/jabber/libfacebook.c
--- a/libpurple/protocols/jabber/libfacebook.c
+++ b/libpurple/protocols/jabber/libfacebook.c
@@ -55,6 +55,23 @@ facebook_list_icon(PurpleAccount *a, Pur
 	return "facebook";
 }
 
+static void
+facebook_login(PurpleAccount *account)
+{
+	PurpleConnection *gc;
+	JabberStream *js;
+
+	jabber_login(account);
+
+	gc = purple_account_get_connection(account);
+	js = purple_connection_get_protocol_data(gc);
+
+	if (!js)
+		return;
+
+	js->server_caps |= JABBER_CAP_FACEBOOK;
+}
+
 static PurplePlugin *my_protocol = NULL;
 
 static PurplePluginProtocolInfo prpl_info =
@@ -76,7 +93,7 @@ static PurplePluginProtocolInfo prpl_inf
 	jabber_blist_node_menu,			/* blist_node_menu */
 	jabber_chat_info,				/* chat_info */
 	jabber_chat_info_defaults,		/* chat_info_defaults */
-	jabber_login,					/* login */
+	facebook_login,					/* login */
 	jabber_close,					/* close */
 	jabber_message_send_im,			/* send_im */
 	jabber_set_info,				/* set_info */
diff --git a/libpurple/protocols/jabber/roster.c b/libpurple/protocols/jabber/roster.c
--- a/libpurple/protocols/jabber/roster.c
+++ b/libpurple/protocols/jabber/roster.c
@@ -27,6 +27,7 @@
 
 #include "buddy.h"
 #include "chat.h"
+#include "facebook_roster.h"
 #include "google/google.h"
 #include "google/google_roster.h"
 #include "presence.h"
@@ -215,11 +216,18 @@ void jabber_roster_parse(JabberStream *j
 
 	js->currently_parsing_roster_push = TRUE;
 
+	if (js->server_caps & JABBER_CAP_FACEBOOK)
+		jabber_facebook_roster_cleanup(js, query);
+
 	for(item = purple_xmlnode_get_child(query, "item"); item; item = purple_xmlnode_get_next_twin(item))
 	{
 		const char *jid, *name, *subscription, *ask;
 		JabberBuddy *jb;
 
+		if (js->server_caps & JABBER_CAP_FACEBOOK)
+			if (!jabber_facebook_roster_incoming(js, item))
+				continue;
+
 		subscription = purple_xmlnode_get_attrib(item, "subscription");
 		jid = purple_xmlnode_get_attrib(item, "jid");
 		name = purple_xmlnode_get_attrib(item, "name");



More information about the Commits mailing list