Mercurial > pidgin.yaz
diff libpurple/protocols/jabber/presence.c @ 26817:3912f55a1633
propagate from branch 'im.pidgin.pidgin' (head fbb4fe5da444943eecc76bdcd6c8ba967790b6c8)
to branch 'im.pidgin.cpw.darkrain42.xmpp.bosh' (head 601bc627c9430320848361f0ed81c6c4c6ee53e0)
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Tue, 28 Apr 2009 18:43:57 +0000 |
parents | bc7fac8e2f79 8953034dae88 |
children | 50db9eb2499a |
line wrap: on
line diff
--- a/libpurple/protocols/jabber/presence.c Sat Apr 18 18:17:16 2009 +0000 +++ b/libpurple/protocols/jabber/presence.c Tue Apr 28 18:43:57 2009 +0000 @@ -154,17 +154,25 @@ /* check if there are any differences to the <presence> and send them in that case */ if (force || allowBuzz != js->allowBuzz || js->old_state != state || CHANGED(js->old_msg, stripped) || js->old_priority != priority || - CHANGED(js->old_avatarhash, js->avatar_hash)) { + CHANGED(js->old_avatarhash, js->avatar_hash) || js->old_idle != js->idle) { /* Need to update allowBuzz before creating the presence (with caps) */ js->allowBuzz = allowBuzz; presence = jabber_presence_create_js(js, state, stripped, priority); - if(js->avatar_hash) { - x = xmlnode_new_child(presence, "x"); - xmlnode_set_namespace(x, "vcard-temp:x:update"); + /* Per XEP-0153 4.1, we must always send the <x> */ + x = xmlnode_new_child(presence, "x"); + xmlnode_set_namespace(x, "vcard-temp:x:update"); + /* + * FIXME: Per XEP-0153 4.3.2 bullet 2, we must not publish our + * image hash if another resource has logged in and updated the + * vcard avatar. Requires changes in jabber_presence_parse. + */ + if (js->vcard_fetched) { + /* Always publish a <photo>; it's empty if we have no image. */ photo = xmlnode_new_child(x, "photo"); - xmlnode_insert_data(photo, js->avatar_hash, -1); + if (js->avatar_hash) + xmlnode_insert_data(photo, js->avatar_hash, -1); } jabber_send(js, presence); @@ -182,6 +190,7 @@ js->old_avatarhash = g_strdup(js->avatar_hash); js->old_state = state; js->old_priority = priority; + js->old_idle = js->idle; } g_free(stripped); @@ -263,6 +272,16 @@ g_free(pstr); } + /* if we are idle and not offline, include idle */ + if (js->idle && state != JABBER_BUDDY_STATE_UNAVAILABLE) { + xmlnode *query = xmlnode_new_child(presence, "query"); + gchar seconds[10]; + g_snprintf(seconds, 10, "%d", (int) (time(NULL) - js->idle)); + + xmlnode_set_namespace(query, "jabber:iq:last"); + xmlnode_set_attrib(query, "seconds", seconds); + } + /* JEP-0115 */ /* calculate hash */ jabber_caps_calculate_own_hash(js); @@ -323,8 +342,6 @@ JabberBuddy *jb = NULL; xmlnode *vcard, *photo, *binval; char *text; - guchar *data; - gsize size; if(!from) return; @@ -339,10 +356,13 @@ (( (binval = xmlnode_get_child(photo, "BINVAL")) && (text = xmlnode_get_data(binval))) || (text = xmlnode_get_data(photo)))) { - char *hash; + guchar *data; + gchar *hash; + gsize size; data = purple_base64_decode(text, &size); hash = jabber_calculate_data_sha1sum(data, size); + purple_buddy_icons_set_for_user(js->gc->account, from, data, size, hash); g_free(hash); g_free(text); @@ -412,6 +432,7 @@ JabberBuddyResource *jbr = NULL, *found_jbr = NULL; PurpleConvChatBuddyFlags flags = PURPLE_CBFLAGS_NONE; gboolean delayed = FALSE; + const gchar *stamp = NULL; /* from <delayed/> element */ PurpleBuddy *b = NULL; char *buddy_name; JabberBuddyState state = JABBER_BUDDY_STATE_UNKNOWN; @@ -419,6 +440,7 @@ gboolean muc = FALSE; char *avatar_hash = NULL; xmlnode *caps = NULL; + int idle = 0; if(!(jb = jabber_buddy_find(js, from, TRUE))) return; @@ -501,12 +523,14 @@ } else if(!strcmp(y->name, "delay") && !strcmp(xmlns, "urn:xmpp:delay")) { /* XXX: compare the time. jabber:x:delay can happen on presence packets that aren't really and truly delayed */ delayed = TRUE; + stamp = xmlnode_get_attrib(y, "stamp"); } else if(!strcmp(y->name, "c") && !strcmp(xmlns, "http://jabber.org/protocol/caps")) { caps = y; /* store for later, when creating buddy resource */ } else if(!strcmp(y->name, "x")) { if(!strcmp(xmlns, "jabber:x:delay")) { /* XXX: compare the time. jabber:x:delay can happen on presence packets that aren't really and truly delayed */ delayed = TRUE; + stamp = xmlnode_get_attrib(y, "stamp"); } else if(!strcmp(xmlns, "http://jabber.org/protocol/muc#user")) { xmlnode *z; @@ -557,9 +581,26 @@ avatar_hash = xmlnode_get_data(photo); } } + } else if (!strcmp(y->name, "query") && + !strcmp(xmlnode_get_namespace(y), "jabber:iq:last")) { + /* resource has specified idle */ + const gchar *seconds = xmlnode_get_attrib(y, "seconds"); + if (seconds) { + /* we may need to take "delayed" into account here */ + idle = atoi(seconds); + } } } + if (idle && delayed && stamp) { + /* if we have a delayed presence, we need to add the delay to the idle + value */ + time_t offset = time(NULL) - purple_str_to_time(stamp, TRUE, NULL, NULL, + NULL); + purple_debug_info("jabber", "got delay %s yielding %ld s offset\n", + stamp, offset); + idle += offset; + } if(jid->node && (chat = jabber_chat_find(js, jid->node, jid->domain))) { static int i = 1; @@ -734,6 +775,12 @@ } else { jbr = jabber_buddy_track_resource(jb, jid->resource, priority, state, status); + if (idle) { + jbr->idle = time(NULL) - idle; + } else { + jbr->idle = 0; + } + if(caps) { /* handle XEP-0115 */ const char *node = xmlnode_get_attrib(caps,"node"); @@ -758,6 +805,7 @@ if((found_jbr = jabber_buddy_find_resource(jb, NULL))) { jabber_google_presence_incoming(js, buddy_name, found_jbr); purple_prpl_got_user_status(js->gc->account, buddy_name, jabber_buddy_state_get_status_id(found_jbr->state), "priority", found_jbr->priority, "message", found_jbr->status, NULL); + purple_prpl_got_user_idle(js->gc->account, buddy_name, found_jbr->idle, found_jbr->idle); } else { purple_prpl_got_user_status(js->gc->account, buddy_name, "offline", status ? "message" : NULL, status, NULL); }