# HG changeset patch # User John Bailey # Date 1255377340 0 # Node ID 791281a6e21d123aa62b3c2afd478ecfeff3f86d # Parent 4558a09a08c730540388768c3939363cb47a2aa4# Parent 3fec904938a22de8ad93d6f0e2c668de74a30c13 propagate from branch 'im.pidgin.pidgin' (head 80eaa62b397424cadf9ea37ca0e98894f823fbf5) to branch 'im.pidgin.pidgin.next.minor' (head 6f6dd5699adbee9e318ef6affef1420796cef69f) diff -r 4558a09a08c7 -r 791281a6e21d ChangeLog --- a/ChangeLog Mon Oct 12 18:52:27 2009 +0000 +++ b/ChangeLog Mon Oct 12 19:55:40 2009 +0000 @@ -14,7 +14,19 @@ Information" dialog accessible on the Help menu. 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. + + MSN: + * Don't forget display names for buddies. + 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. @@ -27,14 +39,6 @@ * 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 URLs, e.g. URLs to open Inbox in Yahoo/MSN protocols, or the Yahoo diff -r 4558a09a08c7 -r 791281a6e21d libpurple/protocols/jabber/buddy.c --- a/libpurple/protocols/jabber/buddy.c Mon Oct 12 18:52:27 2009 +0000 +++ b/libpurple/protocols/jabber/buddy.c Mon Oct 12 19:55:40 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 4558a09a08c7 -r 791281a6e21d libpurple/protocols/jabber/chat.c --- a/libpurple/protocols/jabber/chat.c Mon Oct 12 18:52:27 2009 +0000 +++ b/libpurple/protocols/jabber/chat.c Mon Oct 12 19:55:40 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 4558a09a08c7 -r 791281a6e21d libpurple/protocols/jabber/chat.h --- a/libpurple/protocols/jabber/chat.h Mon Oct 12 18:52:27 2009 +0000 +++ b/libpurple/protocols/jabber/chat.h Mon Oct 12 19:55:40 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 4558a09a08c7 -r 791281a6e21d libpurple/protocols/jabber/google.c --- a/libpurple/protocols/jabber/google.c Mon Oct 12 18:52:27 2009 +0000 +++ b/libpurple/protocols/jabber/google.c Mon Oct 12 19:55:40 2009 +0000 @@ -31,6 +31,7 @@ #include "jabber.h" #include "presence.h" #include "iq.h" +#include "chat.h" #include "jingle/jingle.h" @@ -1425,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 4558a09a08c7 -r 791281a6e21d libpurple/protocols/jabber/google.h --- a/libpurple/protocols/jabber/google.h Mon Oct 12 18:52:27 2009 +0000 +++ b/libpurple/protocols/jabber/google.h Mon Oct 12 19:55:40 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_ */