/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");