# HG changeset patch # User Nathan Walp # Date 1073699304 0 # Node ID 9a6df4d567e0bfd6eff45c7fc24406e4b0d5e7a4 # Parent 7fa6ddec6e30b07597a7d00d7c7c072d3a6f33bf [gaim-migrate @ 8727] I think I can sneak this stuff in here before we release committer: Tailor Script diff -r 7fa6ddec6e30 -r 9a6df4d567e0 src/protocols/jabber/chat.c --- a/src/protocols/jabber/chat.c Fri Jan 09 16:58:33 2004 +0000 +++ b/src/protocols/jabber/chat.c Sat Jan 10 01:48:24 2004 +0000 @@ -41,12 +41,10 @@ pce->identifier = "room"; m = g_list_append(m, pce); - /* we're gonna default to a conference server I know is true, until - * I can figure out how to disco for a chat server */ pce = g_new0(struct proto_chat_entry, 1); pce->label = _("_Server:"); pce->identifier = "server"; - pce->def = "conference.jabber.org"; + pce->def = js->chat_servers ? js->chat_servers->data : "conference.jabber.org"; m = g_list_append(m, pce); pce = g_new0(struct proto_chat_entry, 1); diff -r 7fa6ddec6e30 -r 9a6df4d567e0 src/protocols/jabber/iq.c --- a/src/protocols/jabber/iq.c Fri Jan 09 16:58:33 2004 +0000 +++ b/src/protocols/jabber/iq.c Sat Jan 10 01:48:24 2004 +0000 @@ -278,6 +278,7 @@ SUPPORT_FEATURE("http://jabber.org/protocol/si") SUPPORT_FEATURE("http://jabber.org/protocol/si/profile/file-transfer") */ + SUPPORT_FEATURE("http://jabber.org/protocol/xhtml-im") jabber_iq_send(iq); } else if(!strcmp(type, "result")) { @@ -294,24 +295,32 @@ jbr = jabber_buddy_find_resource(jb, jid->resource); jabber_id_free(jid); - if(!jbr) - return; - for(child = query->child; child; child = child->next) { if(child->type != NODE_TYPE_TAG) continue; - if(!strcmp(child->name, "feature")) { + if(!strcmp(child->name, "identity")) { + const char *category = xmlnode_get_attrib(child, "category"); + const char *type = xmlnode_get_attrib(child, "type"); + if(!category || !type) + continue; + + /* we found a groupchat or MUC server, add it to the list */ + /* XXX: actually check for protocol/muc or gc-1.0 support */ + if(!strcmp(category, "conference") && !strcmp(type, "text")) + js->chat_servers = g_list_append(js->chat_servers, g_strdup(from)); + + } else if(!strcmp(child->name, "feature")) { const char *var = xmlnode_get_attrib(child, "var"); if(!var) continue; - if(!strcmp(var, "http://jabber.org/protocol/si")) + if(jbr && !strcmp(var, "http://jabber.org/protocol/si")) jbr->capabilities |= JABBER_CAP_SI; - else if(!strcmp(var, + else if(jbr && !strcmp(var, "http://jabber.org/protocol/si/profile/file-transfer")) jbr->capabilities |= JABBER_CAP_SI_FILE_XFER; - else if(!strcmp(var, "http://jabber.org/protocol/bytestreams")) + else if(jbr && !strcmp(var, "http://jabber.org/protocol/bytestreams")) jbr->capabilities |= JABBER_CAP_BYTESTREAMS; } } @@ -333,6 +342,58 @@ } } +static void +jabber_iq_disco_server_result_cb(JabberStream *js, xmlnode *packet, gpointer data) +{ + xmlnode *query, *child; + const char *from = xmlnode_get_attrib(packet, "from"); + const char *type = xmlnode_get_attrib(packet, "type"); + + if(!from || !type) + return; + + if(strcmp(from, js->user->domain)) + return; + + if(strcmp(type, "result")) + return; + + while(js->chat_servers) { + g_free(js->chat_servers->data); + js->chat_servers = g_list_delete_link(js->chat_servers, js->chat_servers); + } + + query = xmlnode_get_child(packet, "query"); + + for(child = query->child; child; child = child->next) { + JabberIq *iq; + const char *jid; + + if(child->type != NODE_TYPE_TAG) + continue; + if(strcmp(child->name, "item")) + continue; + if(!(jid = xmlnode_get_attrib(child, "jid"))) + continue; + + iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#info"); + xmlnode_set_attrib(iq->node, "to", jid); + jabber_iq_send(iq); + } +} + +void jabber_iq_disco_server(JabberStream *js) +{ + JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_GET, + "http://jabber.org/protocol/disco#items"); + + xmlnode_set_attrib(iq->node, "to", js->user->domain); + + jabber_iq_set_callback(iq, jabber_iq_disco_server_result_cb, NULL); + jabber_iq_send(iq); +} + + void jabber_iq_parse(JabberStream *js, xmlnode *packet) { JabberCallbackData *jcd; @@ -341,50 +402,51 @@ const char *type, *id; query = xmlnode_get_child(packet, "query"); - - if(query) { - - xmlns = xmlnode_get_attrib(query, "xmlns"); - - if(!xmlns) - return; + type = xmlnode_get_attrib(packet, "type"); - if(!strcmp(xmlns, "jabber:iq:roster")) { - jabber_roster_parse(js, packet); - return; - } else if(!strcmp(xmlns, "jabber:iq:last")) { - jabber_iq_handle_last(js, packet); - return; - } else if(!strcmp(xmlns, "jabber:iq:time")) { - jabber_iq_handle_time(js, packet); - return; - } else if(!strcmp(xmlns, "jabber:iq:version")) { - jabber_iq_handle_version(js, packet); - return; - } else if(!strcmp(xmlns, "jabber:iq:register")) { - jabber_register_parse(js, packet); - return; - } else if(!strcmp(xmlns, "jabber:iq:oob")) { - jabber_oob_parse(js, packet); - return; - } else if(!strcmp(xmlns, "http://jabber.org/protocol/disco#info")) { - jabber_disco_info_parse(js, packet); - return; - } else if(!strcmp(xmlns, "http://jabber.org/protocol/disco#items")) { - jabber_disco_items_parse(js, packet); - return; + if(type && query && (xmlns = xmlnode_get_attrib(query, "xmlns"))) { + if(!strcmp(type, "set")) { + if(!strcmp(xmlns, "jabber:iq:roster")) { + jabber_roster_parse(js, packet); + return; + } else if(!strcmp(xmlns, "jabber:iq:oob")) { + jabber_oob_parse(js, packet); + return; + } + } else if(!strcmp(type, "get")) { + if(!strcmp(xmlns, "jabber:iq:last")) { + jabber_iq_handle_last(js, packet); + return; + } else if(!strcmp(xmlns, "jabber:iq:time")) { + jabber_iq_handle_time(js, packet); + return; + } else if(!strcmp(xmlns, "jabber:iq:version")) { + jabber_iq_handle_version(js, packet); + return; + } else if(!strcmp(xmlns, "http://jabber.org/protocol/disco#info")) { + jabber_disco_info_parse(js, packet); + return; + } else if(!strcmp(xmlns, "http://jabber.org/protocol/disco#items")) { + jabber_disco_items_parse(js, packet); + return; + } + } else if(!strcmp(type, "result")) { + if(!strcmp(xmlns, "jabber:iq:roster")) { + jabber_roster_parse(js, packet); + return; + } else if(!strcmp(xmlns, "jabber:iq:register")) { + jabber_register_parse(js, packet); + return; + } else if(!strcmp(xmlns, "http://jabber.org/protocol/disco#info")) { + jabber_disco_info_parse(js, packet); + return; + } } - /* - } else if(xmlnode_get_child(packet, "si")) { - jabber_si_parse(js, packet); - return; - */ } /* If we got here, no pre-defined handlers got it, lets see if a special * callback got registered */ - type = xmlnode_get_attrib(packet, "type"); id = xmlnode_get_attrib(packet, "id"); if(type && (!strcmp(type, "result") || !strcmp(type, "error")) && id diff -r 7fa6ddec6e30 -r 9a6df4d567e0 src/protocols/jabber/jabber.c --- a/src/protocols/jabber/jabber.c Fri Jan 09 16:58:33 2004 +0000 +++ b/src/protocols/jabber/jabber.c Sat Jan 10 01:48:24 2004 +0000 @@ -380,6 +380,7 @@ g_free, (GDestroyNotify)jabber_buddy_free); js->chats = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + js->chat_servers = g_list_append(NULL, g_strdup("conference.jabber.org")); js->user = jabber_id_new(gaim_account_get_username(account)); js->next_id = g_random_int(); @@ -777,6 +778,10 @@ g_hash_table_destroy(js->buddies); if(js->chats) g_hash_table_destroy(js->chats); + while(js->chat_servers) { + g_free(js->chat_servers->data); + js->chat_servers = g_list_delete_link(js->chat_servers, js->chat_servers); + } if(js->stream_id) g_free(js->stream_id); if(js->user) @@ -784,15 +789,6 @@ g_free(js); } -static void jabber_server_probe(JabberStream *js) -{ - JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_GET, - "http://jabber.org/protocol/disco#items"); - - xmlnode_set_attrib(iq->node, "to", js->user->domain); - jabber_iq_send(iq); -} - void jabber_stream_set_state(JabberStream *js, JabberStreamState state) { js->state = state; @@ -828,7 +824,7 @@ gaim_connection_set_state(js->gc, GAIM_CONNECTED); jabber_roster_request(js); jabber_presence_send(js->gc, js->gc->away_state, js->gc->away); - jabber_server_probe(js); + jabber_iq_disco_server(js); serv_finish_login(js->gc); break; } diff -r 7fa6ddec6e30 -r 9a6df4d567e0 src/protocols/jabber/jabber.h --- a/src/protocols/jabber/jabber.h Fri Jan 09 16:58:33 2004 +0000 +++ b/src/protocols/jabber/jabber.h Sat Jan 10 01:48:24 2004 +0000 @@ -64,6 +64,7 @@ gboolean roster_parsed; GHashTable *chats; + GList *chat_servers; GHashTable *callbacks; int next_id; @@ -91,4 +92,6 @@ char *jabber_get_next_id(JabberStream *js); +void jabber_iq_disco_server(JabberStream *js); + #endif /* _GAIM_JABBER_H_ */ diff -r 7fa6ddec6e30 -r 9a6df4d567e0 src/protocols/jabber/jutil.c --- a/src/protocols/jabber/jutil.c Fri Jan 09 16:58:33 2004 +0000 +++ b/src/protocols/jabber/jutil.c Sat Jan 10 01:48:24 2004 +0000 @@ -20,6 +20,7 @@ */ #include "internal.h" #include "server.h" +#include "util.h" #include "chat.h" #include "presence.h" @@ -300,3 +301,21 @@ return buf; } +GaimConversation * +jabber_find_unnormalized_conv(const char *name, GaimAccount *account) +{ + GaimConversation *c = NULL; + GList *cnv; + + g_return_val_if_fail(name != NULL, NULL); + + for(cnv = gaim_get_conversations(); cnv; cnv = cnv->next) { + c = (GaimConversation*)cnv->data; + if(gaim_conversation_get_type(c) == GAIM_CONV_IM && + !gaim_utf8_strcasecmp(name, gaim_conversation_get_name(c)) && + account == gaim_conversation_get_account(c)) + return c; + } + + return NULL; +} diff -r 7fa6ddec6e30 -r 9a6df4d567e0 src/protocols/jabber/jutil.h --- a/src/protocols/jabber/jutil.h Fri Jan 09 16:58:33 2004 +0000 +++ b/src/protocols/jabber/jutil.h Sat Jan 10 01:48:24 2004 +0000 @@ -23,6 +23,7 @@ #define _GAIM_JABBER_JUTIL_H_ #include "account.h" +#include "conversation.h" typedef struct _JabberID { @@ -46,4 +47,6 @@ gboolean jabber_nameprep_validate(const char *); gboolean jabber_resourceprep_validate(const char *); +GaimConversation *jabber_find_unnormalized_conv(const char *name, GaimAccount *account); + #endif /* _GAIM_JABBER_JUTIL_H_ */ diff -r 7fa6ddec6e30 -r 9a6df4d567e0 src/protocols/jabber/message.c --- a/src/protocols/jabber/message.c Fri Jan 09 16:58:33 2004 +0000 +++ b/src/protocols/jabber/message.c Sat Jan 10 01:48:24 2004 +0000 @@ -52,25 +52,6 @@ g_free(jm); } -static GaimConversation * -find_unnormalized_im(const char *name, GaimAccount *account) -{ - GaimConversation *c = NULL; - GList *cnv; - - g_return_val_if_fail(name != NULL, NULL); - - for(cnv = gaim_get_conversations(); cnv; cnv = cnv->next) { - c = (GaimConversation*)cnv->data; - if(gaim_conversation_get_type(c) == GAIM_CONV_IM && - !gaim_utf8_strcasecmp(name, gaim_conversation_get_name(c)) && - account == gaim_conversation_get_account(c)) - return c; - } - - return NULL; -} - static void handle_chat(JabberMessage *jm) { JabberID *jid = jabber_id_new(jm->from); @@ -85,13 +66,13 @@ jb = jabber_buddy_find(jm->js, jm->from, TRUE); jbr = jabber_buddy_find_resource(jb, jid->resource); - if(find_unnormalized_im(jm->from, jm->js->gc->account)) { + if(jabber_find_unnormalized_conv(jm->from, jm->js->gc->account)) { from = g_strdup(jm->from); } else if(jid->node) { GaimConversation *conv; from = g_strdup_printf("%s@%s", jid->node, jid->domain); - conv = find_unnormalized_im(from, jm->js->gc->account); + conv = jabber_find_unnormalized_conv(from, jm->js->gc->account); if(conv) gaim_conversation_set_name(conv, jm->from); g_free(from); @@ -491,6 +472,9 @@ js = gc->proto_data; chat = jabber_chat_find_by_id(js, id); + if(!chat) + return 0; + if(!strcmp(msg, "/configure") || !strcmp(msg, "/config")) { jabber_chat_request_room_configure(chat); return 1; @@ -507,8 +491,6 @@ } else if(!strncmp(msg, "/part", 5)) { jabber_chat_part(chat, strlen(msg) > 6 ? msg+6 : NULL); return 1; - } else if(!strncmp(msg, "/ban", 4)) { - } else if(!strncmp(msg, "/kick", 5)) { } jm = g_new0(JabberMessage, 1); diff -r 7fa6ddec6e30 -r 9a6df4d567e0 src/protocols/jabber/presence.c --- a/src/protocols/jabber/presence.c Fri Jan 09 16:58:33 2004 +0000 +++ b/src/protocols/jabber/presence.c Sat Jan 10 01:48:24 2004 +0000 @@ -153,9 +153,11 @@ xmlnode *y; gboolean muc = FALSE; - jb = jabber_buddy_find(js, from, TRUE); - if(!jb) + if(!(jb = jabber_buddy_find(js, from, TRUE))) + return; + + if(!(jid = jabber_id_new(from))) return; if(jb->error_msg) { @@ -188,9 +190,11 @@ _("Authorize"), G_CALLBACK(authorize_add_cb), _("Deny"), G_CALLBACK(deny_add_cb)); g_free(msg); + jabber_id_free(jid); return; } else if(type && !strcmp(type, "subscribed")) { /* we've been allowed to see their presence, but we don't care */ + jabber_id_free(jid); return; } else { if((y = xmlnode_get_child(packet, "show"))) { @@ -212,8 +216,6 @@ } } - if(!(jid = jabber_id_new(from))) - return; for(y = packet->child; y; y = y->next) { if(y->type != NODE_TYPE_TAG) @@ -377,7 +379,12 @@ if(state == JABBER_STATE_ERROR || (type && (!strcmp(type, "unavailable") || !strcmp(type, "unsubscribed")))) { + GaimConversation *conv; + jabber_buddy_remove_resource(jb, jid->resource); + if((conv = jabber_find_unnormalized_conv(from, js->gc->account))) + gaim_conversation_set_name(conv, buddy_name); + } else { jabber_buddy_track_resource(jb, jid->resource, priority, state, status);