/pidgin/main: a351cbf422ed: Backport 68d162284480: facebook rost...
Tomasz Wasilczyk <[email protected]>
| Newsgroups | gmane.comp.gnome.gaim.cvs |
|---|---|
| Message-ID | <[email protected]> |
Changeset: a351cbf422ed20bbde373ccb9beb5337c4bfa421 Author: Tomasz Wasilczyk <[email protected]> Date: 2014-05-07 16:22 +0200 Branch: release-2.x.y URL: https://hg.pidgin.im/pidgin/main/rev/a351cbf422ed Description: Backport 68d162284480: facebook roster quirks diffstat: libpurple/protocols/jabber/Makefile.am | 2 + libpurple/protocols/jabber/facebook_roster.c | 131 +++++++++++++++++++++++++++ libpurple/protocols/jabber/facebook_roster.h | 35 +++++++ libpurple/protocols/jabber/jabber.c | 6 + libpurple/protocols/jabber/jabber.h | 2 + libpurple/protocols/jabber/roster.c | 8 + 6 files changed, 184 insertions(+), 0 deletions(-) diffs (246 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,131 @@ +/** + * 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" + +#include "internal.h" + +void +jabber_facebook_roster_cleanup(JabberStream *js, xmlnode *query) +{ + PurpleAccount *account = purple_connection_get_account(js->gc); + xmlnode *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_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 = xmlnode_get_child(query, "item"); item; + item = xmlnode_get_next_twin(item)) + { + jid = 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_buddy_alias(buddy); + item = xmlnode_new_child(query, "item"); + xmlnode_set_namespace(item, xmlnode_get_namespace(query)); + xmlnode_set_attrib(item, "jid", jid); + xmlnode_set_attrib(item, "subscription", "remove"); + if (alias) + xmlnode_set_attrib(item, "name", alias); + } + + g_hash_table_destroy(remove_buddies); +} + +gboolean +jabber_facebook_roster_incoming(JabberStream *js, xmlnode *item) +{ + PurpleAccount *account = purple_connection_get_account(js->gc); + const gchar *jid, *subscription; + gchar *jid_norm; + PurpleBuddy *buddy; + PurpleGroup *buddy_group; + xmlnode *group; + const gchar *alias; + + subscription = xmlnode_get_attrib(item, "subscription"); + + /* Skip entries added with jabber_facebook_roster_cleanup */ + if (g_strcmp0(subscription, "remove") == 0) + return TRUE; + + jid = xmlnode_get_attrib(item, "jid"); + jid_norm = g_strdup(jabber_normalize(account, jid)); + buddy = purple_find_buddy(account, jid); + g_free(jid_norm); + + /* Facebook forces "Facebook Friends" group */ + while ((group = xmlnode_get_child(item, "group")) != NULL) + xmlnode_free(group); + group = xmlnode_new_child(item, "group"); + xmlnode_set_namespace(group, xmlnode_get_namespace(item)); + + /* We don't have that buddy on the list, add him to the default group */ + if (!buddy) { + xmlnode_insert_data(group, + JABBER_ROSTER_DEFAULT_GROUP, -1); + return TRUE; + } + + /* Facebook forces buddy real name as alias */ + alias = purple_buddy_get_local_buddy_alias(buddy); + if (alias) + xmlnode_set_attrib(item, "name", alias); + + /* Add buddy to his group */ + buddy_group = purple_buddy_get_group(buddy); + if (g_strcmp0(purple_group_get_name(buddy_group), _("Buddies")) == 0) + buddy_group = NULL; + if (buddy_group) { + xmlnode_insert_data(group, + purple_group_get_name(buddy_group), -1); + } else { + 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, xmlnode *query); + +/* ignores facebook roster quirks */ +gboolean +jabber_facebook_roster_incoming(JabberStream *js, xmlnode *item); + +#endif /* PURPLE_XMPP_FACEBOOK_ROSTER_H_ */ diff --git a/libpurple/protocols/jabber/jabber.c b/libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c +++ b/libpurple/protocols/jabber/jabber.c @@ -934,6 +934,12 @@ jabber_stream_new(PurpleAccount *account js->gc = gc; js->fd = -1; + if (g_strcmp0("prpl-facebook-xmpp", + purple_account_get_protocol_id(account)) == 0) + { + js->server_caps |= JABBER_CAP_FACEBOOK; + } + user = g_strdup(purple_account_get_username(account)); /* jabber_id_new doesn't accept "user@domain/" as valid */ slash = strchr(user, '/'); 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/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" @@ -211,11 +212,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 = xmlnode_get_child(query, "item"); item; item = 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 = xmlnode_get_attrib(item, "subscription"); jid = xmlnode_get_attrib(item, "jid"); name = xmlnode_get_attrib(item, "name");