diff options
| -rw-r--r-- | protocols/jabber/jabber.c | 25 | ||||
| -rw-r--r-- | protocols/jabber/jabber.h | 9 | ||||
| -rw-r--r-- | protocols/jabber/jabber_util.c | 57 | ||||
| -rw-r--r-- | protocols/jabber/message.c | 31 | ||||
| -rw-r--r-- | protocols/jabber/presence.c | 28 | 
5 files changed, 122 insertions, 28 deletions
| diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 26d7bbab..abc3837b 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -146,23 +146,23 @@ static int jabber_send_im( struct gaim_connection *gc, char *who, char *message,  	bud = jabber_buddy_by_jid( gc, who );  	node = xt_new_node( "body", message, NULL ); -	node = jabber_make_packet( "message", "chat", bud->full_jid, node ); +	node = jabber_make_packet( "message", "chat", bud ? bud->full_jid : who, node ); -	if( ( jd->flags & JFLAG_WANT_TYPING ) && -	    ( ( bud->flags & JBFLAG_DOES_JEP85 ) || -	     !( bud->flags & JBFLAG_PROBED_JEP85 ) ) ) +	if( ( jd->flags & JFLAG_WANT_TYPING ) && bud && +	    ( ( bud->flags & JBFLAG_DOES_XEP85 ) || +	     !( bud->flags & JBFLAG_PROBED_XEP85 ) ) )  	{  		struct xt_node *act;  		/* If the user likes typing notification and if we don't know -		   (and didn't probe before) if this resource supports JEP85, +		   (and didn't probe before) if this resource supports XEP85,  		   include a probe in this packet now. */  		act = xt_new_node( "active", NULL, NULL );  		xt_add_attr( act, "xmlns", "http://jabber.org/protocol/chatstates" );  		xt_add_child( node, act );  		/* Just make sure we do this only once. */ -		bud->flags |= JBFLAG_PROBED_JEP85; +		bud->flags |= JBFLAG_PROBED_XEP85;  	}  	st = jabber_write_packet( gc, node ); @@ -225,6 +225,9 @@ static void jabber_add_buddy( struct gaim_connection *gc, char *who )  static void jabber_remove_buddy( struct gaim_connection *gc, char *who, char *group )  { +	/* We should always do this part. Clean up our administration a little bit. */ +	jabber_buddy_remove_bare( gc, who ); +	  	if( jabber_remove_from_roster( gc, who ) )  		presence_send_request( gc, who, "unsubscribe" );  } @@ -247,8 +250,14 @@ static int jabber_send_typing( struct gaim_connection *gc, char *who, int typing  	/* Enable typing notification related code from now. */  	jd->flags |= JFLAG_WANT_TYPING; -	bud = jabber_buddy_by_jid( gc, who ); -	if( bud->flags & JBFLAG_DOES_JEP85 ) +	if( ( bud = jabber_buddy_by_jid( gc, who ) ) == NULL ) +	{ +		/* Sending typing notifications to unknown buddies is +		   unsupported for now. Shouldn't be a problem, I think. */ +		return 0; +	} +	 +	if( bud->flags & JBFLAG_DOES_XEP85 )  	{  		/* We're only allowed to send this stuff if we know the other  		   side supports it. */ diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index e5b85f39..d1d452b4 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -40,15 +40,15 @@ typedef enum  	                                   before we continue. */  	JFLAG_WAIT_BIND = 16,		/* ... for <bind> tag. */  	JFLAG_WANT_TYPING = 32,		/* Set if we ever sent a typing notification, this -	                                   activates all JEP-85 related code. */ +	                                   activates all XEP-85 related code. */  } jabber_flags_t;  typedef enum  { -	JBFLAG_PROBED_JEP85 = 1,	/* Set this when we sent our probe packet to make +	JBFLAG_PROBED_XEP85 = 1,	/* Set this when we sent our probe packet to make  	                                   sure it gets sent only once. */ -	JBFLAG_DOES_JEP85 = 2,		/* Set this when the resource seems to support -	                                   JEP85 (typing notification shite). */ +	JBFLAG_DOES_XEP85 = 2,		/* Set this when the resource seems to support +	                                   XEP85 (typing notification shite). */  } jabber_buddy_flag_t;  struct jabber_data @@ -137,6 +137,7 @@ void jabber_buddy_ask( struct gaim_connection *gc, char *handle );  struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_jid );  struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid );  int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid ); +int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid );  extern const struct jabber_away_state jabber_away_state_list[]; diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index d9a89951..d5d038cf 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -28,13 +28,20 @@ static int next_id = 1;  char *set_eval_priority( set_t *set, char *value )  {  	account_t *acc = set->data; -	char *ret; +	int i; -	ret = set_eval_int( set, value ); +	if( sscanf( value, "%d", &i ) == 1 ) +	{ +		/* Priority is a signed 8-bit integer, according to RFC 3921. */ +		if( i < -128 || i > 127 ) +			return NULL; +	} +	else +		return NULL;  	/* Only run this stuff if the account is online ATM,  	   and if the setting seems to be acceptable. */ -	if( acc->gc && ret ) +	if( acc->gc )  	{  		/* Although set_eval functions usually are very nice and  		   convenient, they have one disadvantage: If I would just @@ -46,14 +53,14 @@ char *set_eval_priority( set_t *set, char *value )  		   functions next to evals, or just do this little hack: */  		g_free( set->value ); -		set->value = g_strdup( ret ); +		set->value = g_strdup( value );  		/* (Yes, sorry, I prefer the hack. :-P) */  		presence_send_update( acc->gc );  	} -	return ret; +	return value;  }  char *set_eval_tls( set_t *set, char *value ) @@ -282,6 +289,9 @@ struct jabber_buddy *jabber_buddy_add( struct gaim_connection *gc, char *full_ji  	return new;  } +/* Finds a buddy from our structures. Can find both full- and bare JIDs. When +   asked for a bare JID, it uses the "resource_select" setting to see which +   resource to pick. */  struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid )  {  	struct jabber_data *jd = gc->proto_data; @@ -322,6 +332,8 @@ struct jabber_buddy *jabber_buddy_by_jid( struct gaim_connection *gc, char *jid  	return bud;  } +/* Remove one specific full JID from our list. Use this when a buddy goes +   off-line (because (s)he can still be online from a different location. */  int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid )  {  	struct jabber_data *jd = gc->proto_data; @@ -380,3 +392,38 @@ int jabber_buddy_remove( struct gaim_connection *gc, char *full_jid )  		return 0;  	}  } + +/* Remove a buddy completely; removes all resources that belong to the +   specified bare JID. Use this when removing someone from the contact +   list, for example. */ +int jabber_buddy_remove_bare( struct gaim_connection *gc, char *bare_jid ) +{ +	struct jabber_data *jd = gc->proto_data; +	struct jabber_buddy *bud, *next; +	 +	if( strchr( bare_jid, '/' ) ) +		return 0; +	 +	if( ( bud = g_hash_table_lookup( jd->buddies, bare_jid ) ) ) +	{ +		/* Most important: Remove the hash reference. We don't know +		   this buddy anymore. */ +		g_hash_table_remove( jd->buddies, bud->handle ); +		 +		/* Deallocate the linked list of resources. */ +		while( bud ) +		{ +			next = bud->next; +			g_free( bud->full_jid ); +			g_free( bud->away_message ); +			g_free( bud ); +			bud = next; +		} +		 +		return 1; +	} +	else +	{ +		return 0; +	} +} diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c index fea728e3..3ff1da1c 100644 --- a/protocols/jabber/message.c +++ b/protocols/jabber/message.c @@ -29,6 +29,7 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data )  	char *from = xt_find_attr( node, "from" );  	char *type = xt_find_attr( node, "type" );  	struct xt_node *body = xt_find_node( node->children, "body" ); +	char *s;  	if( !type )  		return XT_HANDLED;	/* Grmbl... FIXME */ @@ -37,7 +38,7 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data )  	{  		struct jabber_buddy *bud = NULL; -		if( strchr( from, '/' ) == NULL ) +		if( ( s = strchr( from, '/' ) ) == NULL )  		{  			/* It just shouldn't happen. */  			hide_login_progress( gc, "Received message packet from bare JID" ); @@ -45,21 +46,34 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data )  			return XT_ABORT;  		} -		bud = jabber_buddy_by_jid( gc, from ); -		bud->last_act = time( NULL ); +		if( ( bud = jabber_buddy_by_jid( gc, from ) ) ) +			bud->last_act = time( NULL ); +		else +			*s = 0; /* We need to generate a bare JID now. */  		if( body ) /* Could be just a typing notification. */ -			serv_got_im( gc, bud->handle, body->text, 0, 0, 0 ); +			serv_got_im( gc, bud ? bud->handle : from, body->text, 0, 0, 0 ); +		/* Handling of incoming typing notifications. */  		if( xt_find_node( node->children, "composing" ) )  		{ -			bud->flags |= JBFLAG_DOES_JEP85; -			serv_got_typing( gc, bud->handle, 0, 1 ); +			bud->flags |= JBFLAG_DOES_XEP85; +			serv_got_typing( gc, bud ? bud->handle : from, 0, 1 );  		} -		else if( xt_find_node( node->children, "active" ) ) +		/* No need to send a "stopped typing" signal when there's a message. */ +		else if( xt_find_node( node->children, "active" ) && ( body == NULL ) )  		{ -			bud->flags |= JBFLAG_DOES_JEP85; +			bud->flags |= JBFLAG_DOES_XEP85; +			serv_got_typing( gc, bud ? bud->handle : from, 0, 0 );  		} +		else if( xt_find_node( node->children, "paused" ) ) +		{ +			bud->flags |= JBFLAG_DOES_XEP85; +			serv_got_typing( gc, bud ? bud->handle : from, 0, 2 ); +		} +		 +		if( s ) +			*s = '/'; /* And convert it back to a full JID. */  	}  	else  	{ @@ -69,4 +83,3 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data )  	return XT_HANDLED;  } - diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index b10ce634..ccd22f60 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -30,22 +30,40 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data )  	char *type = xt_find_attr( node, "type" );	/* NULL should mean the person is online. */  	struct xt_node *c;  	struct jabber_buddy *bud; +	char *s;  	if( !from )  		return XT_HANDLED;  	if( type == NULL )  	{ -		if( strchr( from, '/' ) == NULL ) +		if( ( s = strchr( from, '/' ) ) == NULL )  		{  			char *s = xt_to_string( node ); -			serv_got_crap( gc, "WARNING: Ignoring presence tag with bare JID: %s\n", s ); +			serv_got_crap( gc, "WARNING: Ignoring presence tag with bare JID: %s", s );  			g_free( s );  			return XT_HANDLED;  		}  		if( !( bud = jabber_buddy_by_jid( gc, from ) ) )  		{ +			/* FOR NOW, s still contains the location of the /. +			   Keep this in mind when changing things here. :-) */ +			 +			/* We check if the buddy is in the contact list, +			   because Jabber servers seem to like to send +			   presence information of buddies we removed +			   from our list sometimes, for example... */ +			 +			*s = 0; +			if( find_buddy( gc, from ) == NULL ) +			{ +				*s = '/'; +				serv_got_crap( gc, "WARNING: Ignoring presence information from unknown JID: %s", from ); +				return XT_HANDLED; +			} +			*s = '/'; +			  			bud = jabber_buddy_add( gc, from );  		} @@ -85,6 +103,12 @@ xt_status jabber_pkt_presence( struct xt_node *node, gpointer data )  			return XT_HANDLED;  		} +		if( jabber_buddy_by_jid( gc, from ) == NULL ) +		{ +			serv_got_crap( gc, "WARNING: Received presence information from unknown JID: %s", from ); +			return XT_HANDLED; +		} +		  		jabber_buddy_remove( gc, from );  		*s = 0; | 
