diff options
| -rw-r--r-- | protocols/jabber/io.c | 2 | ||||
| -rw-r--r-- | protocols/jabber/iq.c | 119 | ||||
| -rw-r--r-- | protocols/jabber/jabber.c | 10 | ||||
| -rw-r--r-- | protocols/jabber/jabber.h | 8 | 
4 files changed, 131 insertions, 8 deletions
| diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index 3bc967e0..f62e059a 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -334,7 +334,7 @@ static xt_status jabber_pkt_features( struct xt_node *node, gpointer data )  	   to bind/initialize the session. */  	if( jd->flags & JFLAG_AUTHENTICATED && ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )  	{ -		if( !jabber_get_roster( gc ) ) +		if( !jabber_get_roster( gc ) || !jabber_get_privacy( gc ) )  			return XT_ABORT;  	} diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index a7783fcb..0411d4ad 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -27,7 +27,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data )  {  	struct gaim_connection *gc = data;  	struct jabber_data *jd = gc->proto_data; -	struct xt_node *query, *reply = NULL, *orig = NULL; +	struct xt_node *query, *reply = NULL, *orig = NULL, *c;  	char *s, *type, *xmlns;  	int st; @@ -108,10 +108,45 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data )  		account_online( gc );  	} +	if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:privacy" ) == 0 ) +	{ +		struct xt_node *node; +		 +		/* When receiving a list of lists: */ +		if( ( node = xt_find_node( query->children, "active" ) ) ) +		{ +			if( ( s = xt_find_attr( node, "name" ) ) ) +			{ +				set_t *set; +				 +				g_free( jd->privacy_active ); +				jd->privacy_active = g_strdup( s ); +				 +				/* Save it so the user can see it. */ +				if( ( set = set_find( &gc->acc->set, "privacy_list" ) ) ) +				{ +					g_free( set->value ); +					set->value = g_strdup( s ); +				} +				 +				if( !jabber_get_privacy( gc ) ) +					return XT_ABORT; +			} +		} +		/* When receiving an actual list: */ +		else if( ( node = xt_find_node( query->children, "list" ) ) ) +		{ +			xt_free_node( jd->privacy_list ); +			jd->privacy_list = xt_dup( node ); +		} +		else if( query->children == NULL ) +		{ +			/* What to do here if there is no privacy list defined yet... */ +		} +	}  	else if( strcmp( type, "result" ) == 0 && orig )  	{  		struct xt_node *c; -		  		if( !( jd->flags & JFLAG_AUTHENTICATED ) &&  		    ( c = xt_find_node( orig->children, "query" ) ) &&  		    ( c = xt_find_node( c->children, "username" ) ) && @@ -120,7 +155,7 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data )  			/* This happens when we just successfully authenticated  			   the old (non-SASL) way. */  			jd->flags |= JFLAG_AUTHENTICATED; -			if( !jabber_get_roster( gc ) ) +			if( !jabber_get_roster( gc ) || !jabber_get_privacy( gc ) )  				return XT_ABORT;  		}  		/* Tricky: Look for <bind> in the reply, because the server @@ -144,19 +179,39 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data )  			if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )  			{ -				if( !jabber_get_roster( gc ) ) +				if( !jabber_get_roster( gc ) || !jabber_get_privacy( gc ) )  					return XT_ABORT;  			}  		} +		else if( ( c = xt_find_node( orig->children, "query" ) ) && +		         ( c = xt_find_node( c->children, "active" ) ) ) +		{ +			/* We just successfully activated a (different) +			   privacy list. Fetch it now. */ +			g_free( jd->privacy_active ); +			jd->privacy_active = g_strdup( xt_find_attr( c, "name" ) ); +			 +			if( !jabber_get_privacy( gc ) ) +				return XT_ABORT; +		}  	}  	else if( strcmp( type, "error" ) == 0 )  	{ -		if( !( jd->flags & JFLAG_AUTHENTICATED ) ) +		if( !( jd->flags & JFLAG_AUTHENTICATED ) && +		    ( c = xt_find_node( orig->children, "query" ) ) && +		    ( c = xt_find_node( c->children, "username" ) ) && +		    c->text_len )  		{  			hide_login_progress( gc, "Authentication failure" );  			signoff( gc );  			return XT_ABORT;  		} +		else if( orig && +		         ( c = xt_find_node( orig->children, "query" ) ) && +		         ( c = xt_find_node( c->children, "active" ) ) ) +		{ +			serv_got_crap( gc, "Error while activating privacy list, maybe it doesn't exist" ); +		}  	}  	return XT_HANDLED; @@ -237,3 +292,57 @@ int jabber_remove_from_roster( struct gaim_connection *gc, char *handle )  	xt_free_node( node );  	return st;  } + +/* Request the privacy list from the server. We need this, because every +   time we remove/add something we have to send the whole new list to the +   server again... If no privacy list is specified yet, this function will +   first ask for the list of lists (XMPP supports multiple "privacy lists", +   don't ask me why), later we can then fetch the list we want to use. */ +int jabber_get_privacy( struct gaim_connection *gc ) +{ +	struct jabber_data *jd = gc->proto_data; +	struct xt_node *node = NULL; +	char *name; +	int st; +	 +	if( jd->privacy_active ) +	{ +		/* If we know what is the active list right now, fetch it. */ +		node = xt_new_node( "list", NULL, NULL ); +		xt_add_attr( node, "name", jd->privacy_active ); +	} +	/* Okay, we don't know yet. If the user set a specific list, we'll +	   activate that one. Otherwise, we should figure out which list is +	   currently active. */ +	else if( ( name = set_getstr( &gc->acc->set, "privacy_list" ) ) ) +	{ +		return jabber_set_privacy( gc, name ); +	} +	/* else: sending this packet without a <list/> element will give +	   a list of available lists and information about the currently +	   active list. */ +	 +	node = xt_new_node( "query", NULL, node ); +	xt_add_attr( node, "xmlns", "jabber:iq:privacy" ); +	node = jabber_make_packet( "iq", "get", NULL, node ); +	 +	st = jabber_write_packet( gc, node ); +	 +	xt_free_node( node ); +	return st; +} + +int jabber_set_privacy( struct gaim_connection *gc, char *name ) +{ +	struct xt_node *node; +	 +	node = xt_new_node( "active", NULL, NULL ); +	xt_add_attr( node, "name", name ); +	node = xt_new_node( "query", NULL, node ); +	xt_add_attr( node, "xmlns", "jabber:iq:privacy" ); +	 +	node = jabber_make_packet( "iq", "set", NULL, node ); +	jabber_cache_packet( gc, node ); +	 +	return jabber_write_packet( gc, node ); +} diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index df518956..8ec6b70c 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -41,6 +41,9 @@ static void jabber_acc_init( account_t *acc )  	s = set_add( &acc->set, "priority", "0", set_eval_priority, acc ); +	s = set_add( &acc->set, "privacy_list", NULL, NULL, acc ); +	/* TODO: Add evaluator. */ +	  	s = set_add( &acc->set, "resource", "BitlBee", NULL, acc );  	s->flags |= ACC_SET_OFFLINE_ONLY; @@ -80,12 +83,12 @@ static void jabber_login( account_t *acc )  	if( set_getbool( &acc->set, "ssl" ) )  	{ -		jd->ssl = ssl_connect( jd->server, set_getint( &acc->set, "port" ), jabber_connected_ssl, gc ); +		jd->ssl = ssl_connect( acc->server ? acc->server : jd->server, set_getint( &acc->set, "port" ), jabber_connected_ssl, gc );  		jd->fd = ssl_getfd( jd->ssl );  	}  	else  	{ -		jd->fd = proxy_connect( jd->server, set_getint( &acc->set, "port" ), jabber_connected_plain, gc ); +		jd->fd = proxy_connect( acc->server ? acc->server : jd->server, set_getint( &acc->set, "port" ), jabber_connected_plain, gc );  	}  } @@ -108,6 +111,9 @@ static void jabber_close( struct gaim_connection *gc )  	if( jd->tx_len )  		g_free( jd->txq ); +	xt_free_node( jd->privacy_list ); +	g_free( jd->privacy_active ); +	  	xt_free_node( jd->node_cache );  	xt_free( jd->xt ); diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index 8ca7d545..1ee02d3e 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -59,6 +59,10 @@ struct jabber_data  	struct jabber_away_state *away_state;  	char *away_message; +	/* Updates to this one should be synchronized using jabber_privacy_update(). */ +	struct xt_node *privacy_list; +	char *privacy_active; +	  	struct xt_node *node_cache;  }; @@ -68,12 +72,16 @@ struct jabber_away_state  	char *full_name;  }; +#define DEFAULT_PRIVACY_LIST "simple_blocklist" +  /* iq.c */  xt_status jabber_pkt_iq( struct xt_node *node, gpointer data );  int jabber_start_iq_auth( struct gaim_connection *gc );  int jabber_get_roster( struct gaim_connection *gc );  int jabber_add_to_roster( struct gaim_connection *gc, char *handle, char *name );  int jabber_remove_from_roster( struct gaim_connection *gc, char *handle ); +int jabber_get_privacy( struct gaim_connection *gc ); +int jabber_set_privacy( struct gaim_connection *gc, char *name );  /* message.c */  xt_status jabber_pkt_message( struct xt_node *node, gpointer data ); | 
