# HG changeset patch # User Marcus Lundblad # Date 1226874540 0 # Node ID e9b7e41dc816f2d4140deb498512e199fba09ed1 # Parent fae699fece1f0072d6a416615f423681c5dd14e1 A first stab at supporting the upcoming new use-case in XMPP XEP-0012 to provide info on idleness in stanzas, which allows to track idle times without polling. diff -r fae699fece1f -r e9b7e41dc816 libpurple/protocols/jabber/buddy.c --- a/libpurple/protocols/jabber/buddy.c Sun Nov 16 00:10:02 2008 +0000 +++ b/libpurple/protocols/jabber/buddy.c Sun Nov 16 22:29:00 2008 +0000 @@ -627,7 +627,7 @@ gpresence = purple_account_get_presence(gc->account); status = purple_presence_get_active_status(gpresence); - jabber_presence_send(gc->account, status); + jabber_presence_send(gc->account, status, FALSE); } /* diff -r fae699fece1f -r e9b7e41dc816 libpurple/protocols/jabber/buddy.h --- a/libpurple/protocols/jabber/buddy.h Sun Nov 16 00:10:02 2008 +0000 +++ b/libpurple/protocols/jabber/buddy.h Sun Nov 16 22:29:00 2008 +0000 @@ -69,6 +69,7 @@ int priority; JabberBuddyState state; char *status; + time_t idle; JabberCapabilities capabilities; char *thread_id; enum { diff -r fae699fece1f -r e9b7e41dc816 libpurple/protocols/jabber/disco.c --- a/libpurple/protocols/jabber/disco.c Sun Nov 16 00:10:02 2008 +0000 +++ b/libpurple/protocols/jabber/disco.c Sun Nov 16 22:29:00 2008 +0000 @@ -348,7 +348,7 @@ } /* Send initial presence; this will trigger receipt of presence for contacts on the roster */ - jabber_presence_send(js->gc->account, NULL); + jabber_presence_send(js->gc->account, NULL, FALSE); if (js->server_caps & JABBER_CAP_ADHOC) { /* The server supports ad-hoc commands, so let's request the list */ diff -r fae699fece1f -r e9b7e41dc816 libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Sun Nov 16 00:10:02 2008 +0000 +++ b/libpurple/protocols/jabber/jabber.c Sun Nov 16 22:29:00 2008 +0000 @@ -1434,8 +1434,14 @@ void jabber_idle_set(PurpleConnection *gc, int idle) { JabberStream *js = gc->proto_data; - + PurpleAccount *account = purple_connection_get_account(gc); + PurpleStatus *status = purple_account_get_active_status(account); + js->idle = idle ? time(NULL) - idle : idle; + + /* send out an updated prescence */ + purple_debug_info("jabber", "sending updated presence for idle\n"); + jabber_presence_send(account, status, TRUE); } void jabber_add_feature(const char *shortname, const char *namespace, JabberFeatureEnabled cb) { diff -r fae699fece1f -r e9b7e41dc816 libpurple/protocols/jabber/presence.c --- a/libpurple/protocols/jabber/presence.c Sun Nov 16 00:10:02 2008 +0000 +++ b/libpurple/protocols/jabber/presence.c Sun Nov 16 22:29:00 2008 +0000 @@ -95,7 +95,8 @@ } -void jabber_presence_send(PurpleAccount *account, PurpleStatus *status) +void jabber_presence_send(PurpleAccount *account, PurpleStatus *status, + gboolean update_idle) { PurpleConnection *gc = NULL; JabberStream *js = NULL; @@ -150,7 +151,7 @@ #define CHANGED(a,b) ((!a && b) || (a && a[0] == '\0' && b && b[0] != '\0') || \ (a && !b) || (a && a[0] != '\0' && b && b[0] == '\0') || (a && b && strcmp(a,b))) /* check if there are any differences to the and send them in that case */ - if (allowBuzz != js->allowBuzz || js->old_state != state || CHANGED(js->old_msg, stripped) || + if (update_idle || allowBuzz != js->allowBuzz || js->old_state != state || CHANGED(js->old_msg, stripped) || js->old_priority != priority || CHANGED(js->old_avatarhash, js->avatar_hash)) { js->allowBuzz = allowBuzz; @@ -260,6 +261,15 @@ 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 = g_strdup_printf("%d", (int) (time(NULL) - js->idle)); + + xmlnode_set_namespace(query, "jabber:iq:last"); + xmlnode_set_attrib(query, "seconds", seconds); + } + /* JEP-0115 */ c = xmlnode_new_child(presence, "c"); xmlnode_set_namespace(c, "http://jabber.org/protocol/caps"); @@ -412,6 +422,42 @@ g_free(userdata); } +static void +jabber_presence_update_buddy_idle(PurpleAccount *account, const gchar *who, + JabberBuddy *jb) +{ + const GList *iter = NULL; + gboolean idle = TRUE; + time_t last_idle = 0; + + purple_debug_info("jabber", "updating idle for buddy %s\n", who); + + if (!jb->resources) { + idle = FALSE; + } + + for (iter = jb->resources ; iter ; iter = g_list_next(iter)) { + JabberBuddyResource *jbr = (JabberBuddyResource *) iter->data; + + purple_debug_info("jabber", "resource %s has an idle set to %d\n", + jbr->name, jbr->idle); + + if (!jbr->idle) { + idle = FALSE; + break; + } + if (jbr->idle > last_idle) { + last_idle = jbr->idle; + } + } + + if (idle) { + purple_prpl_got_user_idle(account, who, TRUE, last_idle); + } else { + purple_prpl_got_user_idle(account, who, FALSE, 0); + } +} + void jabber_presence_parse(JabberStream *js, xmlnode *packet) { const char *from = xmlnode_get_attrib(packet, "from"); @@ -434,7 +480,8 @@ gboolean muc = FALSE; char *avatar_hash = NULL; xmlnode *caps = NULL; - + int idle = 0; + if(!(jb = jabber_buddy_find(js, from, TRUE))) return; @@ -570,6 +617,14 @@ 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); + } } } @@ -747,6 +802,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) { const char *node = xmlnode_get_attrib(caps,"node"); const char *ver = xmlnode_get_attrib(caps,"ver"); @@ -768,6 +829,7 @@ } else { purple_prpl_got_user_status(js->gc->account, buddy_name, "offline", status ? "message" : NULL, status, NULL); } + jabber_presence_update_buddy_idle(js->gc->account, buddy_name, jb); g_free(buddy_name); } g_free(status); diff -r fae699fece1f -r e9b7e41dc816 libpurple/protocols/jabber/presence.h --- a/libpurple/protocols/jabber/presence.h Sun Nov 16 00:10:02 2008 +0000 +++ b/libpurple/protocols/jabber/presence.h Sun Nov 16 22:29:00 2008 +0000 @@ -26,7 +26,8 @@ #include "jabber.h" #include "xmlnode.h" -void jabber_presence_send(PurpleAccount *account, PurpleStatus *status); +void jabber_presence_send(PurpleAccount *account, PurpleStatus *status, + gboolean update_idle); 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); diff -r fae699fece1f -r e9b7e41dc816 libpurple/protocols/jabber/roster.c --- a/libpurple/protocols/jabber/roster.c Sun Nov 16 00:10:02 2008 +0000 +++ b/libpurple/protocols/jabber/roster.c Sun Nov 16 22:29:00 2008 +0000 @@ -261,7 +261,7 @@ if(!js->roster_parsed) { js->roster_parsed = TRUE; - jabber_presence_send(js->gc->account, NULL); + jabber_presence_send(js->gc->account, NULL, FALSE); } }