diff options
Diffstat (limited to 'protocols')
| -rw-r--r-- | protocols/msn/msn.c | 8 | ||||
| -rw-r--r-- | protocols/msn/msn.h | 5 | ||||
| -rw-r--r-- | protocols/msn/msn_util.c | 12 | ||||
| -rw-r--r-- | protocols/msn/ns.c | 200 | ||||
| -rw-r--r-- | protocols/msn/soap.c | 1 | 
5 files changed, 125 insertions, 101 deletions
| diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 0b9cffc2..4de2d822 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -67,6 +67,7 @@ static void msn_login( account_t *acc )  	md->ic = ic;  	md->away_state = msn_away_state_list; +	md->domaintree = g_tree_new( msn_domaintree_cmp );  	msn_connections = g_slist_append( msn_connections, ic );  } @@ -106,6 +107,9 @@ static void msn_logout( struct im_connection *ic )  		g_free( md->tokens[1] );  		g_free( md->lock_key ); +		g_tree_destroy( md->domaintree ); +		md->domaintree = NULL; +		  		while( md->grpq )  		{  			struct msn_groupadd *ga = md->grpq->data; @@ -335,11 +339,15 @@ static char *set_eval_display_name( set_t *set, char *value )  static void msn_buddy_data_add( bee_user_t *bu )  { +	struct msn_data *md = bu->ic->proto_data;  	bu->data = g_new0( struct msn_buddy_data, 1 ); +	g_tree_insert( md->domaintree, bu->handle, bu );  }  static void msn_buddy_data_free( bee_user_t *bu )  { +	struct msn_data *md = bu->ic->proto_data; +	g_tree_remove( md->domaintree, bu->handle );  	g_free( bu->data );  } diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 757359fe..6e447d7f 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -88,6 +88,7 @@ struct msn_data  	int buddycount;  	int groupcount;  	char **grouplist; +	GTree *domaintree;  };  struct msn_switchboard @@ -152,7 +153,7 @@ struct msn_handler_data  typedef enum  { -	MSN_BUDDY_FL = 1, +	MSN_BUDDY_FL = 1,   /* Warning: FL,AL,BL *must* be 1,2,4. */  	MSN_BUDDY_AL = 2,  	MSN_BUDDY_BL = 4,  	MSN_BUDDY_RL = 8, @@ -186,6 +187,7 @@ extern GSList *msn_switchboards;  /* ns.c */  gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond );  void msn_auth_got_passport_token( struct im_connection *ic, char *token ); +void msn_auth_got_contact_list( struct im_connection *ic );  /* msn_util.c */  int msn_write( struct im_connection *ic, char *s, int len ); @@ -200,6 +202,7 @@ char *msn_http_encode( const char *input );  void msn_msgq_purge( struct im_connection *ic, GSList **list );  gboolean msn_set_display_name( struct im_connection *ic, const char *rawname );  char *msn_p11_challenge( char *challenge ); +gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ );  /* tables.c */  const struct msn_away_state *msn_away_state_by_number( int number ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 65b12476..3a19d92f 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -527,3 +527,15 @@ char *msn_p11_challenge( char *challenge )  	return output;  } + +gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ ) +{ +	const char *a = a_, *b = b_; +	gint ret; +	 +	if( !( a = strchr( a, '@' ) ) || !( b = strchr( b, '@' ) ) || +	    ( ret = strcmp( a, b ) ) == 0 ) +		ret = strcmp( a_, b_ ); +	 +	return ret; +} diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index f0d6a58d..ffb21c47 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -26,15 +26,16 @@  #include <ctype.h>  #include "nogaim.h"  #include "msn.h" -#include "passport.h"  #include "md5.h"  #include "soap.h" +#include "xmltree.h"  static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond );  static int msn_ns_command( gpointer data, char **cmd, int num_parts );  static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts );  static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name ); +static void msn_ns_send_adl( struct im_connection *ic );  gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond )  { @@ -134,7 +135,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )  		char *server;  		int port; -		if( num_parts == 6 && strcmp( cmd[2], "NS" ) == 0 ) +		if( num_parts >= 6 && strcmp( cmd[2], "NS" ) == 0 )  		{  			b_event_remove( ic->inpa );  			ic->inpa = 0; @@ -155,7 +156,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )  			md->fd = proxy_connect( server, port, msn_ns_connected, ic );  		} -		else if( num_parts == 6 && strcmp( cmd[2], "SB" ) == 0 ) +		else if( num_parts >= 6 && strcmp( cmd[2], "SB" ) == 0 )  		{  			struct msn_switchboard *sb; @@ -260,109 +261,34 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )  			return( 0 );  		}  	} -	else if( strcmp( cmd[0], "SYN" ) == 0 ) +	else if( strcmp( cmd[0], "BLP" ) == 0 )  	{ -		if( num_parts == 5 ) -		{ -			int i, groupcount; -			 -			groupcount = atoi( cmd[4] ); -			if( groupcount > 0 ) -			{ -				/* valgrind says this is leaking memory, I'm guessing -				   that this happens during server redirects. */ -				if( md->grouplist ) -				{ -					for( i = 0; i < md->groupcount; i ++ ) -						g_free( md->grouplist[i] ); -					g_free( md->grouplist ); -				} -				 -				md->groupcount = groupcount; -				md->grouplist = g_new0( char *, md->groupcount ); -			} -			 -			md->buddycount = atoi( cmd[3] ); -			if( !*cmd[3] || md->buddycount == 0 ) -				msn_logged_in( ic ); -		} -		else -		{ -			/* Hrrm... This SYN reply doesn't really look like something we expected. -			   Let's assume everything is okay. */ -			 -			msn_logged_in( ic ); -		} +		msn_ns_send_adl( ic );  	} -	else if( strcmp( cmd[0], "LST" ) == 0 ) +	else if( strcmp( cmd[0], "ADL" ) == 0 )  	{ -		int list; -		 -		if( num_parts != 4 && num_parts != 5 ) -		{ -			imcb_error( ic, "Syntax error" ); -			imc_logout( ic, TRUE ); -			return( 0 ); -		} -		 -		http_decode( cmd[2] ); -		list = atoi( cmd[3] ); -		 -		if( list & 1 ) /* FL */ +		if( num_parts >= 3 && strcmp( cmd[2], "OK" ) == 0 )  		{ -			char *group = NULL; -			int num; +			char buf[1024]; +			char *fn_raw = set_getstr( &ic->acc->set, "display_name" ); +			char *fn; -			if( cmd[4] != NULL && sscanf( cmd[4], "%d", &num ) == 1 && num < md->groupcount ) -				group = md->grouplist[num]; +			if( fn_raw == NULL ) +				fn_raw = ic->acc->user; +			fn = g_malloc( strlen( fn_raw ) * 3 + 1 ); +			strcpy( fn, fn_raw ); +			http_encode( fn ); -			imcb_add_buddy( ic, cmd[1], group ); -			imcb_rename_buddy( ic, cmd[1], cmd[2] ); -		} -		if( list & 2 ) /* AL */ -		{ -			ic->permit = g_slist_append( ic->permit, g_strdup( cmd[1] ) ); -		} -		if( list & 4 ) /* BL */ -		{ -			ic->deny = g_slist_append( ic->deny, g_strdup( cmd[1] ) ); -		} -		if( list & 8 ) /* RL */ -		{ -			if( ( list & 6 ) == 0 ) -				msn_buddy_ask( ic, cmd[1], cmd[2] ); -		} -		 -		if( --md->buddycount == 0 ) -		{ -			if( ic->flags & OPT_LOGGED_IN ) -			{ -				imcb_log( ic, "Successfully transferred to different server" ); -				g_snprintf( buf, sizeof( buf ), "CHG %d %s %d\r\n", ++md->trId, md->away_state->code, 0 ); -				return( msn_write( ic, buf, strlen( buf ) ) ); -			} -			else -			{ -				msn_logged_in( ic ); -			} +			g_snprintf( buf, sizeof( buf ), "PRP %d MFN %s\r\n", +			            ++md->trId, fn ); +			g_free( fn ); +			 +			msn_write( ic, buf, strlen( buf ) );  		}  	} -	else if( strcmp( cmd[0], "LSG" ) == 0 ) +	else if( strcmp( cmd[0], "PRP" ) == 0 )  	{ -		int num; -		 -		if( num_parts != 4 ) -		{ -			imcb_error( ic, "Syntax error" ); -			imc_logout( ic, TRUE ); -			return( 0 ); -		} -		 -		http_decode( cmd[2] ); -		num = atoi( cmd[1] ); -		 -		if( num < md->groupcount ) -			md->grouplist[num] = g_strdup( cmd[2] ); +		imcb_connected( ic );  	}  	else if( strcmp( cmd[0], "CHL" ) == 0 )  	{ @@ -392,15 +318,15 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )  	{  		const struct msn_away_state *st; -		if( num_parts != 6 ) +		if( num_parts < 6 )  		{  			imcb_error( ic, "Syntax error" );  			imc_logout( ic, TRUE );  			return( 0 );  		} -		http_decode( cmd[4] ); -		imcb_rename_buddy( ic, cmd[3], cmd[4] ); +		http_decode( cmd[5] ); +		imcb_rename_buddy( ic, cmd[3], cmd[5] );  		st = msn_away_state_by_code( cmd[2] );  		if( !st ) @@ -786,6 +712,80 @@ void msn_auth_got_passport_token( struct im_connection *ic, char *token )  	}  } +void msn_auth_got_contact_list( struct im_connection *ic ) +{ +	char buf[64]; +	struct msn_data *md; +	 +	/* Dead connection? */ +	if( g_slist_find( msn_connections, ic ) == NULL ) +		return; +	 +	md = ic->proto_data; +	 +	 +	g_snprintf( buf, sizeof( buf ), "BLP %d %s\r\n", ++md->trId, "BL" ); +	msn_write( ic, buf, strlen( buf ) ); +} + +static gboolean msn_ns_send_adl_1( gpointer key, gpointer value, gpointer data ) +{ +	struct xt_node *adl = data, *d, *c; +	struct bee_user *bu = value; +	struct msn_buddy_data *bd = bu->data; +	char handle[strlen(bu->handle)]; +	char *domain; +	char l[4]; +	 +	strcpy( handle, bu->handle ); +	if( ( domain = strchr( handle, '@' ) ) == NULL ) /* WTF */ +		return FALSE;  +	*domain = '\0'; +	domain ++; +	 +	if( ( d = adl->children ) == NULL || +	    g_strcasecmp( xt_find_attr( d, "n" ), domain ) != 0 ) +	{ +		d = xt_new_node( "d", NULL, NULL ); +		xt_add_attr( d, "n", domain ); +		xt_insert_child( adl, d ); +	} +	 +	g_snprintf( l, sizeof( l ), "%d", bd->flags & 7 ); +	c = xt_new_node( "c", NULL, NULL ); +	xt_add_attr( c, "n", handle ); +	xt_add_attr( c, "l", l ); +	xt_add_attr( c, "t", "1" ); /* 1 means normal, 4 means mobile? */ +	xt_insert_child( d, c ); +	 +	return FALSE; +} + +static void msn_ns_send_adl( struct im_connection *ic ) +{ +	struct xt_node *adl; +	struct msn_data *md; +	char *adls, buf[64]; +	 +	/* Dead connection? */ +	if( g_slist_find( msn_connections, ic ) == NULL ) +		return; +	 +	md = ic->proto_data; +	 +	adl = xt_new_node( "ml", NULL, NULL ); +	xt_add_attr( adl, "l", "1" ); +	g_tree_foreach( md->domaintree, msn_ns_send_adl_1, adl ); +	adls = xt_to_string( adl ); +	 +	g_snprintf( buf, sizeof( buf ), "ADL %d %zd\r\n", ++md->trId, strlen( adls ) ); +	if( msn_write( ic, buf, strlen( buf ) ) ) +		msn_write( ic, adls, strlen( adls ) ); +	 +	g_free( adls ); +	xt_free_node( adl ); +} +  static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name )  {  	set_t *s; diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 62d58200..bb664861 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -577,6 +577,7 @@ static const struct xt_handler_entry msn_soap_addressbook_parser[] = {  static int msn_soap_addressbook_handle_response( struct msn_soap_req_data *soap_req )  { +	msn_auth_got_contact_list( soap_req->ic );  	return MSN_SOAP_OK;  } | 
