# HG changeset patch # User Andreas Monitzer # Date 1181092789 0 # Node ID 95affacf6f823bfa1fa7d327e801dc124686256c # Parent 6ab1089e210108b6318d949837d13f12f0ae1880 Added the ability to define extensions to caps diff -r 6ab1089e2101 -r 95affacf6f82 libpurple/protocols/jabber/buddy.c --- a/libpurple/protocols/jabber/buddy.c Wed Jun 06 00:04:29 2007 +0000 +++ b/libpurple/protocols/jabber/buddy.c Wed Jun 06 01:19:49 2007 +0000 @@ -1257,7 +1257,7 @@ status = purple_presence_get_active_status(gpresence); purple_status_to_jabber(status, &state, &msg, &priority); - presence = jabber_presence_create(state, msg, priority); + presence = jabber_presence_create_js(js, state, msg, priority); g_free(msg); diff -r 6ab1089e2101 -r 95affacf6f82 libpurple/protocols/jabber/chat.c --- a/libpurple/protocols/jabber/chat.c Wed Jun 06 00:04:29 2007 +0000 +++ b/libpurple/protocols/jabber/chat.c Wed Jun 06 01:19:49 2007 +0000 @@ -261,7 +261,7 @@ purple_status_to_jabber(status, &state, &msg, &priority); - presence = jabber_presence_create(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); @@ -634,7 +634,7 @@ purple_status_to_jabber(status, &state, &msg, &priority); - presence = jabber_presence_create(state, msg, priority); + presence = jabber_presence_create_js(chat->js, state, msg, priority); full_jid = g_strdup_printf("%s@%s/%s", chat->room, chat->server, nick); xmlnode_set_attrib(presence, "to", full_jid); g_free(full_jid); diff -r 6ab1089e2101 -r 95affacf6f82 libpurple/protocols/jabber/disco.c --- a/libpurple/protocols/jabber/disco.c Wed Jun 06 00:04:29 2007 +0000 +++ b/libpurple/protocols/jabber/disco.c Wed Jun 06 01:19:49 2007 +0000 @@ -73,7 +73,6 @@ xmlnode_set_attrib(query, "node", node); if(!node || !strcmp(node, CAPS0115_NODE "#" VERSION)) { - identity = xmlnode_new_child(query, "identity"); xmlnode_set_attrib(identity, "category", "client"); xmlnode_set_attrib(identity, "type", "pc"); /* XXX: bot, console, @@ -98,18 +97,60 @@ SUPPORT_FEATURE("http://jabber.org/protocol/si/profile/file-transfer") SUPPORT_FEATURE("http://jabber.org/protocol/xhtml-im") SUPPORT_FEATURE("http://www.xmpp.org/extensions/xep-0199.html#ns") + + if(!node) { /* non-caps disco#info, add all extensions */ + GList *features; + for(features = js->features; features; features = features->next) { + JabberFeature *feat = (JabberFeature*)features->data; + SUPPORT_FEATURE(feat->namespace); + } + } } else { - xmlnode *error, *inf; + const char *ext = NULL; + unsigned pos; + unsigned nodelen = strlen(node); + unsigned capslen = strlen(CAPS0115_NODE); + /* do a basic plausability check */ + if(nodelen > capslen+1) { + /* verify that the string is CAPS0115# and get the pointer to the ext part */ + for(pos = 0; pos < capslen+1; ++pos) { + if(pos == capslen) { + if(node[pos] == '#') + ext = &node[pos+1]; + else + break; + } else if(node[pos] != CAPS0115_NODE[pos]) + break; + } + + if(ext != NULL) { + /* look for that ext */ + GList *features; + for(features = js->features; features; features = features->next) { + JabberFeature *feat = (JabberFeature*)features->data; + if(!strcmp(feat->shortname, ext)) { + SUPPORT_FEATURE(feat->namespace); + break; + } + } + if(features == NULL) + ext = NULL; + } + } + + if(ext == NULL) { + xmlnode *error, *inf; - /* XXX: gross hack, implement jabber_iq_set_type or something */ - xmlnode_set_attrib(iq->node, "type", "error"); - iq->type = JABBER_IQ_ERROR; + /* XXX: gross hack, implement jabber_iq_set_type or something */ + xmlnode_set_attrib(iq->node, "type", "error"); + iq->type = JABBER_IQ_ERROR; - error = xmlnode_new_child(query, "error"); - xmlnode_set_attrib(error, "code", "404"); - xmlnode_set_attrib(error, "type", "cancel"); - inf = xmlnode_new_child(error, "item-not-found"); - xmlnode_set_namespace(inf, "urn:ietf:params:xml:ns:xmpp-stanzas"); + error = xmlnode_new_child(query, "error"); + xmlnode_set_attrib(error, "code", "404"); + xmlnode_set_attrib(error, "type", "cancel"); + inf = xmlnode_new_child(error, "item-not-found"); + xmlnode_set_namespace(inf, "urn:ietf:params:xml:ns:xmpp-stanzas"); + } } jabber_iq_send(iq); diff -r 6ab1089e2101 -r 95affacf6f82 libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Wed Jun 06 00:04:29 2007 +0000 +++ b/libpurple/protocols/jabber/jabber.c Wed Jun 06 01:19:49 2007 +0000 @@ -1024,6 +1024,12 @@ #endif if(js->serverFQDN) g_free(js->serverFQDN); + while(js->features) { + g_free(((JabberFeature*)js->features->data)->shortname); + g_free(((JabberFeature*)js->features->data)->namespace); + g_free(js->features->data); + js->features = g_list_delete_link(js->features, js->features); + } g_free(js->server_name); g_free(js->gmail_last_time); g_free(js->gmail_last_tid); @@ -1093,6 +1099,32 @@ js->idle = idle ? time(NULL) - idle : idle; } +void jabber_add_feature(JabberStream *js, const char *shortname, const char *namespace) { + JabberFeature *feat = g_new0(JabberFeature,1); + feat->shortname = g_strdup(shortname); + feat->namespace = g_strdup(namespace); + + /* try to remove just in case it already exists in the list */ + jabber_remove_feature(js, shortname); + + js->features = g_list_append(js->features, feat); +} + +void jabber_remove_feature(JabberStream *js, const char *shortname) { + GList *feature; + for(feature = js->features; feature; feature = feature->next) { + JabberFeature *feat = (JabberFeature*)feature->data; + if(!strcmp(feat->shortname, shortname)) { + g_free(feat->shortname); + g_free(feat->namespace); + + g_free(feature->data); + feature = g_list_delete_link(feature, feature); + break; + } + } +} + const char *jabber_list_icon(PurpleAccount *a, PurpleBuddy *b) { return "jabber"; diff -r 6ab1089e2101 -r 95affacf6f82 libpurple/protocols/jabber/jabber.h --- a/libpurple/protocols/jabber/jabber.h Wed Jun 06 00:04:29 2007 +0000 +++ b/libpurple/protocols/jabber/jabber.h Wed Jun 06 01:19:49 2007 +0000 @@ -71,6 +71,12 @@ JABBER_STREAM_CONNECTED } JabberStreamState; +typedef struct _JabberFeature +{ + gchar *shortname; + gchar *namespace; +} JabberFeature; + typedef struct _JabberStream { int fd; @@ -149,7 +155,9 @@ GString *sasl_mechs; #endif char *serverFQDN; - + + /* what kind of additional features as returned from disco#info are supported? */ + GList *features; } JabberStream; void jabber_process_packet(JabberStream *js, xmlnode *packet); @@ -165,6 +173,9 @@ char *jabber_parse_error(JabberStream *js, xmlnode *packet); +void jabber_add_feature(JabberStream *js, const gchar *shortname, const gchar *namespace); +void jabber_remove_feature(JabberStream *js, const gchar *shortname); + /** PRPL functions */ const char *jabber_list_icon(PurpleAccount *a, PurpleBuddy *b); const char* jabber_list_emblem(PurpleBuddy *b); diff -r 6ab1089e2101 -r 95affacf6f82 libpurple/protocols/jabber/presence.c --- a/libpurple/protocols/jabber/presence.c Wed Jun 06 00:04:29 2007 +0000 +++ b/libpurple/protocols/jabber/presence.c Wed Jun 06 01:19:49 2007 +0000 @@ -118,7 +118,7 @@ purple_status_to_jabber(status, &state, &stripped, &priority); - presence = jabber_presence_create(state, stripped, priority); + presence = jabber_presence_create_js(js, state, stripped, priority); g_free(stripped); if(js->avatar_hash) { @@ -138,6 +138,11 @@ xmlnode *jabber_presence_create(JabberBuddyState state, const char *msg, int priority) { + return jabber_presence_create_js(NULL, state, msg, priority); +} + +xmlnode *jabber_presence_create_js(JabberStream *js, JabberBuddyState state, const char *msg, int priority) +{ xmlnode *show, *status, *presence, *pri, *c; const char *show_string = NULL; @@ -172,6 +177,31 @@ xmlnode_set_namespace(c, "http://jabber.org/protocol/caps"); xmlnode_set_attrib(c, "node", CAPS0115_NODE); xmlnode_set_attrib(c, "ver", VERSION); + + if(js != NULL) { + /* add the extensions */ + char extlist[1024]; + unsigned remaining = 1023; /* one less for the \0 */ + GSList *feature; + + extlist[0] = '\0'; + for(feature = js->features; feature && remaining > 0; feature = feature->next) { + JabberFeature *feat = (JabberFeature*)feature->data; + unsigned featlen = strlen(feat->shortname); + + /* cut off when we don't have any more space left in our buffer (too bad) */ + if(featlen > remaining) + break; + + strncat(extlist,feat->shortname,remaining); + remaining -= featlen; + strncat(extlist," ",remaining); + --remaining; + } + /* did we add anything? */ + if(remaining < 1023) + xmlnode_set_attrib(c, "ext", extlist); + } return presence; } diff -r 6ab1089e2101 -r 95affacf6f82 libpurple/protocols/jabber/presence.h --- a/libpurple/protocols/jabber/presence.h Wed Jun 06 00:04:29 2007 +0000 +++ b/libpurple/protocols/jabber/presence.h Wed Jun 06 01:19:49 2007 +0000 @@ -27,7 +27,8 @@ #include "xmlnode.h" void jabber_presence_send(PurpleAccount *account, PurpleStatus *status); -xmlnode *jabber_presence_create(JabberBuddyState state, const char *msg, int priority); +xmlnode *jabber_presence_create(JabberBuddyState state, const char *msg, int priority); /* DEPRECATED */ +xmlnode *jabber_presence_create_js(JabberStream *js, JabberBuddyState state, const char *msg, int priority); void jabber_presence_parse(JabberStream *js, xmlnode *packet); void jabber_presence_subscription_set(JabberStream *js, const char *who, const char *type);