Mercurial > pidgin.yaz
changeset 28751:bd8a1dad7f1c
merged with im.pidgin.pidgin
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Wed, 14 Oct 2009 13:26:08 +0900 |
parents | 659dde8c53a9 (current diff) 912b9999bbe6 (diff) |
children | 75aab8587e90 |
files | libpurple/protocols/jabber/google.c libpurple/protocols/jabber/jabber.c libpurple/protocols/yahoo/libymsg.c pidgin/gtkutils.c |
diffstat | 18 files changed, 665 insertions(+), 312 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Sun Oct 11 17:36:59 2009 +0900 +++ b/ChangeLog Wed Oct 14 13:26:08 2009 +0900 @@ -1,7 +1,17 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul version 2.6.3 (??/??/20??): + 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. + * Fix DNS TXT query resolution. + 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,13 +19,11 @@ Yahoo: * Fix sending /buzz. - - 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. + * 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) Finch: * The TinyURL plugin now creates shorter URLs for long non-conversation
--- a/libpurple/dnssrv.c Sun Oct 11 17:36:59 2009 +0900 +++ b/libpurple/dnssrv.c Wed Oct 14 13:26:08 2009 +0900 @@ -361,8 +361,12 @@ /* TODO: Check return value */ if (query.type == T_SRV) write(out, ret->data, sizeof(PurpleSrvResponse)); - if (query.type == T_TXT) - write(out, ret->data, sizeof(PurpleTxtResponse)); + if (query.type == T_TXT) { + PurpleTxtResponse *response = ret->data; + gsize l = strlen(response->content) + 1 /* null byte */; + write(out, &l, sizeof(l)); + write(out, response->content, l); + } g_free(ret->data); ret = g_list_remove(ret, ret->data); @@ -429,21 +433,38 @@ PurpleTxtCallback cb = query_data->cb.txt; ssize_t red; purple_debug_info("dnssrv","found %d TXT entries\n", size); - res = g_new0(PurpleTxtResponse, 1); for (i = 0; i < size; i++) { - red = read(source, res, sizeof(PurpleTxtResponse)); - if (red != sizeof(PurpleTxtResponse)) { + gsize len; + + red = read(source, &len, sizeof(len)); + if (red != sizeof(len)) { purple_debug_error("dnssrv","unable to read txt " - "response: %s\n", g_strerror(errno)); + "response length: %s\n", g_strerror(errno)); size = 0; - g_free(res); g_list_foreach(responses, (GFunc)purple_txt_response_destroy, NULL); g_list_free(responses); responses = NULL; break; } + + res = g_new0(PurpleTxtResponse, 1); + res->content = g_new0(gchar, len); + + red = read(source, res->content, len); + if (red != len) { + purple_debug_error("dnssrv","unable to read txt " + "response: %s\n", g_strerror(errno)); + size = 0; + purple_txt_response_destroy(res); + g_list_foreach(responses, (GFunc)purple_txt_response_destroy, NULL); + g_list_free(responses); + responses = NULL; + break; + } + responses = g_list_prepend(responses, res); } + responses = g_list_reverse(responses); cb(responses, query_data->extradata); } else { purple_debug_error("dnssrv", "type unknown of DNS result entry; errno is %i\n", errno); @@ -788,6 +809,7 @@ internal_query.type = T_TXT; strncpy(internal_query.query, query, 255); + internal_query.query[255] = '\0'; if (write(in[1], &internal_query, sizeof(internal_query)) < 0) purple_debug_error("dnssrv", "Could not write to TXT resolver\n");
--- a/libpurple/protocols/jabber/buddy.c Sun Oct 11 17:36:59 2009 +0900 +++ b/libpurple/protocols/jabber/buddy.c Wed Oct 14 13:26:08 2009 +0900 @@ -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 *
--- a/libpurple/protocols/jabber/chat.c Sun Oct 11 17:36:59 2009 +0900 +++ b/libpurple/protocols/jabber/chat.c Wed Oct 14 13:26:08 2009 +0900 @@ -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)
--- a/libpurple/protocols/jabber/chat.h Sun Oct 11 17:36:59 2009 +0900 +++ b/libpurple/protocols/jabber/chat.h Wed Oct 14 13:26:08 2009 +0900 @@ -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);
--- a/libpurple/protocols/jabber/google.c Sun Oct 11 17:36:59 2009 +0900 +++ b/libpurple/protocols/jabber/google.c Wed Oct 14 13:26:08 2009 +0900 @@ -32,6 +32,7 @@ #include "jabber.h" #include "presence.h" #include "iq.h" +#include "chat.h" #include "jingle/jingle.h" @@ -96,14 +97,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]; @@ -111,7 +112,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); @@ -169,6 +170,7 @@ jabber_iq_send(iq); } + purple_media_candidate_list_free(candidates); } static void @@ -1428,3 +1430,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); +}
--- a/libpurple/protocols/jabber/google.h Sun Oct 11 17:36:59 2009 +0900 +++ b/libpurple/protocols/jabber/google.h Wed Oct 14 13:26:08 2009 +0900 @@ -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_ */
--- a/libpurple/protocols/jabber/jabber.c Sun Oct 11 17:36:59 2009 +0900 +++ b/libpurple/protocols/jabber/jabber.c Wed Oct 14 13:26:08 2009 +0900 @@ -1081,39 +1081,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);
--- a/libpurple/protocols/msn/contact.c Sun Oct 11 17:36:59 2009 +0900 +++ b/libpurple/protocols/msn/contact.c Wed Oct 14 13:26:08 2009 +0900 @@ -356,9 +356,10 @@ char *type; char *member_id; MsnUser *user; - xmlnode *annotation; + xmlnode *annotation, *display; guint nid = MSN_NETWORK_UNKNOWN; char *invite = NULL; + char *display_text; passport = xmlnode_get_data(xmlnode_get_child(member, node)); if (!purple_email_is_valid(passport)) { @@ -368,7 +369,13 @@ type = xmlnode_get_data(xmlnode_get_child(member, "Type")); member_id = xmlnode_get_data(xmlnode_get_child(member, "MembershipId")); - user = msn_userlist_find_add_user(session->userlist, passport, NULL); + if ((display = xmlnode_get_child(member, "DisplayName"))) { + display_text = xmlnode_get_data(display); + } else { + display_text = NULL; + } + + user = msn_userlist_find_add_user(session->userlist, passport, display_text); for (annotation = xmlnode_get_child(member, "Annotations/Annotation"); annotation; @@ -409,6 +416,7 @@ g_free(type); g_free(member_id); g_free(invite); + g_free(display_text); } static void
--- a/libpurple/protocols/msn/nexus.c Sun Oct 11 17:36:59 2009 +0900 +++ b/libpurple/protocols/msn/nexus.c Wed Oct 14 13:26:08 2009 +0900 @@ -508,6 +508,7 @@ } g_free(ud); + g_free(key); } void
--- a/libpurple/protocols/msn/notification.c Sun Oct 11 17:36:59 2009 +0900 +++ b/libpurple/protocols/msn/notification.c Wed Oct 14 13:26:08 2009 +0900 @@ -963,7 +963,7 @@ if (cmd->trans->data) { MsnFqyCbData *fqy_data = cmd->trans->data; fqy_data->cb(session, passport, network, fqy_data->data); - /* Don't free fqy_data yet since the server responds to FQY multipe times. + /* Don't free fqy_data yet since the server responds to FQY multiple times. It will be freed when cmd->trans is freed. */ } @@ -1098,7 +1098,6 @@ } if (msn_user_set_friendly_name(user, friendly)) { - serv_got_alias(gc, passport, friendly); msn_update_contact(session, passport, MSN_UPDATE_DISPLAY, friendly); } g_free(friendly); @@ -1263,7 +1262,6 @@ if (msn_user_set_friendly_name(user, friendly)) { - serv_got_alias(gc, passport, friendly); msn_update_contact(session, passport, MSN_UPDATE_DISPLAY, friendly); }
--- a/libpurple/protocols/msn/servconn.c Sun Oct 11 17:36:59 2009 +0900 +++ b/libpurple/protocols/msn/servconn.c Wed Oct 14 13:26:08 2009 +0900 @@ -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; }
--- a/libpurple/protocols/msn/user.c Sun Oct 11 17:36:59 2009 +0900 +++ b/libpurple/protocols/msn/user.c Wed Oct 14 13:26:08 2009 +0900 @@ -183,12 +183,15 @@ { g_return_val_if_fail(user != NULL, FALSE); - if (user->friendly_name && name && !strcmp(user->friendly_name, name)) + if (user->friendly_name && name && (!strcmp(user->friendly_name, name) || + !strcmp(user->passport, name))) return FALSE; g_free(user->friendly_name); user->friendly_name = g_strdup(name); + serv_got_alias(purple_account_get_connection(user->userlist->session->account), + user->passport, name); return TRUE; }
--- a/libpurple/protocols/yahoo/libymsg.c Sun Oct 11 17:36:59 2009 +0900 +++ b/libpurple/protocols/yahoo/libymsg.c Wed Oct 14 13:26:08 2009 +0900 @@ -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, "<ding>")) { 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; @@ -2137,8 +2212,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; @@ -2154,9 +2228,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; } @@ -2168,20 +2240,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); @@ -2553,7 +2635,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 */ @@ -3594,8 +3676,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; } @@ -4265,11 +4348,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) { @@ -4287,7 +4370,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 */ @@ -4337,15 +4430,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"); @@ -4361,7 +4459,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) @@ -4386,13 +4484,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 */ } } @@ -4411,9 +4509,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; @@ -4421,7 +4531,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 */ @@ -4429,14 +4539,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); } @@ -4684,17 +4804,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) @@ -4704,37 +4836,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); @@ -4750,17 +4880,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))) { @@ -4771,20 +4900,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); } @@ -4792,7 +4930,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; @@ -4800,11 +4938,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"); @@ -4814,19 +4963,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"); @@ -4864,7 +5022,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, @@ -4873,8 +5030,7 @@ if (!f) return; - if(f->protocol == 2) { - msn = TRUE; + if(f->fed) { temp = who+4; } else temp = who; @@ -4892,9 +5048,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),
--- a/libpurple/protocols/yahoo/libymsg.h Sun Oct 11 17:36:59 2009 +0900 +++ b/libpurple/protocols/yahoo/libymsg.h Wed Oct 14 13:26:08 2009 +0900 @@ -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;
--- a/libpurple/protocols/yahoo/yahoo_friend.c Sun Oct 11 17:36:59 2009 +0900 +++ b/libpurple/protocols/yahoo/yahoo_friend.c Wed Oct 14 13:26:08 2009 +0900 @@ -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",
--- a/libpurple/protocols/yahoo/yahoo_friend.h Sun Oct 11 17:36:59 2009 +0900 +++ b/libpurple/protocols/yahoo/yahoo_friend.h Wed Oct 14 13:26:08 2009 +0900 @@ -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;
--- a/pidgin/gtkutils.c Sun Oct 11 17:36:59 2009 +0900 +++ b/pidgin/gtkutils.c Wed Oct 14 13:26:08 2009 +0900 @@ -3901,6 +3901,40 @@ return (gnome_url_handlers != NULL); } +#ifdef _WIN32 +static void +winpidgin_register_win32_url_handlers(void) +{ + int idx = 0; + LONG ret = ERROR_SUCCESS; + + do { + DWORD nameSize = 256; + char protocol[256]; + /* I don't think we need to worry about non-ASCII protocol names */ + ret = RegEnumKeyExA(HKEY_CLASSES_ROOT, idx++, protocol, &nameSize, + NULL, NULL, NULL, NULL); + if (ret == ERROR_SUCCESS) { + HKEY reg_key = NULL; + ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, protocol, 0, KEY_READ, ®_key); + if (ret == ERROR_SUCCESS) { + ret = RegQueryValueExA(reg_key, "URL Protocol", NULL, NULL, NULL, NULL); + if (ret == ERROR_SUCCESS) { + /* We still pass everything to the "http" "open" handler for security reasons */ + gtk_imhtml_class_register_protocol(protocol, url_clicked_cb, link_context_menu); + } + RegCloseKey(reg_key); + } + ret = ERROR_SUCCESS; + } + } while (ret == ERROR_SUCCESS); + + if (ret != ERROR_NO_MORE_ITEMS) + purple_debug_error("winpidgin", "Error iterating HKEY_CLASSES_ROOT subkeys: %ld\n", + ret); +} +#endif + void pidgin_utils_init(void) { gtk_imhtml_class_register_protocol("http://", url_clicked_cb, link_context_menu); @@ -3918,6 +3952,11 @@ /* If we're under GNOME, try registering the system URL handlers. */ if (purple_running_gnome()) register_gnome_url_handlers(); + +#ifdef _WIN32 + winpidgin_register_win32_url_handlers(); +#endif + } void pidgin_utils_uninit(void)