cpw.malu.xmpp.idle: 4def8227: A first stab at supporting the upcoming ...

malu at pidgin.im malu at pidgin.im
Sun Nov 16 17:30:35 EST 2008


-----------------------------------------------------------------
Revision: 4def82270f4601da28a42de74b29d1ab0046be3e
Ancestor: f3891f3348abfe90fbe60a054833c12075aa8df4
Author: malu at pidgin.im
Date: 2008-11-16T22:29:00
Branch: im.pidgin.cpw.malu.xmpp.idle
URL: http://d.pidgin.im/viewmtn/revision/info/4def82270f4601da28a42de74b29d1ab0046be3e

Modified files:
        libpurple/protocols/jabber/buddy.c
        libpurple/protocols/jabber/buddy.h
        libpurple/protocols/jabber/disco.c
        libpurple/protocols/jabber/jabber.c
        libpurple/protocols/jabber/presence.c
        libpurple/protocols/jabber/presence.h
        libpurple/protocols/jabber/roster.c

ChangeLog: 

A first stab at supporting the upcoming new use-case in XMPP XEP-0012
to provide info on idleness in <presence/> stanzas, which allows to track
idle times without polling.

-------------- next part --------------
============================================================
--- libpurple/protocols/jabber/buddy.c	b687d1cce701f26584534067479bb48e29893101
+++ libpurple/protocols/jabber/buddy.c	ba0c5e278c9fd7a40af3c1b4b734f1b65496ca23
@@ -627,7 +627,7 @@ void jabber_set_buddy_icon(PurpleConnect
 
 	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);
 }
 
 /*
============================================================
--- libpurple/protocols/jabber/buddy.h	b72ccdfffb3ac98b1f2cab34a3fddfef59c086e5
+++ libpurple/protocols/jabber/buddy.h	202840b79a776232124f348b43d9b02dec0dcdb4
@@ -69,6 +69,7 @@ typedef struct _JabberBuddyResource {
 	int priority;
 	JabberBuddyState state;
 	char *status;
+	time_t idle;
 	JabberCapabilities capabilities;
 	char *thread_id;
 	enum {
============================================================
--- libpurple/protocols/jabber/disco.c	7f85a8a092ed6670ee147af38b8482042416e2ee
+++ libpurple/protocols/jabber/disco.c	7a7045489884ae4fcd1b2ab6e76b1da0f4bf0148
@@ -348,7 +348,7 @@ jabber_disco_finish_server_info_result_c
 	}
 
 	/* 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 */
============================================================
--- libpurple/protocols/jabber/jabber.c	7ae43cf5a01de166b8e02df1e8f6f4ec195540b4
+++ libpurple/protocols/jabber/jabber.c	07dcd63dd716adf23b5b19743564bfe7a5d47682
@@ -1434,8 +1434,14 @@ void jabber_idle_set(PurpleConnection *g
 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) {
============================================================
--- libpurple/protocols/jabber/presence.c	1bb6fa1483cacef7ba9da2c4f3dcecff39c2eeb3
+++ libpurple/protocols/jabber/presence.c	386e5b34c3882ed4a0b9524c84a6956fe36c2ee1
@@ -95,7 +95,8 @@ void jabber_presence_fake_to_self(Jabber
 }
 
 
-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 @@ void jabber_presence_send(PurpleAccount 
 #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 <presence> 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 @@ xmlnode *jabber_presence_create_js(Jabbe
 		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 @@ static void jabber_presence_set_capabili
 	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 @@ void jabber_presence_parse(JabberStream 
 	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 @@ void jabber_presence_parse(JabberStream 
 					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 @@ void jabber_presence_parse(JabberStream 
 		} 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 @@ void jabber_presence_parse(JabberStream 
 		} 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);
============================================================
--- libpurple/protocols/jabber/presence.h	a77bd82d513655a2ba4eef03d8c9f2d70e7e7e3d
+++ libpurple/protocols/jabber/presence.h	d9060c67c048b365eb8c9edc4bec60b58c371cfa
@@ -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);
============================================================
--- libpurple/protocols/jabber/roster.c	a384763565f91ecfa641f97f9ba59f697fa9169a
+++ libpurple/protocols/jabber/roster.c	89f92e6dd7b9b26035b253670fefa8bbdf42bad7
@@ -261,7 +261,7 @@ void jabber_roster_parse(JabberStream *j
 	if(!js->roster_parsed) {
 		js->roster_parsed = TRUE;
 
-		jabber_presence_send(js->gc->account, NULL);
+		jabber_presence_send(js->gc->account, NULL, FALSE);
 	}
 }
 


More information about the Commits mailing list