diff options
Diffstat (limited to 'protocols/jabber/presence.c')
| -rw-r--r-- | protocols/jabber/presence.c | 76 | 
1 files changed, 53 insertions, 23 deletions
| diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index c3d7dced..6fc360b7 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -28,9 +28,9 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data )  	struct im_connection *ic = data;  	char *from = xt_find_attr( node, "from" );  	char *type = xt_find_attr( node, "type" );	/* NULL should mean the person is online. */ -	struct xt_node *c; -	struct jabber_buddy *bud; -	int is_chat = 0, is_away = 0; +	struct xt_node *c, *cap; +	struct jabber_buddy *bud, *send_presence = NULL; +	int is_chat = 0;  	char *s;  	if( !from ) @@ -49,7 +49,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data )  		if( !( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT | GET_BUDDY_CREAT ) ) )  		{  			if( set_getbool( &ic->irc->set, "debug" ) ) -				imcb_log( ic, "WARNING: Could not handle presence information from JID: %s", from ); +				imcb_log( ic, "Warning: Could not handle presence information from JID: %s", from );  			return XT_HANDLED;  		} @@ -62,8 +62,6 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data )  		if( ( c = xt_find_node( node->children, "show" ) ) && c->text_len > 0 )  		{  			bud->away_state = (void*) jabber_away_state_by_code( c->text ); -			if( strcmp( c->text, "chat" ) != 0 ) -				is_away = OPT_AWAY;  		}  		else  		{ @@ -78,19 +76,37 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data )  		else  			bud->priority = 0; +		if( bud && ( cap = xt_find_node( node->children, "c" ) ) && +		    ( s = xt_find_attr( cap, "xmlns" ) ) && strcmp( s, XMLNS_CAPS ) == 0 ) +		{ +			/* This <presence> stanza includes an XEP-0115 +			   capabilities part. Not too interesting, but we can +			   see if it has an ext= attribute. */ +			s = xt_find_attr( cap, "ext" ); +			if( s && ( strstr( s, "cstates" ) || strstr( s, "chatstate" ) ) ) +				bud->flags |= JBFLAG_DOES_XEP85; +			 +			/* This field can contain more information like xhtml +			   support, but we don't support that ourselves. +			   Officially the ext= tag was deprecated, but enough +			   clients do send it. +			    +			   (I'm aware that this is not the right way to use +			   this field.) See for an explanation of ext=: +			   http://www.xmpp.org/extensions/attic/xep-0115-1.3.html*/ +		} +		  		if( is_chat )  			jabber_chat_pkt_presence( ic, bud, node ); -		else if( bud == jabber_buddy_by_jid( ic, bud->bare_jid, 0 ) ) -			imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away, -			                   ( is_away && bud->away_state ) ? bud->away_state->full_name : NULL, -			                   bud->away_message ); +		else +			send_presence = jabber_buddy_by_jid( ic, bud->bare_jid, 0 );  	}  	else if( strcmp( type, "unavailable" ) == 0 )  	{  		if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) == NULL )  		{  			if( set_getbool( &ic->irc->set, "debug" ) ) -				imcb_log( ic, "WARNING: Received presence information from unknown JID: %s", from ); +				imcb_log( ic, "Warning: Received presence information from unknown JID: %s", from );  			return XT_HANDLED;  		} @@ -118,17 +134,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data )  			/* If another resource is still available, send its presence  			   information. */ -			if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) ) -			{ -				if( bud->away_state && ( *bud->away_state->code == 0 || -				    strcmp( bud->away_state->code, "chat" ) == 0 ) ) -					is_away = OPT_AWAY; -				 -				imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away, -				                   ( is_away && bud->away_state ) ? bud->away_state->full_name : NULL, -				                   bud->away_message ); -			} -			else +			if( ( send_presence = jabber_buddy_by_jid( ic, from, 0 ) ) == NULL )  			{  				/* Otherwise, count him/her as offline now. */  				imcb_buddy_status( ic, from, 0, NULL, NULL ); @@ -176,6 +182,20 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data )  			jabber_error_free( err );  		} */  	} + +	if( send_presence ) +	{ +		int is_away = 0; + +		if( send_presence->away_state && !( *send_presence->away_state->code == 0 || +		    strcmp( send_presence->away_state->code, "chat" ) == 0 ) ) +			is_away = OPT_AWAY; + +		imcb_buddy_status( ic, send_presence->bare_jid, OPT_LOGGED_IN | is_away, +		                   ( is_away && send_presence->away_state ) ? +		                   send_presence->away_state->full_name : NULL, +		                   send_presence->away_message ); +	}  	return XT_HANDLED;  } @@ -185,7 +205,7 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data )  int presence_send_update( struct im_connection *ic )  {  	struct jabber_data *jd = ic->proto_data; -	struct xt_node *node; +	struct xt_node *node, *cap;  	char *show = jd->away_state->code;  	char *status = jd->away_message;  	struct groupchat *c; @@ -198,6 +218,16 @@ int presence_send_update( struct im_connection *ic )  	if( status )  		xt_add_child( node, xt_new_node( "status", status, NULL ) ); +	/* This makes the packet slightly bigger, but clients interested in +	   capabilities can now cache the discovery info. This reduces the +	   usual post-login iq-flood. See XEP-0115. At least libpurple and +	   Trillian seem to do this right. */ +	cap = xt_new_node( "c", NULL, NULL ); +	xt_add_attr( cap, "xmlns", XMLNS_CAPS ); +	xt_add_attr( cap, "node", "http://bitlbee.org/xmpp/caps" ); +	xt_add_attr( cap, "ver", BITLBEE_VERSION ); /* The XEP wants this hashed, but nobody's doing that. */ +	xt_add_child( node, cap ); +	  	st = jabber_write_packet( ic, node );  	/* Have to send this update to all groupchats too, the server won't | 
