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

Tomasz Wasilczyk <[email protected]>
Newsgroups gmane.comp.gnome.gaim.cvs
Message-ID <[email protected]>
Changeset: 68d162284480d3158697c68f3021dbd242dd19f6
Author:	 Tomasz Wasilczyk <[email protected]>
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");
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.