From: <sea...@us...> - 2006-12-14 04:58:37
|
Revision: 17993 http://svn.sourceforge.net/gaim/?rev=17993&view=rev Author: seanegan Date: 2006-12-13 20:56:54 -0800 (Wed, 13 Dec 2006) Log Message: ----------- Blocking on Google Talk. Our Privacy API sucks so bad that even with no prior support for blocking in Jabber, this has no interface changes. If someone wanted to implement the deprecated Jabber privacy lists API, though, that would be ok by me. Modified Paths: -------------- trunk/libgaim/protocols/jabber/disco.c trunk/libgaim/protocols/jabber/google.c trunk/libgaim/protocols/jabber/google.h trunk/libgaim/protocols/jabber/jabber.c trunk/libgaim/protocols/jabber/jabber.h trunk/libgaim/protocols/jabber/parser.c trunk/libgaim/protocols/jabber/roster.c trunk/libgaim/xmlnode.c trunk/libgaim/xmlnode.h Modified: trunk/libgaim/protocols/jabber/disco.c =================================================================== --- trunk/libgaim/protocols/jabber/disco.c 2006-12-14 04:17:02 UTC (rev 17992) +++ trunk/libgaim/protocols/jabber/disco.c 2006-12-14 04:56:54 UTC (rev 17993) @@ -27,8 +27,8 @@ #include "iq.h" #include "disco.h" #include "jabber.h" +#include "roster.h" - struct _jabber_disco_info_cb_data { gpointer data; JabberDiscoInfoCallback *callback; @@ -262,8 +262,14 @@ if (!strcmp("google:mail:notify", var)) { js->server_caps |= JABBER_CAP_GMAIL_NOTIFY; jabber_gmail_init(js); + } else if (!strcmp("google:roster", var)) { + js->server_caps |= JABBER_CAP_GOOGLE_ROSTER; + jabber_google_roster_init(js); } } + + if (!js->server_caps & JABBER_CAP_GOOGLE_ROSTER) + jabber_roster_request(js); } static void Modified: trunk/libgaim/protocols/jabber/google.c =================================================================== --- trunk/libgaim/protocols/jabber/google.c 2006-12-14 04:17:02 UTC (rev 17992) +++ trunk/libgaim/protocols/jabber/google.c 2006-12-14 04:56:54 UTC (rev 17993) @@ -21,8 +21,12 @@ #include "internal.h" #include "debug.h" +#include "privacy.h" + +#include "buddy.h" #include "google.h" #include "jabber.h" +#include "presence.h" #include "iq.h" static void @@ -167,3 +171,190 @@ jabber_iq_set_callback(iq, jabber_gmail_parse, NULL); jabber_iq_send(iq); } + +void jabber_google_roster_init(JabberStream *js) +{ + JabberIq *iq; + xmlnode *query; + + iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:roster"); + query = xmlnode_get_child(iq->node, "query"); + + xmlnode_set_attrib(query, "xmlns:gr", "google:roster"); + xmlnode_set_attrib(query, "gr:ext", "2"); + + jabber_iq_send(iq); +} + +void jabber_google_roster_outgoing(JabberStream *js, xmlnode *query, xmlnode *item) +{ + GaimAccount *account = gaim_connection_get_account(js->gc); + GSList *list = account->deny; + const char *jid = xmlnode_get_attrib(item, "jid"); + char *jid_norm = g_strdup(jabber_normalize(account, jid)); + + while (list) { + if (!strcmp(jid_norm, (char*)list->data)) { + xmlnode_set_attrib(query, "xmlns:gr", "google:roster"); + xmlnode_set_attrib(item, "gr:t", "B"); + xmlnode_set_attrib(query, "xmlns:gr", "google:roster"); + xmlnode_set_attrib(query, "gr:ext", "2"); + return; + } + list = list->next; + } + +} + +void jabber_google_roster_incoming(JabberStream *js, xmlnode *item) +{ + GaimAccount *account = gaim_connection_get_account(js->gc); + GSList *list = account->deny; + const char *jid = xmlnode_get_attrib(item, "jid"); + gboolean on_block_list = FALSE; + + char *jid_norm = g_strdup(jabber_normalize(account, jid)); + + const char *grt = xmlnode_get_attrib_with_namespace(item, "t", "google:roster"); + + while (list) { + if (!strcmp(jid_norm, (char*)list->data)) { + on_block_list = TRUE; + break; + } + list = list->next; + } + + if (!on_block_list && (grt && (*grt == 'B' || *grt == 'b'))) { + gaim_debug_info("jabber", "Blocking %s\n", jid_norm); + gaim_privacy_deny_add(account, jid_norm, TRUE); + } else if (on_block_list && (!grt || (*grt != 'B' && *grt != 'b' ))){ + gaim_debug_info("jabber", "Unblocking %s\n", jid_norm); + gaim_privacy_deny_remove(account, jid_norm, TRUE); + } +} + +void jabber_google_roster_add_deny(GaimConnection *gc, const char *who) +{ + JabberStream *js; + GSList *buddies; + JabberIq *iq; + xmlnode *query; + xmlnode *item; + xmlnode *group; + GaimBuddy *b; + JabberBuddy *jb; + + js = (JabberStream*)(gc->proto_data); + + if (!js || !js->server_caps & JABBER_CAP_GOOGLE_ROSTER) + return; + + jb = jabber_buddy_find(js, who, TRUE); + + buddies = gaim_find_buddies(js->gc->account, who); + if(!buddies) + return; + + b = buddies->data; + + iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster"); + + query = xmlnode_get_child(iq->node, "query"); + item = xmlnode_new_child(query, "item"); + + while(buddies) { + GaimGroup *g; + + b = buddies->data; + g = gaim_buddy_get_group(b); + + group = xmlnode_new_child(item, "group"); + xmlnode_insert_data(group, g->name, -1); + + buddies = buddies->next; + } + + iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster"); + + query = xmlnode_get_child(iq->node, "query"); + item = xmlnode_new_child(query, "item"); + + xmlnode_set_attrib(item, "jid", who); + xmlnode_set_attrib(item, "name", b->alias ? b->alias : ""); + xmlnode_set_attrib(item, "gr:t", "B"); + xmlnode_set_attrib(query, "xmlns:gr", "google:roster"); + xmlnode_set_attrib(query, "gr:ext", "2"); + + jabber_iq_send(iq); + + /* Synthesize a sign-off */ + if (jb) { + JabberBuddyResource *jbr; + GList *l = jb->resources; + while (l) { + jbr = l->data; + printf("ASDFA %s\n", jbr->name); + jabber_buddy_remove_resource(jb, jbr->name); + l = l->next; + } + } + gaim_prpl_got_user_status(gaim_connection_get_account(gc), who, "offline", NULL); +} + +void jabber_google_roster_rem_deny(GaimConnection *gc, const char *who) +{ + JabberStream *js; + GSList *buddies; + JabberIq *iq; + xmlnode *query; + xmlnode *item; + xmlnode *group; + GaimBuddy *b; + + g_return_if_fail(gc != NULL); + g_return_if_fail(who != NULL); + + js = (JabberStream*)(gc->proto_data); + + if (!js || !js->server_caps & JABBER_CAP_GOOGLE_ROSTER) + return; + + buddies = gaim_find_buddies(js->gc->account, who); + if(!buddies) + return; + + b = buddies->data; + + iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster"); + + query = xmlnode_get_child(iq->node, "query"); + item = xmlnode_new_child(query, "item"); + + while(buddies) { + GaimGroup *g; + + b = buddies->data; + g = gaim_buddy_get_group(b); + + group = xmlnode_new_child(item, "group"); + xmlnode_insert_data(group, g->name, -1); + + buddies = buddies->next; + } + + iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster"); + + query = xmlnode_get_child(iq->node, "query"); + item = xmlnode_new_child(query, "item"); + + xmlnode_set_attrib(item, "jid", who); + xmlnode_set_attrib(item, "name", b->alias ? b->alias : ""); + xmlnode_set_attrib(query, "xmlns:gr", "google:roster"); + xmlnode_set_attrib(query, "gr:ext", "2"); + + jabber_iq_send(iq); + + /* See if he's online */ + jabber_presence_subscription_set(js, who, "probe"); +} Modified: trunk/libgaim/protocols/jabber/google.h =================================================================== --- trunk/libgaim/protocols/jabber/google.h 2006-12-14 04:17:02 UTC (rev 17992) +++ trunk/libgaim/protocols/jabber/google.h 2006-12-14 04:56:54 UTC (rev 17993) @@ -29,4 +29,12 @@ void jabber_gmail_init(JabberStream *js); void jabber_gmail_poke(JabberStream *js, xmlnode *node); +void jabber_google_roster_init(JabberStream *js); +void jabber_google_roster_outgoing(JabberStream *js, xmlnode *query, xmlnode *item); +void jabber_google_roster_incoming(JabberStream *js, xmlnode *item); +void jabber_google_roster_add_deny(GaimConnection *gc, const char *who); +void jabber_google_roster_rem_deny(GaimConnection *gc, const char *who); + + + #endif /* _GAIM_GOOGLE_H_ */ Modified: trunk/libgaim/protocols/jabber/jabber.c =================================================================== --- trunk/libgaim/protocols/jabber/jabber.c 2006-12-14 04:17:02 UTC (rev 17992) +++ trunk/libgaim/protocols/jabber/jabber.c 2006-12-14 04:56:54 UTC (rev 17993) @@ -41,6 +41,7 @@ #include "buddy.h" #include "chat.h" #include "disco.h" +#include "google.h" #include "iq.h" #include "jutil.h" #include "message.h" @@ -1041,7 +1042,6 @@ break; case JABBER_STREAM_CONNECTED: - jabber_roster_request(js); gpresence = gaim_account_get_presence(js->gc->account); status = gaim_presence_get_active_status(gpresence); jabber_presence_send(js->gc->account, status); @@ -1875,9 +1875,9 @@ jabber_roster_remove_buddy, /* remove_buddy */ NULL, /* remove_buddies */ NULL, /* add_permit */ - NULL, /* add_deny */ + jabber_google_roster_add_deny, /* add_deny */ NULL, /* rem_permit */ - NULL, /* rem_deny */ + jabber_google_roster_rem_deny, /* rem_deny */ NULL, /* set_permit_deny */ jabber_chat_join, /* join_chat */ NULL, /* reject_chat */ Modified: trunk/libgaim/protocols/jabber/jabber.h =================================================================== --- trunk/libgaim/protocols/jabber/jabber.h 2006-12-14 04:17:02 UTC (rev 17992) +++ trunk/libgaim/protocols/jabber/jabber.h 2006-12-14 04:56:54 UTC (rev 17993) @@ -55,6 +55,7 @@ * http://code.google.com/apis/talk/jep_extensions/extensions.html */ JABBER_CAP_GMAIL_NOTIFY = 1 << 9, + JABBER_CAP_GOOGLE_ROSTER = 1 << 10, JABBER_CAP_RETRIEVED = 1 << 31 } JabberCapabilities; Modified: trunk/libgaim/protocols/jabber/parser.c =================================================================== --- trunk/libgaim/protocols/jabber/parser.c 2006-12-14 04:17:02 UTC (rev 17992) +++ trunk/libgaim/protocols/jabber/parser.c 2006-12-14 04:56:54 UTC (rev 17993) @@ -76,13 +76,21 @@ char *txt; int attrib_len = attributes[i+4] - attributes[i+3]; char *attrib = g_malloc(attrib_len + 1); + char *attrib_ns = NULL; + + if (attributes[i+2]) { + attrib_ns = g_strdup(attributes[i+2]);; + } + memcpy(attrib, attributes[i+3], attrib_len); attrib[attrib_len] = '\0'; + txt = attrib; attrib = gaim_unescape_html(txt); g_free(txt); - xmlnode_set_attrib(node, (const char*) attributes[i], attrib); + xmlnode_set_attrib_with_namespace(node, (const char*) attributes[i], attrib_ns, attrib); g_free(attrib); + g_free(attrib_ns); } js->current = node; Modified: trunk/libgaim/protocols/jabber/roster.c =================================================================== --- trunk/libgaim/protocols/jabber/roster.c 2006-12-14 04:17:02 UTC (rev 17992) +++ trunk/libgaim/protocols/jabber/roster.c 2006-12-14 04:56:54 UTC (rev 17993) @@ -24,6 +24,7 @@ #include "util.h" #include "buddy.h" +#include "google.h" #include "presence.h" #include "roster.h" #include "iq.h" @@ -224,6 +225,8 @@ if (g_slist_find_custom(groups, group_name, (GCompareFunc)gaim_utf8_strcasecmp) == NULL) groups = g_slist_append(groups, group_name); } + if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER) + jabber_google_roster_incoming(js, item); add_gaim_buddies_in_groups(js, jid, name, groups); } } @@ -271,7 +274,12 @@ if(!grps) g_slist_free(groups); - + + if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER) { + jabber_google_roster_outgoing(js, query, item); + xmlnode_set_attrib(query, "xmlns:gr", "google:roster"); + xmlnode_set_attrib(query, "gr:ext", "2"); + } jabber_iq_send(iq); } Modified: trunk/libgaim/xmlnode.c =================================================================== --- trunk/libgaim/xmlnode.c 2006-12-14 04:17:02 UTC (rev 17992) +++ trunk/libgaim/xmlnode.c 2006-12-14 04:56:54 UTC (rev 17993) @@ -142,7 +142,35 @@ } } + void +xmlnode_remove_attrib_with_namespace(xmlnode *node, const char *attr, const char *xmlns) +{ + xmlnode *attr_node, *sibling = NULL; + + g_return_if_fail(node != NULL); + g_return_if_fail(attr != NULL); + + for(attr_node = node->child; attr_node; attr_node = attr_node->next) + { + if(attr_node->type == XMLNODE_TYPE_ATTRIB && + !strcmp(attr_node->name, attr) && + !strcmp(attr_node->xmlns, xmlns)) { + if(node->child == attr_node) { + node->child = attr_node->next; + } else if (node->lastchild == attr_node) { + node->lastchild = sibling; + } else { + sibling->next = attr_node->next; + } + xmlnode_free(attr_node); + return; + } + sibling = attr_node; + } +} + +void xmlnode_set_attrib(xmlnode *node, const char *attr, const char *value) { xmlnode *attrib_node; @@ -160,6 +188,25 @@ xmlnode_insert_child(node, attrib_node); } +void +xmlnode_set_attrib_with_namespace(xmlnode *node, const char *attr, const char *xmlns, const char *value) +{ + xmlnode *attrib_node; + + g_return_if_fail(node != NULL); + g_return_if_fail(attr != NULL); + g_return_if_fail(value != NULL); + + xmlnode_remove_attrib_with_namespace(node, attr, xmlns); + + attrib_node = new_node(attr, XMLNODE_TYPE_ATTRIB); + + attrib_node->data = g_strdup(value); + attrib_node->xmlns = g_strdup(xmlns); + + xmlnode_insert_child(node, attrib_node); +} + const char * xmlnode_get_attrib(xmlnode *node, const char *attr) { @@ -176,7 +223,24 @@ return NULL; } +const char * +xmlnode_get_attrib_with_namespace(xmlnode *node, const char *attr, const char *xmlns) +{ + xmlnode *x; + g_return_val_if_fail(node != NULL, NULL); + + for(x = node->child; x; x = x->next) { + if(x->type == XMLNODE_TYPE_ATTRIB && + !strcmp(attr, x->name) && !strcmp(x->xmlns, xmlns)) { + return x->data; + } + } + + return NULL; +} + + void xmlnode_set_namespace(xmlnode *node, const char *xmlns) { g_return_if_fail(node != NULL); Modified: trunk/libgaim/xmlnode.h =================================================================== --- trunk/libgaim/xmlnode.h 2006-12-14 04:17:02 UTC (rev 17992) +++ trunk/libgaim/xmlnode.h 2006-12-14 04:56:54 UTC (rev 17993) @@ -143,6 +143,16 @@ void xmlnode_set_attrib(xmlnode *node, const char *attr, const char *value); /** + * Sets a namespaced attribute for a node + * + * @param node The node to set an attribute for. + * @param attr The name of the attribute to set + * @param xmlns The namespace of the attribute to ste + * @param value The value of the attribute + */ +void xmlnode_set_attrib_with_namespace(xmlnode *node, const char *attr, const char *xmlns, const char *value); + +/** * Gets an attribute from a node. * * @param node The node to get an attribute from. @@ -153,6 +163,17 @@ const char *xmlnode_get_attrib(xmlnode *node, const char *attr); /** + * Gets a namespaced attribute from a node + * + * @param node The node to get an attribute from. + * @param attr The attribute to get + * @param xmlns The namespace of the attribute to get + * + * @return The value of the attribute/ + */ +const char *xmlnode_get_attrib_with_namespace(xmlnode *node, const char *attr, const char *xmlns); + +/** * Removes an attribute from a node. * * @param node The node to remove an attribute from. @@ -161,6 +182,15 @@ void xmlnode_remove_attrib(xmlnode *node, const char *attr); /** + * Removes a namespaced attribute from a node + * + * @param node The node to remove an attribute from + * @param attr The attribute to remove + * @param xmlns The namespace of the attribute to remove + */ +void xmlnode_remove_attrib_with_namespace(xmlnode *node, const char *attr, const char *xmlns); + +/** * Sets the namespace of a node * * @param node The node to qualify This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |