comparison libpurple/protocols/jabber/presence.c @ 17609:f88b3a093cba

Implemented ad-hoc commands for the buddy action menu (untested), implemented the receiving end of XEP-0115: Entity Capabilities. Note that this seems not to be reliable right now, since some clients seem to have a very broken [read: completely non-functional] implementation (most notably Gajim and the py-transports).
author Andreas Monitzer <pidgin@monitzer.com>
date Sat, 23 Jun 2007 02:57:21 +0000
parents 3399dd1c258d
children 935005186312
comparison
equal deleted inserted replaced
17608:a8b1159fd95b 17609:f88b3a093cba
34 #include "buddy.h" 34 #include "buddy.h"
35 #include "chat.h" 35 #include "chat.h"
36 #include "presence.h" 36 #include "presence.h"
37 #include "iq.h" 37 #include "iq.h"
38 #include "jutil.h" 38 #include "jutil.h"
39 #include "adhoccommands.h"
39 40
40 #include "usertune.h" 41 #include "usertune.h"
41 42
42 43
43 static void chats_send_presence_foreach(gpointer key, gpointer val, 44 static void chats_send_presence_foreach(gpointer key, gpointer val,
335 g_free(text); 336 g_free(text);
336 } 337 }
337 } 338 }
338 } 339 }
339 340
341 typedef struct _JabberPresenceCapabilities {
342 JabberStream *js;
343 JabberBuddyResource *jbr;
344 char *from;
345 } JabberPresenceCapabilities;
346
347 static void jabber_presence_set_capabilities(JabberCapsClientInfo *info, gpointer user_data) {
348 JabberPresenceCapabilities *userdata = user_data;
349 GList *iter;
350
351 if(userdata->jbr->caps)
352 jabber_caps_free_clientinfo(userdata->jbr->caps);
353 userdata->jbr->caps = info;
354
355 for(iter = info->features; iter; iter = g_list_next(iter)) {
356 if(!strcmp((const char*)iter->data, "http://jabber.org/protocol/commands")) {
357 JabberIq *iq = jabber_iq_new_query(userdata->js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#items");
358 xmlnode *query = xmlnode_get_child_with_namespace(iq->node,"query","http://jabber.org/protocol/disco#items");
359 xmlnode_set_attrib(iq->node, "to", userdata->from);
360 xmlnode_set_attrib(query, "node", "http://jabber.org/protocol/commands");
361
362 jabber_iq_set_callback(iq, jabber_adhoc_disco_result_cb, NULL);
363 jabber_iq_send(iq);
364 break;
365 }
366 }
367 g_free(user_data);
368 }
369
340 void jabber_presence_parse(JabberStream *js, xmlnode *packet) 370 void jabber_presence_parse(JabberStream *js, xmlnode *packet)
341 { 371 {
342 const char *from = xmlnode_get_attrib(packet, "from"); 372 const char *from = xmlnode_get_attrib(packet, "from");
343 const char *type = xmlnode_get_attrib(packet, "type"); 373 const char *type = xmlnode_get_attrib(packet, "type");
344 const char *real_jid = NULL; 374 const char *real_jid = NULL;
356 char *buddy_name; 386 char *buddy_name;
357 JabberBuddyState state = JABBER_BUDDY_STATE_UNKNOWN; 387 JabberBuddyState state = JABBER_BUDDY_STATE_UNKNOWN;
358 xmlnode *y; 388 xmlnode *y;
359 gboolean muc = FALSE; 389 gboolean muc = FALSE;
360 char *avatar_hash = NULL; 390 char *avatar_hash = NULL;
391 xmlnode *caps = NULL;
361 392
362 if(!(jb = jabber_buddy_find(js, from, TRUE))) 393 if(!(jb = jabber_buddy_find(js, from, TRUE)))
363 return; 394 return;
364 395
365 if(!(jid = jabber_id_new(from))) 396 if(!(jid = jabber_id_new(from)))
418 } 449 }
419 } 450 }
420 451
421 452
422 for(y = packet->child; y; y = y->next) { 453 for(y = packet->child; y; y = y->next) {
454 const char *xmlns;
423 if(y->type != XMLNODE_TYPE_TAG) 455 if(y->type != XMLNODE_TYPE_TAG)
424 continue; 456 continue;
457 xmlns = xmlnode_get_namespace(y);
425 458
426 if(!strcmp(y->name, "status")) { 459 if(!strcmp(y->name, "status")) {
427 g_free(status); 460 g_free(status);
428 status = xmlnode_get_data(y); 461 status = xmlnode_get_data(y);
429 } else if(!strcmp(y->name, "priority")) { 462 } else if(!strcmp(y->name, "priority")) {
430 char *p = xmlnode_get_data(y); 463 char *p = xmlnode_get_data(y);
431 if(p) { 464 if(p) {
432 priority = atoi(p); 465 priority = atoi(p);
433 g_free(p); 466 g_free(p);
434 } 467 }
435 } else if(!strcmp(y->name, "delay")) { 468 } else if(!strcmp(y->name, "delay") && !strcmp(xmlns, "urn:xmpp:delay")) {
436 /* XXX: compare the time. jabber:x:delay can happen on presence packets that aren't really and truly delayed */ 469 /* XXX: compare the time. jabber:x:delay can happen on presence packets that aren't really and truly delayed */
437 delayed = TRUE; 470 delayed = TRUE;
471 } else if(!strcmp(y->name, "c") && !strcmp(xmlns, "http://jabber.org/protocol/caps")) {
472 caps = y; /* store for later, when creating buddy resource */
438 } else if(!strcmp(y->name, "x")) { 473 } else if(!strcmp(y->name, "x")) {
439 const char *xmlns = xmlnode_get_namespace(y); 474 const char *xmlns = xmlnode_get_namespace(y);
440 if(xmlns && !strcmp(xmlns, "jabber:x:delay")) { 475 if(xmlns && !strcmp(xmlns, "jabber:x:delay")) {
441 /* XXX: compare the time. jabber:x:delay can happen on presence packets that aren't really and truly delayed */ 476 /* XXX: compare the time. jabber:x:delay can happen on presence packets that aren't really and truly delayed */
442 delayed = TRUE; 477 delayed = TRUE;
654 purple_conversation_set_name(conv, buddy_name); 689 purple_conversation_set_name(conv, buddy_name);
655 690
656 } else { 691 } else {
657 jbr = jabber_buddy_track_resource(jb, jid->resource, priority, 692 jbr = jabber_buddy_track_resource(jb, jid->resource, priority,
658 state, status); 693 state, status);
694 if(caps) {
695 const char *node = xmlnode_get_attrib(caps,"node");
696 const char *ver = xmlnode_get_attrib(caps,"ver");
697 const char *ext = xmlnode_get_attrib(caps,"ext");
698
699 if(node && ver) {
700 JabberPresenceCapabilities *userdata = g_new0(JabberPresenceCapabilities, 1);
701 userdata->js = js;
702 userdata->jbr = jbr;
703 userdata->from = g_strdup(from);
704 jabber_caps_get_info(js, from, node, ver, ext, jabber_presence_set_capabilities, userdata);
705 }
706 }
659 } 707 }
660 708
661 if((found_jbr = jabber_buddy_find_resource(jb, NULL))) { 709 if((found_jbr = jabber_buddy_find_resource(jb, NULL))) {
662 if(!jbr || jbr == found_jbr) { 710 if(!jbr || jbr == found_jbr) {
663 purple_prpl_got_user_status(js->gc->account, buddy_name, jabber_buddy_state_get_status_id(state), "priority", found_jbr->priority, found_jbr->status ? "message" : NULL, found_jbr->status, NULL); 711 purple_prpl_got_user_status(js->gc->account, buddy_name, jabber_buddy_state_get_status_id(state), "priority", found_jbr->priority, found_jbr->status ? "message" : NULL, found_jbr->status, NULL);