# HG changeset patch # User Elliott Sales de Andrade # Date 1255379030 0 # Node ID ff66496188e0d6917f49c9bfb0760e08c1f6484a # Parent 7f80b0fc825d842d2dee34fe314c25dd127365dc# Parent 63dc67b32577e806b8633f16568870d375a52edc merge of '899182ae412c1d58eab5efb5001e980fdfda4190' and '9afa0cfda64ff9907b43b21fe64f17f698d2aa0d' diff -r 7f80b0fc825d -r ff66496188e0 ChangeLog --- a/ChangeLog Sat Oct 10 04:24:35 2009 +0000 +++ b/ChangeLog Mon Oct 12 20:23:50 2009 +0000 @@ -2,6 +2,8 @@ version 2.6.3 (??/??/20??): XMPP: + * Users connecting to Google Talk now have an "Initiate Chat" context menu + option for their buddies. (Eion Robb) * Fix a crash when attempting to validate an invalid JID. * Resolve an issue when connecting to iChat Server when no resource is specified. @@ -9,12 +11,18 @@ Yahoo: * Fix sending /buzz. + * Fix blocking behavior for federated (MSN/OCS/Sametime) service users. + (Jason Cohen) + * Add support for adding OCS and Sametime buddies. OCS users are added + as "ocs/user@domain.tld" and Sametime users are added as + "ibm/sametime_id". (Jason Cohen) General: * New 'plugins' sub-command to 'debug' command (i.e. '/debug plugins') to announce the list of loaded plugins (in both Finch and Pidgin). * Fix a crash when performing DNS queries on Unixes that use the blocking DNS lookups. (Brian Lu) + * Fix building the GnuTLS plugin with older versions of GnuTLS. Finch: * The TinyURL plugin now creates shorter URLs for long non-conversation diff -r 7f80b0fc825d -r ff66496188e0 configure.ac --- a/configure.ac Sat Oct 10 04:24:35 2009 +0000 +++ b/configure.ac Mon Oct 12 20:23:50 2009 +0000 @@ -1773,6 +1773,23 @@ LIBS="$LIBS_save" fi +if test "x$enable_gnutls" = "xyes"; then + AC_MSG_CHECKING(for GNUTLS_CERT_INSECURE_ALGORITHM) + LIBS_save="$LIBS" + LIBS="$LIBS $GNUTLS_LIBS" + CPPFLAGS_save="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $GNUTLS_CFLAGS" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[unsigned int verify = GNUTLS_CERT_INSECURE_ALGORITHM;]])], + [AC_DEFINE([HAVE_GNUTLS_CERT_INSECURE_ALGORITHM], 1, + [Define if your gnutls has the GNUTLS_CERT_INSECURE_ALGORITHM flag]) + AC_MSG_RESULT(yes)], + [AC_MSG_RESULT(no)]) + CPPFLAGS="$CPPFLAGS_save" + LIBS="$LIBS_save" +fi + + AM_CONDITIONAL(USE_GNUTLS, test "x$enable_gnutls" = "xyes") diff -r 7f80b0fc825d -r ff66496188e0 libpurple/certificate.c --- a/libpurple/certificate.c Sat Oct 10 04:24:35 2009 +0000 +++ b/libpurple/certificate.c Mon Oct 12 20:23:50 2009 +0000 @@ -97,8 +97,8 @@ "automatically checked."); break; case PURPLE_CERTIFICATE_CA_UNKNOWN: - return _("The root certificate this one claims to be issued by is " - "unknown."); + return _("The certificate is not trusted because no certificate " + "that can verify it is currently trusted."); break; case PURPLE_CERTIFICATE_NOT_ACTIVATED: return _("The certificate is not valid yet."); diff -r 7f80b0fc825d -r ff66496188e0 libpurple/ft.c --- a/libpurple/ft.c Sat Oct 10 04:24:35 2009 +0000 +++ b/libpurple/ft.c Mon Oct 12 20:23:50 2009 +0000 @@ -1030,7 +1030,7 @@ * watcher. */ if (xfer->watcher != 0) { - purple_timeout_remove(xfer->watcher); + purple_input_remove(xfer->watcher); xfer->watcher = 0; } diff -r 7f80b0fc825d -r ff66496188e0 libpurple/plugins/ssl/ssl-gnutls.c --- a/libpurple/plugins/ssl/ssl-gnutls.c Sat Oct 10 04:24:35 2009 +0000 +++ b/libpurple/plugins/ssl/ssl-gnutls.c Mon Oct 12 20:23:50 2009 +0000 @@ -698,9 +698,8 @@ crt_issuer_id = purple_certificate_get_issuer_unique_id(crt); purple_debug_info("gnutls/x509", - "Certificate for %s claims to be " - "issued by %s, but the certificate " - "for %s does not match.\n", + "Certificate %s is issued by " + "%s, which does not match %s.\n", crt_id ? crt_id : "(null)", crt_issuer_id ? crt_issuer_id : "(null)", issuer_id ? issuer_id : "(null)"); @@ -730,6 +729,7 @@ return FALSE; } +#ifdef HAVE_GNUTLS_CERT_INSECURE_ALGORITHM if (verify & GNUTLS_CERT_INSECURE_ALGORITHM) { /* * A certificate in the chain is signed with an insecure @@ -743,6 +743,7 @@ "Insecure hash algorithm used by %s to sign %s\n", issuer_id, crt_id); } +#endif if (verify & GNUTLS_CERT_INVALID) { /* Signature didn't check out, but at least diff -r 7f80b0fc825d -r ff66496188e0 libpurple/protocols/jabber/buddy.c --- a/libpurple/protocols/jabber/buddy.c Sat Oct 10 04:24:35 2009 +0000 +++ b/libpurple/protocols/jabber/buddy.c Mon Oct 12 20:23:50 2009 +0000 @@ -38,6 +38,7 @@ #include "xdata.h" #include "pep.h" #include "adhoccommands.h" +#include "google.h" typedef struct { long idle_seconds; @@ -1842,6 +1843,13 @@ m = g_list_append(m, act); } + if (js->googletalk) { + act = purple_menu_action_new(_("Initiate _Chat"), + PURPLE_CALLBACK(google_buddy_node_chat), + NULL, NULL); + m = g_list_append(m, act); + } + /* * This if-condition implements parts of XEP-0100: Gateway Interaction * diff -r 7f80b0fc825d -r ff66496188e0 libpurple/protocols/jabber/chat.c --- a/libpurple/protocols/jabber/chat.c Sat Oct 10 04:24:35 2009 +0000 +++ b/libpurple/protocols/jabber/chat.c Mon Oct 12 20:23:50 2009 +0000 @@ -209,19 +209,96 @@ g_hash_table_insert(hash_table, g_strdup(key), g_strdup(value)); } -void jabber_chat_join(PurpleConnection *gc, GHashTable *data) +static JabberChat *jabber_chat_new(JabberStream *js, const char *room, + const char *server, const char *handle, + const char *password, GHashTable *data) { JabberChat *chat; - char *room, *server, *handle, *passwd; + char *jid; + + g_return_val_if_fail(jabber_chat_find(js, room, server) == NULL, NULL); + + chat = g_new0(JabberChat, 1); + chat->js = js; + + chat->room = g_strdup(room); + chat->server = g_strdup(server); + chat->handle = g_strdup(handle); + + /* Copy the data hash table to chat->components */ + chat->components = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_free); + if (data == NULL) { + g_hash_table_insert(chat->components, g_strdup("handle"), g_strdup(handle)); + g_hash_table_insert(chat->components, g_strdup("room"), g_strdup(room)); + g_hash_table_insert(chat->components, g_strdup("server"), g_strdup(server)); + /* g_hash_table_insert(chat->components, g_strdup("password"), g_strdup(server)); */ + } else { + g_hash_table_foreach(data, insert_in_hash_table, chat->components); + } + + chat->members = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, + (GDestroyNotify)jabber_chat_member_free); + + jid = g_strdup_printf("%s@%s", room, server); + g_hash_table_insert(js->chats, jid, chat); + + return chat; +} + +JabberChat *jabber_join_chat(JabberStream *js, const char *room, + const char *server, const char *handle, + const char *password, GHashTable *data) +{ + JabberChat *chat; + + PurpleConnection *gc; + PurpleAccount *account; + PurpleStatus *status; + xmlnode *presence, *x; - char *tmp, *room_jid, *full_jid; - JabberStream *js = gc->proto_data; - PurplePresence *gpresence; - PurpleStatus *status; JabberBuddyState state; char *msg; int priority; + char *jid; + + chat = jabber_chat_new(js, room, server, handle, password, data); + g_return_val_if_fail(chat != NULL, NULL); + + gc = js->gc; + account = purple_connection_get_account(gc); + status = purple_account_get_active_status(account); + purple_status_to_jabber(status, &state, &msg, &priority); + + presence = jabber_presence_create_js(js, state, msg, priority); + g_free(msg); + + jid = g_strdup_printf("%s@%s/%s", room, server, handle); + xmlnode_set_attrib(presence, "to", jid); + g_free(jid); + + x = xmlnode_new_child(presence, "x"); + xmlnode_set_namespace(x, "http://jabber.org/protocol/muc"); + + if (password && *password) { + xmlnode *p = xmlnode_new_child(x, "password"); + xmlnode_insert_data(p, password, -1); + } + + jabber_send(js, presence); + xmlnode_free(presence); + + return chat; +} + +void jabber_chat_join(PurpleConnection *gc, GHashTable *data) +{ + char *room, *server, *handle, *passwd; + JabberID *jid; + JabberStream *js = gc->proto_data; + char *tmp; + room = g_hash_table_lookup(data, "room"); server = g_hash_table_lookup(data, "server"); handle = g_hash_table_lookup(data, "handle"); @@ -256,51 +333,23 @@ return; } - if(jabber_chat_find(js, room, server)) - return; - + /* Normalize the room and server parameters */ tmp = g_strdup_printf("%s@%s", room, server); - room_jid = g_strdup(jabber_normalize(NULL, tmp)); + jid = jabber_id_new(tmp); g_free(tmp); - chat = g_new0(JabberChat, 1); - chat->js = gc->proto_data; - - chat->room = g_strdup(room); - chat->server = g_strdup(server); - chat->handle = g_strdup(handle); - - /* Copy the data hash table to chat->components */ - chat->components = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, g_free); - g_hash_table_foreach(data, insert_in_hash_table, chat->components); - - chat->members = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, - (GDestroyNotify)jabber_chat_member_free); - - g_hash_table_insert(js->chats, room_jid, chat); + if (jid == NULL) { + /* TODO: Error message */ - gpresence = purple_account_get_presence(gc->account); - status = purple_presence_get_active_status(gpresence); - - purple_status_to_jabber(status, &state, &msg, &priority); - - presence = jabber_presence_create_js(js, state, msg, priority); - full_jid = g_strdup_printf("%s/%s", room_jid, handle); - xmlnode_set_attrib(presence, "to", full_jid); - g_free(full_jid); - g_free(msg); - - x = xmlnode_new_child(presence, "x"); - xmlnode_set_namespace(x, "http://jabber.org/protocol/muc"); - - if(passwd && *passwd) { - xmlnode *password = xmlnode_new_child(x, "password"); - xmlnode_insert_data(password, passwd, -1); + g_return_if_reached(); } - jabber_send(js, presence); - xmlnode_free(presence); + /* + * Now that we've done all that nice core-interface stuff, let's join + * this room! + */ + jabber_join_chat(js, jid->node, jid->domain, handle, passwd, data); + jabber_id_free(jid); } void jabber_chat_leave(PurpleConnection *gc, int id) diff -r 7f80b0fc825d -r ff66496188e0 libpurple/protocols/jabber/chat.h --- a/libpurple/protocols/jabber/chat.h Sat Oct 10 04:24:35 2009 +0000 +++ b/libpurple/protocols/jabber/chat.h Mon Oct 12 20:23:50 2009 +0000 @@ -57,6 +57,19 @@ GList *jabber_chat_info(PurpleConnection *gc); GHashTable *jabber_chat_info_defaults(PurpleConnection *gc, const char *chat_name); char *jabber_get_chat_name(GHashTable *data); + +/** + * in-prpl function for joining a chat room. Doesn't require sticking goop + * into a hash table. + * + * @param password The password (if required) to join the room. May be NULL. + * @param data The chat hash table. May be NULL (it will be generated + * for current core<>prpl API interface.) + */ +JabberChat *jabber_join_chat(JabberStream *js, const char *room, + const char *server, const char *handle, + const char *password, GHashTable *data); + void jabber_chat_join(PurpleConnection *gc, GHashTable *data); JabberChat *jabber_chat_find(JabberStream *js, const char *room, const char *server); diff -r 7f80b0fc825d -r ff66496188e0 libpurple/protocols/jabber/google.c --- a/libpurple/protocols/jabber/google.c Sat Oct 10 04:24:35 2009 +0000 +++ b/libpurple/protocols/jabber/google.c Mon Oct 12 20:23:50 2009 +0000 @@ -31,6 +31,7 @@ #include "jabber.h" #include "presence.h" #include "iq.h" +#include "chat.h" #include "jingle/jingle.h" @@ -95,14 +96,14 @@ gchar *participant, GoogleSession *session) { GList *candidates = purple_media_get_local_candidates( - session->media, session_id, session->remote_jid); + session->media, session_id, session->remote_jid), *iter; PurpleMediaCandidate *transport; gboolean video = FALSE; if (!strcmp(session_id, "google-video")) video = TRUE; - for (;candidates;candidates = candidates->next) { + for (iter = candidates; iter; iter = iter->next) { JabberIq *iq; gchar *ip, *port, *username, *password; gchar pref[16]; @@ -110,7 +111,7 @@ xmlnode *sess; xmlnode *candidate; guint component_id; - transport = (PurpleMediaCandidate*)(candidates->data); + transport = PURPLE_MEDIA_CANDIDATE(iter->data); component_id = purple_media_candidate_get_component_id( transport); @@ -168,6 +169,7 @@ jabber_iq_send(iq); } + purple_media_candidate_list_free(candidates); } static void @@ -1424,3 +1426,43 @@ purple_debug_info("jabber", "sending google:jingleinfo query\n"); jabber_iq_send(jingle_info); } + +void google_buddy_node_chat(PurpleBlistNode *node, gpointer data) +{ + PurpleBuddy *buddy; + PurpleConnection *gc; + JabberStream *js; + JabberChat *chat; + gchar *room; + guint32 tmp, a, b; + + g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + + buddy = PURPLE_BUDDY(node); + gc = purple_account_get_connection(purple_buddy_get_account(buddy)); + g_return_if_fail(gc != NULL); + js = purple_connection_get_protocol_data(gc); + + /* Generate a version 4 UUID */ + tmp = g_random_int(); + a = 0x4000 | (tmp & 0xFFF); /* 0x4000 to 0x4FFF */ + tmp >>= 12; + b = ((1 << 3) << 12) | (tmp & 0x3FFF); /* 0x8000 to 0xBFFF */ + + tmp = g_random_int(); + room = g_strdup_printf("private-chat-%08x-%04x-%04x-%04x-%04x%08x", + g_random_int(), + tmp & 0xFFFF, + a, + b, + (tmp >> 16) & 0xFFFF, g_random_int()); + + chat = jabber_join_chat(js, room, GOOGLE_GROUPCHAT_SERVER, js->user->node, + NULL, NULL); + if (chat) { + chat->muc = TRUE; + jabber_chat_invite(gc, chat->id, "", buddy->name); + } + + g_free(room); +} diff -r 7f80b0fc825d -r ff66496188e0 libpurple/protocols/jabber/google.h --- a/libpurple/protocols/jabber/google.h Sat Oct 10 04:24:35 2009 +0000 +++ b/libpurple/protocols/jabber/google.h Mon Oct 12 20:23:50 2009 +0000 @@ -31,6 +31,8 @@ #define GOOGLE_VIDEO_CAP "http://www.google.com/xmpp/protocol/video/v1" #define GOOGLE_JINGLE_INFO_NAMESPACE "google:jingleinfo" +#define GOOGLE_GROUPCHAT_SERVER "groupchat.google.com" + void jabber_gmail_init(JabberStream *js); void jabber_gmail_poke(JabberStream *js, const char *from, JabberIqType type, const char *id, xmlnode *new_mail); @@ -59,4 +61,6 @@ xmlnode *child); void jabber_google_send_jingle_info(JabberStream *js); +void google_buddy_node_chat(PurpleBlistNode *node, gpointer data); + #endif /* PURPLE_JABBER_GOOGLE_H_ */ diff -r 7f80b0fc825d -r ff66496188e0 libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Sat Oct 10 04:24:35 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.c Mon Oct 12 20:23:50 2009 +0000 @@ -1079,39 +1079,19 @@ return; } } else { + const char *ids[] = {"username", "password", "name", "email", "nick", "first", + "last", "address", "city", "state", "zip", "phone", "url", "date", + NULL}; const char *value = purple_request_field_string_get_value(field); - - if(!strcmp(id, "username")) { - y = xmlnode_new_child(query, "username"); - } else if(!strcmp(id, "password")) { - y = xmlnode_new_child(query, "password"); - } else if(!strcmp(id, "name")) { - y = xmlnode_new_child(query, "name"); - } else if(!strcmp(id, "email")) { - y = xmlnode_new_child(query, "email"); - } else if(!strcmp(id, "nick")) { - y = xmlnode_new_child(query, "nick"); - } else if(!strcmp(id, "first")) { - y = xmlnode_new_child(query, "first"); - } else if(!strcmp(id, "last")) { - y = xmlnode_new_child(query, "last"); - } else if(!strcmp(id, "address")) { - y = xmlnode_new_child(query, "address"); - } else if(!strcmp(id, "city")) { - y = xmlnode_new_child(query, "city"); - } else if(!strcmp(id, "state")) { - y = xmlnode_new_child(query, "state"); - } else if(!strcmp(id, "zip")) { - y = xmlnode_new_child(query, "zip"); - } else if(!strcmp(id, "phone")) { - y = xmlnode_new_child(query, "phone"); - } else if(!strcmp(id, "url")) { - y = xmlnode_new_child(query, "url"); - } else if(!strcmp(id, "date")) { - y = xmlnode_new_child(query, "date"); - } else { + int i; + for (i = 0; ids[i]; i++) { + if (!strcmp(id, ids[i])) + break; + } + + if (!ids[i]) continue; - } + y = xmlnode_new_child(query, ids[i]); xmlnode_insert_data(y, value, -1); if(cbdata->js->registration && !strcmp(id, "username")) { g_free(cbdata->js->user->node); diff -r 7f80b0fc825d -r ff66496188e0 libpurple/protocols/msn/nexus.c --- a/libpurple/protocols/msn/nexus.c Sat Oct 10 04:24:35 2009 +0000 +++ b/libpurple/protocols/msn/nexus.c Mon Oct 12 20:23:50 2009 +0000 @@ -508,6 +508,7 @@ } g_free(ud); + g_free(key); } void diff -r 7f80b0fc825d -r ff66496188e0 libpurple/protocols/msn/servconn.c --- a/libpurple/protocols/msn/servconn.c Sat Oct 10 04:24:35 2009 +0000 +++ b/libpurple/protocols/msn/servconn.c Mon Oct 12 20:23:50 2009 +0000 @@ -299,8 +299,8 @@ static gboolean servconn_idle_timeout_cb(MsnServConn *servconn) { + servconn->timeout_handle = 0; msn_servconn_disconnect(servconn); - servconn->timeout_handle = 0; /* XXX: servconn may not be valid anymore */ return FALSE; } diff -r 7f80b0fc825d -r ff66496188e0 libpurple/protocols/yahoo/libymsg.c --- a/libpurple/protocols/yahoo/libymsg.c Sat Oct 10 04:24:35 2009 +0000 +++ b/libpurple/protocols/yahoo/libymsg.c Mon Oct 12 20:23:50 2009 +0000 @@ -153,7 +153,7 @@ char *name = NULL; gboolean unicode = FALSE; char *message = NULL; - char *msn_name = NULL; + YahooFederation fed = YAHOO_FEDERATION_NONE; if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) { if (!purple_account_get_remember_password(account)) @@ -184,27 +184,35 @@ f = NULL; if (pair->value && g_utf8_validate(pair->value, -1, NULL)) { GSList *tmplist; - int protocol = 0; name = pair->value; - /* Look ahead to see if we have the protocol info about the buddy */ + /* Look ahead to see if we have the federation info about the buddy */ for (tmplist = l->next; tmplist; tmplist = tmplist->next) { struct yahoo_pair *p = tmplist->data; if (p->key == 7) break; if (p->key == 241) { - if(strtol(p->value, NULL, 10) == 2) { - g_free(msn_name); - msn_name = g_strconcat("msn/", name, NULL); - name = msn_name; - protocol = 2; + fed = strtol(p->value, NULL, 10); + switch (fed) { + case YAHOO_FEDERATION_MSN: + name = g_strconcat("msn/", name, NULL); + break; + case YAHOO_FEDERATION_OCS: + name = g_strconcat("ocs/", name, NULL); + break; + case YAHOO_FEDERATION_IBM: + name = g_strconcat("ibm/", name, NULL); + break; + case YAHOO_FEDERATION_NONE: + default: + break; } break; } } f = yahoo_friend_find_or_new(gc, name); - f->protocol = protocol; + f->fed = fed; } break; case 10: /* state */ @@ -361,7 +369,7 @@ if(f && strtol(pair->value, NULL, 10)) f->version_id = strtol(pair->value, NULL, 10); break; - case 241: /* protocol buddy belongs to */ + case 241: /* Federated network buddy belongs to */ break; /* We process this when get '7' */ default: purple_debug_warning("yahoo", @@ -381,7 +389,7 @@ if (name) /* update the last buddy */ yahoo_update_status(gc, name, f); } - g_free(msn_name); + } static void yahoo_do_group_check(PurpleAccount *account, GHashTable *ht, const char *name, const char *group) @@ -488,13 +496,13 @@ PurpleAccount *account = purple_connection_get_account(gc); YahooData *yd = gc->proto_data; GHashTable *ht; - char *norm_bud; + char *norm_bud = NULL; char *temp = NULL; YahooFriend *f = NULL; /* It's your friends. They're going to want you to share your StarBursts. */ /* But what if you had no friends? */ PurpleBuddy *b; PurpleGroup *g; - int protocol = 0; + YahooFederation fed = YAHOO_FEDERATION_NONE; int stealth = 0; ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_slist_free); @@ -519,11 +527,20 @@ break; case 301: /* This is 319 before all s/n's in a group after the first. It is followed by an identical 300. */ if(temp != NULL) { - if(protocol == 2) - norm_bud = g_strconcat("msn/", temp, NULL); - else - norm_bud = g_strdup(temp); - + switch (fed) { + case YAHOO_FEDERATION_MSN: + norm_bud = g_strconcat("msn/", temp, NULL); + break; + case YAHOO_FEDERATION_OCS: + norm_bud = g_strconcat("ocs/", temp, NULL); + break; + case YAHOO_FEDERATION_IBM: + norm_bud = g_strconcat("ibm/", temp, NULL); + break; + case YAHOO_FEDERATION_NONE: + norm_bud = g_strdup(temp); + break; + } if (yd->current_list15_grp) { /* This buddy is in a group */ f = yahoo_friend_find_or_new(gc, norm_bud); @@ -536,15 +553,15 @@ purple_blist_add_buddy(b, NULL, g, NULL); } yahoo_do_group_check(account, ht, norm_bud, yd->current_list15_grp); - if(protocol != 0) { - f->protocol = protocol; - purple_debug_info("yahoo", "Setting protocol to %d\n", f->protocol); + if(fed) { + f->fed = fed; + purple_debug_info("yahoo", "Setting federation to %d\n", f->fed); } if(stealth == 2) f->presence = YAHOO_PRESENCE_PERM_OFFLINE; /* set p2p status not connected and no p2p packet sent */ - if(protocol == 0) { + if(fed == YAHOO_FEDERATION_NONE) { yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED); f->p2p_packet_sent = 0; } else @@ -556,8 +573,8 @@ } g_free(norm_bud); - - protocol = 0; + norm_bud=NULL; + fed = YAHOO_FEDERATION_NONE; stealth = 0; g_free(temp); temp = NULL; @@ -573,8 +590,8 @@ g_free(temp); temp = g_strdup(purple_normalize(account, pair->value)); break; - case 241: /* another protocol user */ - protocol = strtol(pair->value, NULL, 10); + case 241: /* user on federated network */ + fed = strtol(pair->value, NULL, 10); break; case 59: /* somebody told cookies come here too, but im not sure */ yahoo_process_cookie(yd, pair->value); @@ -766,7 +783,7 @@ GSList *l = pkt->hash; gint val_11 = 0; YahooData *yd = gc->proto_data; - gboolean msn = FALSE; + YahooFederation fed = YAHOO_FEDERATION_NONE; account = purple_connection_get_account(gc); @@ -783,8 +800,7 @@ if (pair->key == 11) val_11 = strtol(pair->value, NULL, 10); if (pair->key == 241) - if(strtol(pair->value, NULL, 10) == 2) - msn = TRUE; + fed = strtol(pair->value, NULL, 10); l = l->next; } @@ -802,20 +818,30 @@ if (!g_ascii_strncasecmp(msg, "TYPING", strlen("TYPING")) && (purple_privacy_check(account, from))) { - if(msn) { - char *msn_from = g_strconcat("msn/", from, NULL); - if (*stat == '1') - serv_got_typing(gc, msn_from, 0, PURPLE_TYPING); - else - serv_got_typing_stopped(gc, msn_from); - g_free(msn_from); + char *fed_from = from; + switch (fed) { + case YAHOO_FEDERATION_MSN: + fed_from = g_strconcat("msn/", from, NULL); + break; + case YAHOO_FEDERATION_OCS: + fed_from = g_strconcat("ocs/", from, NULL); + break; + case YAHOO_FEDERATION_IBM: + fed_from = g_strconcat("ibm/", from, NULL); + break; + case YAHOO_FEDERATION_NONE: + default: + break; } - else { - if (*stat == '1') - serv_got_typing(gc, from, 0, PURPLE_TYPING); - else - serv_got_typing_stopped(gc, from); - } + + if (*stat == '1') + serv_got_typing(gc, fed_from, 0, PURPLE_TYPING); + else + serv_got_typing_stopped(gc, fed_from); + + if (fed_from != from) + g_free(fed_from); + } else if (!g_ascii_strncasecmp(msg, "GAME", strlen("GAME"))) { PurpleBuddy *bud = purple_find_buddy(account, from); @@ -852,7 +878,7 @@ int buddy_icon; char *id; char *msg; - gboolean msn; + YahooFederation fed; }; static void yahoo_process_sms_message(PurpleConnection *gc, struct yahoo_packet *pkt) @@ -926,6 +952,7 @@ struct _yahoo_im *im = NULL; const char *imv = NULL; gint val_11 = 0; + char *fed_from = NULL; account = purple_connection_get_account(gc); @@ -936,9 +963,10 @@ if (pair->key == 4 || pair->key == 1) { im = g_new0(struct _yahoo_im, 1); list = g_slist_append(list, im); - im->from = pair->value; + im->from = fed_from = pair->value; im->time = time(NULL); im->utf8 = TRUE; + im->fed = YAHOO_FEDERATION_NONE; } if (im && pair->key == 5) im->active_id = pair->value; @@ -956,8 +984,23 @@ im->msg = pair->value; } if (im && pair->key == 241) { - if(strtol(pair->value, NULL, 10) == 2) - im->msn = TRUE; + im->fed = strtol(pair->value, NULL, 10); + switch (im->fed) { + case YAHOO_FEDERATION_MSN: + fed_from = g_strconcat("msn/",im->from, NULL); + break; + case YAHOO_FEDERATION_OCS: + fed_from = g_strconcat("ocs/",im->from, NULL); + break; + case YAHOO_FEDERATION_IBM: + fed_from = g_strconcat("ibm/",im->from, NULL); + break; + case YAHOO_FEDERATION_NONE: + default: + break; + } + purple_debug_info("yahoo", "Message from federated (%d) buddy %s.\n", im->fed, fed_from); + } /* peer session id */ if (pair->key == 11) { @@ -981,10 +1024,10 @@ /* disconnect the peer if connected through p2p and sends wrong value for session id */ if( (pkt_type == YAHOO_PKT_TYPE_P2P) && (val_11 != yd->session_id) ) { - purple_debug_warning("yahoo","p2p: %s sent us message with wrong session id. Disconnecting p2p connection to peer\n", im ? im->from : "(im was null)"); + purple_debug_warning("yahoo","p2p: %s sent us message with wrong session id. Disconnecting p2p connection to peer\n", im ? fed_from : "(im was null)"); /* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */ if (im) { - g_hash_table_remove(yd->peers, im->from); + g_hash_table_remove(yd->peers, fed_from); g_free(im); } return; @@ -992,6 +1035,7 @@ /* TODO: It seems that this check should be per IM, not global */ /* Check for the Doodle IMV */ + /* no doodle with federated buddies -- assumption??? */ if (im != NULL && imv!= NULL && im->from != NULL) { g_hash_table_replace(yd->imvironments, g_strdup(im->from), g_strdup(imv)); @@ -1026,17 +1070,15 @@ for (l = list; l; l = l->next) { YahooFriend *f; char *m, *m2; - char *msn_from = NULL; - const char *from; im = l->data; - if (!im->from || !im->msg) { + if (!fed_from || !im->msg) { g_free(im); continue; } - if (!purple_privacy_check(account, im->from)) { - purple_debug_info("yahoo", "Message from %s dropped.\n", im->from); + if (!purple_privacy_check(account, fed_from)) { + purple_debug_info("yahoo", "Message from %s dropped.\n", fed_from); return; } @@ -1071,34 +1113,25 @@ g_free(m); m = m2; purple_util_chrreplace(m, '\r', '\n'); - - if (im->msn) { - msn_from = g_strconcat("msn/", im->from, NULL); - from = msn_from; - } else { - from = im->from; - } - if (!strcmp(m, "")) { char *username; - username = g_markup_escape_text(from, -1); + username = g_markup_escape_text(fed_from, -1); purple_prpl_got_attention(gc, username, YAHOO_BUZZ); g_free(username); g_free(m); g_free(im); - g_free(msn_from); continue; } m2 = yahoo_codes_to_html(m); g_free(m); - serv_got_im(gc, from, m2, 0, im->time); + serv_got_im(gc, fed_from, m2, 0, im->time); g_free(m2); - /* laters : implement buddy icon for msn friends */ - if (!im->msn) { + /* Official clients don't share buddy images with federated buddies */ + if (im->fed == YAHOO_FEDERATION_NONE) { if ((f = yahoo_friend_find(gc, im->from)) && im->buddy_icon == 2) { if (yahoo_friend_get_buddy_icon_need_request(f)) { yahoo_send_picture_request(gc, im->from); @@ -1108,8 +1141,9 @@ } g_free(im); - g_free(msn_from); } + if (fed_from != im->from) + g_free(fed_from); g_slist_free(list); } @@ -1142,7 +1176,7 @@ PurpleConnection *gc; char *id; char *who; - int protocol; + YahooFederation fed; }; static void @@ -1153,16 +1187,24 @@ YahooData *yd = add_req->gc->proto_data; const char *who = add_req->who; - if (add_req->protocol == 2) + pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15, YAHOO_STATUS_AVAILABLE, yd->session_id); + if (add_req->fed) { who += 4; - - pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15, YAHOO_STATUS_AVAILABLE, yd->session_id); - yahoo_packet_hash(pkt, "ssiii", - 1, add_req->id, - 5, who, - 241, add_req->protocol, - 13, 1, - 334, 0); + yahoo_packet_hash(pkt, "ssiii", + 1, add_req->id, + 5, who, + 241, add_req->fed, + 13, 1, + 334, 0); + } + else { + yahoo_packet_hash(pkt, "ssii", + 1, add_req->id, + 5, who, + 13, 1, + 334, 0); + } + yahoo_packet_send_and_free(pkt, yd); g_free(add_req->id); @@ -1178,23 +1220,33 @@ char *encoded_msg = NULL; const char *who = add_req->who; - if (add_req->protocol == 2) - who += 4; /* Skip 'msn/' */ - if (msg && *msg) encoded_msg = yahoo_string_encode(add_req->gc, msg, NULL); pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15, YAHOO_STATUS_AVAILABLE, yd->session_id); - yahoo_packet_hash(pkt, "ssiiiis", - 1, add_req->id, - 5, who, - 241, add_req->protocol, - 13, 2, - 334, 0, - 97, 1, - 14, encoded_msg ? encoded_msg : ""); + if (add_req->fed) { + who += 4; /* Skip fed identifier (msn|ocs|ibm)/' */ + yahoo_packet_hash(pkt, "ssiiiis", + 1, add_req->id, + 5, who, + 241, add_req->fed, + 13, 2, + 334, 0, + 97, 1, + 14, encoded_msg ? encoded_msg : ""); + } + else { + yahoo_packet_hash(pkt, "ssiiis", + 1, add_req->id, + 5, who, + 13, 2, + 334, 0, + 97, 1, + 14, encoded_msg ? encoded_msg : ""); + } + yahoo_packet_send_and_free(pkt, yd); @@ -1249,8 +1301,7 @@ PurpleAccount *account; GSList *l = pkt->hash; const char *msg = NULL; - int protocol = 0; - + account = purple_connection_get_account(gc); /* Buddy authorized/declined our addition */ @@ -1258,6 +1309,7 @@ char *temp = NULL; char *who = NULL; int response = 0; + YahooFederation fed = YAHOO_FEDERATION_NONE; while (l) { struct yahoo_pair *pair = l->data; @@ -1273,16 +1325,27 @@ msg = pair->value; break; case 241: - protocol = strtol(pair->value, NULL, 10); + fed = strtol(pair->value, NULL, 10); break; } l = l->next; } - if(protocol == 0) - who = g_strdup(temp); - else if(protocol == 2) - who = g_strconcat("msn/", temp, NULL); + switch (fed) { + case YAHOO_FEDERATION_MSN: + who = g_strconcat("msn/", temp, NULL); + break; + case YAHOO_FEDERATION_OCS: + who = g_strconcat("ocs/", temp, NULL); + break; + case YAHOO_FEDERATION_IBM: + who = g_strconcat("ibm/", temp, NULL); + break; + case YAHOO_FEDERATION_NONE: + default: + who = g_strdup(temp); + break; + } if (response == 1) /* Authorized */ purple_debug_info("yahoo", "Received authorization from buddy '%s'.\n", who ? who : "(Unknown Buddy)"); @@ -1301,6 +1364,7 @@ add_req = g_new0(struct yahoo_add_request, 1); add_req->gc = gc; + add_req->fed = YAHOO_FEDERATION_NONE; while (l) { struct yahoo_pair *pair = l->data; @@ -1319,7 +1383,7 @@ firstname = pair->value; break; case 241: - add_req->protocol = strtol(pair->value, NULL, 10); + add_req->fed = strtol(pair->value, NULL, 10); break; case 254: lastname = pair->value; @@ -1328,10 +1392,21 @@ } l = l->next; } - if(add_req->protocol == 2) - add_req->who = g_strconcat("msn/", temp, NULL); - else - add_req->who = g_strdup(temp); + switch (add_req->fed) { + case YAHOO_FEDERATION_MSN: + add_req->who = g_strconcat("msn/", temp, NULL); + break; + case YAHOO_FEDERATION_OCS: + add_req->who = g_strconcat("ocs/", temp, NULL); + break; + case YAHOO_FEDERATION_IBM: + add_req->who = g_strconcat("ibm/", temp, NULL); + break; + case YAHOO_FEDERATION_NONE: + default: + add_req->who = g_strdup(temp); + break; + } if (add_req->id && add_req->who) { char *alias = NULL, *dec_msg = NULL; @@ -2131,8 +2206,7 @@ YahooFriend *f; GSList *l = pkt->hash; YahooData *yd = gc->proto_data; - int protocol = 0; - gboolean msn = FALSE; + YahooFederation fed = YAHOO_FEDERATION_NONE; while (l) { struct yahoo_pair *pair = l->data; @@ -2148,9 +2222,7 @@ group = pair->value; break; case 241: - protocol = strtol(pair->value, NULL, 10); - if(protocol == 2) - msn = TRUE; + fed = strtol(pair->value, NULL, 10); break; } @@ -2162,20 +2234,30 @@ if (!group) group = ""; - if(msn) - who = g_strconcat("msn/", temp, NULL); - else - who = g_strdup(temp); + switch (fed) { + case YAHOO_FEDERATION_MSN: + who = g_strconcat("msn/", temp, NULL); + break; + case YAHOO_FEDERATION_OCS: + who = g_strconcat("ocs/", temp, NULL); + break; + case YAHOO_FEDERATION_IBM: + who = g_strconcat("ibm/", temp, NULL); + break; + case YAHOO_FEDERATION_NONE: + default: + who = g_strdup(temp); + break; + } if (!err || (err == 2)) { /* 0 = ok, 2 = already on serv list */ f = yahoo_friend_find_or_new(gc, who); yahoo_update_status(gc, who, f); - if(protocol) - f->protocol = protocol; + f->fed = fed; if( !g_hash_table_lookup(yd->peers, who) ) { /* we are not connected as client, so set friend to not connected */ - if(msn) + if(fed) yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_DO_NOT_CONNECT); else { yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED); @@ -2547,7 +2629,7 @@ return; /* Dont send p2p packet to buddies of other protocols */ - if(f->protocol) + if(f->fed) return; /* Finally, don't try to connect to buddies not online or on sms */ @@ -3588,8 +3670,9 @@ if (purple_presence_is_online(presence)) { if (yahoo_friend_get_game(f)) return "game"; - if (f->protocol == 2) - return "msn"; + + if (f->fed) + return "external"; } return NULL; } @@ -4259,11 +4342,11 @@ gboolean utf8 = TRUE; PurpleWhiteboard *wb; int ret = 1; - YahooFriend *f = NULL; + const char *fed_who; gsize lenb = 0; glong lenc = 0; struct yahoo_p2p_data *p2p_data; - gboolean msn = FALSE; + YahooFederation fed = YAHOO_FEDERATION_NONE; msg2 = yahoo_string_encode(gc, msg, &utf8); if(msg2) { @@ -4281,7 +4364,17 @@ } } - msn = !g_ascii_strncasecmp(who, "msn/", 4); + if (who[3] == '/') { + if (!g_ascii_strncasecmp(who, "msn/", 4)) { + fed = YAHOO_FEDERATION_MSN; + } + else if (!g_ascii_strncasecmp(who, "ocs/", 4)) { + fed = YAHOO_FEDERATION_OCS; + } + else if (!g_ascii_strncasecmp(who, "ibm/", 4)) { + fed = YAHOO_FEDERATION_IBM; + } + } if (who[0] == '+') { /* we have an sms to be sent */ @@ -4331,15 +4424,20 @@ } pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, YAHOO_STATUS_OFFLINE, yd->session_id); - if(msn) { - yahoo_packet_hash(pkt, "ss", 1, purple_connection_get_display_name(gc), 5, who+4); - yahoo_packet_hash_int(pkt, 241, 2); + fed_who = who; + switch (fed) { + case YAHOO_FEDERATION_MSN: + case YAHOO_FEDERATION_OCS: + case YAHOO_FEDERATION_IBM: + fed_who += 4; + break; + case YAHOO_FEDERATION_NONE: + default: + break; } - else { - yahoo_packet_hash(pkt, "ss", 1, purple_connection_get_display_name(gc), 5, who); - if ((f = yahoo_friend_find(gc, who)) && f->protocol) - yahoo_packet_hash_int(pkt, 241, f->protocol); - } + yahoo_packet_hash(pkt, "ss", 1, purple_connection_get_display_name(gc), 5, fed_who); + if (fed) + yahoo_packet_hash_int(pkt, 241, fed); if (utf8) yahoo_packet_hash_str(pkt, 97, "1"); @@ -4355,7 +4453,7 @@ * just so that we don't inadvertantly reset their IMVironment back * to nothing. * - * If they have no set an IMVironment, then use the default. + * If they have not set an IMVironment, then use the default. */ wb = purple_whiteboard_get_session(gc->account, who); if (wb) @@ -4380,13 +4478,13 @@ /* We may need to not send any packets over 2000 bytes, but I'm not sure yet. */ if ((YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt)) <= 2000) { /* if p2p link exists, send through it. To-do: key 15, time value to be sent in case of p2p */ - if( (p2p_data = g_hash_table_lookup(yd->peers, who)) && !msn ) { + if( (p2p_data = g_hash_table_lookup(yd->peers, who)) && !fed) { yahoo_packet_hash_int(pkt, 11, p2p_data->session_id); yahoo_p2p_write_pkt(p2p_data->source, pkt); } else { yahoo_packet_send(pkt, yd); - if(!msn) + if(!fed) yahoo_send_p2p_pkt(gc, who, 0); /* send p2p packet, with val_13=0 */ } } @@ -4405,9 +4503,21 @@ { YahooData *yd = gc->proto_data; struct yahoo_p2p_data *p2p_data; - gboolean msn = !g_ascii_strncasecmp(who, "msn/", 4); + YahooFederation fed = YAHOO_FEDERATION_NONE; struct yahoo_packet *pkt = NULL; + if (who[3] == '/') { + if (!g_ascii_strncasecmp(who, "msn/", 4)) { + fed = YAHOO_FEDERATION_MSN; + } + else if (!g_ascii_strncasecmp(who, "ocs/", 4)) { + fed = YAHOO_FEDERATION_OCS; + } + else if (!g_ascii_strncasecmp(who, "ibm/", 4)) { + fed = YAHOO_FEDERATION_IBM; + } + } + /* Don't do anything if sms is being typed */ if( strncmp(who, "+", 1) == 0 ) return 0; @@ -4415,7 +4525,7 @@ pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YAHOO_STATUS_TYPING, yd->session_id); /* check to see if p2p link exists, send through it */ - if( (p2p_data = g_hash_table_lookup(yd->peers, who)) && !msn ) { + if( (p2p_data = g_hash_table_lookup(yd->peers, who)) && !fed) { yahoo_packet_hash(pkt, "sssssis", 49, "TYPING", 1, purple_connection_get_display_name(gc), 14, " ", 13, state == PURPLE_TYPING ? "1" : "0", 5, who, 11, p2p_data->session_id, 1002, "1"); /* To-do: key 15 to be sent in case of p2p */ @@ -4423,14 +4533,24 @@ yahoo_packet_free(pkt); } else { /* send through yahoo server */ - if(msn) - yahoo_packet_hash(pkt, "sssssss", 49, "TYPING", 1, purple_connection_get_display_name(gc), - 14, " ", 13, state == PURPLE_TYPING ? "1" : "0", - 5, who+4, 1002, "1", 241, "2"); - else - yahoo_packet_hash(pkt, "ssssss", 49, "TYPING", 1, purple_connection_get_display_name(gc), - 14, " ", 13, state == PURPLE_TYPING ? "1" : "0", - 5, who, 1002, "1"); + + const char *fed_who = who; + switch (fed) { + case YAHOO_FEDERATION_MSN: + case YAHOO_FEDERATION_OCS: + case YAHOO_FEDERATION_IBM: + fed_who += 4; + break; + case YAHOO_FEDERATION_NONE: + default: + break; + } + + yahoo_packet_hash(pkt, "ssssss", 49, "TYPING", 1, purple_connection_get_display_name(gc), + 14, " ", 13, state == PURPLE_TYPING ? "1" : "0", + 5, fed_who, 1002, "1"); + if (fed) + yahoo_packet_hash_int(pkt, 241, fed); yahoo_packet_send_and_free(pkt, yd); } @@ -4677,17 +4797,29 @@ char *group2; YahooFriend *f; const char *bname; - gboolean msn = FALSE; + const char *fed_bname; + YahooFederation fed = YAHOO_FEDERATION_NONE; if (!yd->logged_in) return; - bname = purple_buddy_get_name(buddy); + fed_bname = bname = purple_buddy_get_name(buddy); if (!purple_privacy_check(purple_connection_get_account(gc), bname)) return; f = yahoo_friend_find(gc, bname); - msn = !g_ascii_strncasecmp(bname, "msn/", 4); + if (bname[3] == '/') { + fed_bname += 4; + if (!g_ascii_strncasecmp(bname, "msn/", 4)) { + fed = YAHOO_FEDERATION_MSN; + } + else if (!g_ascii_strncasecmp(bname, "ocs/", 4)) { + fed = YAHOO_FEDERATION_OCS; + } + else if (!g_ascii_strncasecmp(bname, "ibm/", 4)) { + fed = YAHOO_FEDERATION_IBM; + } + } g = purple_buddy_get_group(buddy); if (g) @@ -4697,37 +4829,35 @@ group2 = yahoo_string_encode(gc, group, NULL); pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, yd->session_id); - if(msn) { - yahoo_packet_hash(pkt, "sssssssssss", - 14, "", - 65, group2, - 97, "1", - 1, purple_connection_get_display_name(gc), - 302, "319", - 300, "319", - 7, bname + 4, - 241, "2", - 334, "0", - 301, "319", - 303, "319" + if (fed) { + yahoo_packet_hash(pkt, "sssssssisss", + 14, "", + 65, group2, + 97, "1", + 1, purple_connection_get_display_name(gc), + 302, "319", + 300, "319", + 7, fed_bname, + 241, fed, + 334, "0", + 301, "319", + 303, "319" ); } - else { + else { yahoo_packet_hash(pkt, "ssssssssss", - 14, "", - 65, group2, - 97, "1", - 1, purple_connection_get_display_name(gc), - 302, "319", - 300, "319", - 7, bname, - 334, "0", - 301, "319", - 303, "319" + 14, "", + 65, group2, + 97, "1", + 1, purple_connection_get_display_name(gc), + 302, "319", + 300, "319", + 7, fed_bname, + 334, "0", + 301, "319", + 303, "319" ); } - if (f && f->protocol && !msn) - yahoo_packet_hash_int(pkt, 241, f->protocol); yahoo_packet_send_and_free(pkt, yd); g_free(group2); @@ -4743,17 +4873,16 @@ char *cg; const char *bname, *gname; YahooFriend *f = NULL; - gboolean msn = FALSE; + YahooFederation fed = YAHOO_FEDERATION_NONE; bname = purple_buddy_get_name(buddy); f = yahoo_friend_find(gc, bname); if (!f) return; + fed = f->fed; gname = purple_group_get_name(group); buddies = purple_find_buddies(purple_connection_get_account(gc), bname); - if(f->protocol == 2) - msn = TRUE; for (l = buddies; l; l = l->next) { g = purple_buddy_get_group(l->data); if (purple_utf8_strcasecmp(gname, purple_group_get_name(g))) { @@ -4764,20 +4893,29 @@ g_slist_free(buddies); - if (remove) + if (remove) { g_hash_table_remove(yd->friends, bname); + f = NULL; /* f no longer valid - Just making it clear */ + } cg = yahoo_string_encode(gc, gname, NULL); pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YAHOO_STATUS_AVAILABLE, yd->session_id); - if(msn) - yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), - 7, bname+4, 65, cg); - else - yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), + switch (fed) { + case YAHOO_FEDERATION_MSN: + case YAHOO_FEDERATION_OCS: + case YAHOO_FEDERATION_IBM: + bname += 4; + break; + case YAHOO_FEDERATION_NONE: + default: + break; + } + + yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), 7, bname, 65, cg); - if(f->protocol) - yahoo_packet_hash_int(pkt, 241, f->protocol); + if (fed) + yahoo_packet_hash_int(pkt, 241, fed); yahoo_packet_send_and_free(pkt, yd); g_free(cg); } @@ -4785,7 +4923,7 @@ void yahoo_add_deny(PurpleConnection *gc, const char *who) { YahooData *yd = (YahooData *)gc->proto_data; struct yahoo_packet *pkt; - gboolean msn = FALSE; + YahooFederation fed = YAHOO_FEDERATION_NONE; if (!yd->logged_in) return; @@ -4793,11 +4931,22 @@ if (!who || who[0] == '\0') return; - msn = !g_ascii_strncasecmp(who, "msn/", 4); + if (who[3] == '/') { + if (!g_ascii_strncasecmp(who, "msn/", 4)) { + fed = YAHOO_FEDERATION_MSN; + } + else if (!g_ascii_strncasecmp(who, "ocs/", 4)) { + fed = YAHOO_FEDERATION_OCS; + } + else if (!g_ascii_strncasecmp(who, "ibm/", 4)) { + fed = YAHOO_FEDERATION_IBM; + } + } + pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, YAHOO_STATUS_AVAILABLE, yd->session_id); - if(msn) - yahoo_packet_hash(pkt, "ssss", 1, purple_connection_get_display_name(gc), 7, who+4, 241, "2", 13, "1"); + if(fed) + yahoo_packet_hash(pkt, "ssis", 1, purple_connection_get_display_name(gc), 7, who+4, 241, fed, 13, "1"); else yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), 7, who, 13, "1"); @@ -4807,19 +4956,28 @@ void yahoo_rem_deny(PurpleConnection *gc, const char *who) { YahooData *yd = (YahooData *)gc->proto_data; struct yahoo_packet *pkt; - gboolean msn = FALSE; + YahooFederation fed = YAHOO_FEDERATION_NONE; if (!yd->logged_in) return; if (!who || who[0] == '\0') return; - - msn = !g_ascii_strncasecmp(who, "msn/", 4); + if (who[3] == '/') { + if (!g_ascii_strncasecmp(who, "msn/", 4)) { + fed = YAHOO_FEDERATION_MSN; + } + else if (!g_ascii_strncasecmp(who, "ocs/", 4)) { + fed = YAHOO_FEDERATION_OCS; + } + else if (!g_ascii_strncasecmp(who, "ibm/", 4)) { + fed = YAHOO_FEDERATION_IBM; + } + } pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, YAHOO_STATUS_AVAILABLE, yd->session_id); - if(msn) - yahoo_packet_hash(pkt, "ssss", 1, purple_connection_get_display_name(gc), 7, who+4, 241, "2", 13, "2"); + if(fed) + yahoo_packet_hash(pkt, "ssis", 1, purple_connection_get_display_name(gc), 7, who+4, 241, fed, 13, "2"); else yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), 7, who, 13, "2"); @@ -4857,7 +5015,6 @@ struct yahoo_packet *pkt; char *gpn, *gpo; YahooFriend *f = yahoo_friend_find(gc, who); - gboolean msn = FALSE; const char *temp = NULL; /* Step 0: If they aren't on the server list anyway, @@ -4866,8 +5023,7 @@ if (!f) return; - if(f->protocol == 2) { - msn = TRUE; + if(f->fed) { temp = who+4; } else temp = who; @@ -4885,9 +5041,9 @@ } pkt = yahoo_packet_new(YAHOO_SERVICE_CHGRP_15, YAHOO_STATUS_AVAILABLE, yd->session_id); - if(f->protocol) + if(f->fed) yahoo_packet_hash(pkt, "ssssissss", 1, purple_connection_get_display_name(gc), - 302, "240", 300, "240", 7, temp, 241, f->protocol, 224, gpo, 264, gpn, 301, + 302, "240", 300, "240", 7, temp, 241, f->fed, 224, gpo, 264, gpn, 301, "240", 303, "240"); else yahoo_packet_hash(pkt, "ssssssss", 1, purple_connection_get_display_name(gc), diff -r 7f80b0fc825d -r ff66496188e0 libpurple/protocols/yahoo/libymsg.h --- a/libpurple/protocols/yahoo/libymsg.h Sat Oct 10 04:24:35 2009 +0000 +++ b/libpurple/protocols/yahoo/libymsg.h Mon Oct 12 20:23:50 2009 +0000 @@ -128,6 +128,20 @@ YAHOO_STATUS_DISCONNECTED = 0xffffffff /* in ymsg 15. doesnt mean the normal sense of 'disconnected' */ }; +/* + * Yahoo federated networks. Key 241 in ymsg. + * If it doesn't exist, it is on Yahoo's netowrk. + * It if does exist, send to another IM network. + */ + +typedef enum { + YAHOO_FEDERATION_NONE = 0, /* No federation - Yahoo! network */ + YAHOO_FEDERATION_OCS = 1, /* LCS or OCS private networks */ + YAHOO_FEDERATION_MSN = 2, /* MSN or Windows Live network */ + YAHOO_FEDERATION_IBM = 9 /* IBM/Sametime network */ +} YahooFederation; + + struct yahoo_buddy_icon_upload_data { PurpleConnection *gc; GString *str; diff -r 7f80b0fc825d -r ff66496188e0 libpurple/protocols/yahoo/yahoo_friend.c --- a/libpurple/protocols/yahoo/yahoo_friend.c Sat Oct 10 04:24:35 2009 +0000 +++ b/libpurple/protocols/yahoo/yahoo_friend.c Mon Oct 12 20:23:50 2009 +0000 @@ -151,9 +151,8 @@ char *temp = NULL; char *who = NULL; int value = 0; - int protocol = 0; - gboolean msn = FALSE; - + YahooFederation fed = YAHOO_FEDERATION_NONE; + while (l) { struct yahoo_pair *pair = l->data; @@ -165,8 +164,7 @@ value = strtol(pair->value, NULL, 10); break; case 241: - protocol = strtol(pair->value, NULL, 10); - msn = TRUE; + fed = strtol(pair->value, NULL, 10); break; } @@ -177,12 +175,21 @@ purple_debug_error("yahoo", "Received unknown value for presence key: %d\n", value); return; } - - if(msn) - who = g_strconcat("msn/", temp, NULL); - else - who = g_strdup(temp); - + + switch (fed) { + case YAHOO_FEDERATION_MSN: + who = g_strconcat("msn/", temp, NULL); + break; + case YAHOO_FEDERATION_OCS: + who = g_strconcat("ocs/", temp, NULL); + break; + case YAHOO_FEDERATION_IBM: + who = g_strconcat("ibm/", temp, NULL); + break; + case YAHOO_FEDERATION_NONE: + who = g_strdup(temp); + break; + } g_return_if_fail(who != NULL); f = yahoo_friend_find(gc, who); @@ -228,12 +235,12 @@ f = yahoo_friend_find(gc, name); if (!f) return; - - if(f->protocol == 2) + + if(f->fed != YAHOO_FEDERATION_NONE) temp = name+4; else temp = name; - + /* No need to change the value if it is already correct */ if (f->presence == presence) { purple_debug_info("yahoo", "Not setting presence because there are no changes.\n"); @@ -258,12 +265,12 @@ if (f->presence == YAHOO_PRESENCE_PERM_OFFLINE) { pkt = yahoo_packet_new(YAHOO_SERVICE_PRESENCE_PERM, YAHOO_STATUS_AVAILABLE, yd->session_id); - if(f->protocol) + if(f->fed) yahoo_packet_hash(pkt, "ssssssiss", 1, purple_connection_get_display_name(gc), 31, "2", 13, "2", 302, "319", 300, "319", - 7, temp, 241, f->protocol, + 7, temp, 241, f->fed, 301, "319", 303, "319"); else yahoo_packet_hash(pkt, "ssssssss", @@ -285,12 +292,12 @@ pkt = yahoo_packet_new(service, YAHOO_STATUS_AVAILABLE, yd->session_id); - if(f->protocol) + if(f->fed) yahoo_packet_hash(pkt, "ssssssiss", 1, purple_connection_get_display_name(gc), 31, thirtyone, 13, thirteen, 302, "319", 300, "319", - 7, temp, 241, f->protocol, + 7, temp, 241, f->fed, 301, "319", 303, "319"); else yahoo_packet_hash(pkt, "ssssssss", diff -r 7f80b0fc825d -r ff66496188e0 libpurple/protocols/yahoo/yahoo_friend.h --- a/libpurple/protocols/yahoo/yahoo_friend.h Sat Oct 10 04:24:35 2009 +0000 +++ b/libpurple/protocols/yahoo/yahoo_friend.h Mon Oct 12 20:23:50 2009 +0000 @@ -41,6 +41,7 @@ YAHOO_P2PSTATUS_WE_ARE_CLIENT } YahooP2PStatus; + /* these are called friends instead of buddies mainly so I can use variables * named f and not confuse them with variables named b */ @@ -54,7 +55,7 @@ gchar *ip; gboolean bicon_sent_request; YahooPresenceVisibility presence; - int protocol; /* 1=LCS, 2=MSN*/ + YahooFederation fed; long int version_id; YahooPersonalDetails ypd; YahooP2PStatus p2p_status;