Mercurial > pidgin.yaz
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); |