diff options
| -rw-r--r-- | protocols/msn/msn.c | 11 | ||||
| -rw-r--r-- | protocols/msn/msn.h | 14 | ||||
| -rw-r--r-- | protocols/msn/ns.c | 29 | ||||
| -rw-r--r-- | protocols/msn/soap.c | 76 | ||||
| -rw-r--r-- | protocols/msn/soap.h | 57 | 
5 files changed, 163 insertions, 24 deletions
| diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 873a51ad..4b79cc26 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -82,6 +82,7 @@ static void msn_logout( struct im_connection *ic )  {  	struct msn_data *md = ic->proto_data;  	GSList *l; +	int i;  	if( md )  	{ @@ -106,9 +107,8 @@ static void msn_logout( struct im_connection *ic )  		msn_msgq_purge( ic, &md->msgq ); -		g_free( md->tokens[0] ); -		g_free( md->tokens[1] ); -		g_free( md->tokens[2] ); +		for( i = 0; i < sizeof( md->tokens ) / sizeof( md->tokens[0] ); i ++ ) +			g_free( md->tokens[i] );  		g_free( md->lock_key );  		while( md->groups ) @@ -336,6 +336,7 @@ static char *set_eval_display_name( set_t *set, char *value )  {  	account_t *acc = set->data;  	struct im_connection *ic = acc->ic; +	struct msn_data *md = ic->proto_data;  	if( strlen( value ) > 129 )  	{ @@ -343,6 +344,10 @@ static char *set_eval_display_name( set_t *set, char *value )  		return NULL;  	} +	if( md->flags & MSN_GOT_PROFILE_DN ) +		imcb_log( ic, "Warning: Persistent name changes for this account have to be done " +		              "in the profile. BitlBee doesn't currently support this." ); +	  	msn_soap_addressbook_set_display_name( ic, value );  	return msn_ns_set_display_name( ic, value ) ? value : NULL;  } diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 3ea8c503..7cb3241c 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -49,12 +49,9 @@  */  #define MSNP11_PROD_KEY "ILTXC!4IXB5FB*PX" -//PK}_A_0N_K%O?A9S"  #define MSNP11_PROD_ID  "PROD0119GSJUC$18" -//PROD0114ES4Z%Q5W"  #define MSNP_VER        "MSNP15"  #define MSNP_BUILD      "8.5.1288" -//"8.1.0178"  #define MSN_SB_NEW         -24062002 @@ -75,15 +72,23 @@  #define PROFILE_URL "http://members.msn.com/" +typedef enum +{ +	MSN_GOT_PROFILE = 1, +	MSN_GOT_PROFILE_DN = 2, +	MSN_DONE_ADL = 4, +} msn_flags_t; +  struct msn_data  {  	struct im_connection *ic;  	int fd;  	struct msn_handler_data *handler; +	msn_flags_t flags;  	int trId; -	char *tokens[3]; +	char *tokens[4];  	char *lock_key;  	GSList *msgq, *grpq; @@ -205,6 +210,7 @@ extern GSList *msn_switchboards;  gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond );  void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error );  void msn_auth_got_contact_list( struct im_connection *ic ); +int msn_ns_finish_login( struct im_connection *ic );  /* msn_util.c */  int msn_write( struct im_connection *ic, char *s, int len ); diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index c9b01ef2..4b779a58 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -258,23 +258,14 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )  	else if( strcmp( cmd[0], "BLP" ) == 0 )  	{  		msn_ns_send_adl_start( ic ); -		 -		if( md->adl_todo < 0 && !( ic->flags & OPT_LOGGED_IN ) ) -			return msn_ns_set_display_name( ic, set_getstr( &ic->acc->set, "display_name" ) ); +		return msn_ns_finish_login( ic );  	}  	else if( strcmp( cmd[0], "ADL" ) == 0 )  	{  		if( num_parts >= 3 && strcmp( cmd[2], "OK" ) == 0 )  		{  			msn_ns_send_adl( ic ); -			 -			if( md->adl_todo < 0 && !( ic->flags & OPT_LOGGED_IN ) ) -			{ -				msn_ns_send_adl( ic ); -				 -				if( md->adl_todo < 0 && !( ic->flags & OPT_LOGGED_IN ) ) -					return msn_ns_set_display_name( ic, set_getstr( &ic->acc->set, "display_name" ) ); -			} +			return msn_ns_finish_login( ic );  		}  		else if( num_parts >= 3 )  		{ @@ -817,3 +808,19 @@ static void msn_ns_send_adl_start( struct im_connection *ic )  	msn_ns_send_adl( ic );  } + +int msn_ns_finish_login( struct im_connection *ic ) +{ +	struct msn_data *md = ic->proto_data; +	 +	if( ic->flags & OPT_LOGGED_IN ) +		return 1; +	 +	if( md->adl_todo < 0 ) +		md->flags |= MSN_DONE_ADL; +	 +	if( ( md->flags & MSN_DONE_ADL ) && ( md->flags & MSN_GOT_PROFILE ) ) +		return msn_ns_set_display_name( ic, set_getstr( &ic->acc->set, "display_name" ) ); +	else +		return 1; +} diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index b717343f..410ff37c 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -208,7 +208,7 @@ static xt_status msn_soap_passport_sso_token( struct xt_node *node, gpointer dat  	    	sd->secret = g_strdup( p->text );  	*id -= '1'; -	if( *id >= 0 && *id <= 2 ) +	if( *id >= 0 && *id < sizeof( md->tokens ) / sizeof( md->tokens[0] ) )  	{  		g_free( md->tokens[(int)*id] );  		md->tokens[(int)*id] = g_strdup( node->text ); @@ -686,7 +686,6 @@ static xt_status msn_soap_addressbook_contact( struct xt_node *node, gpointer da  	     *display_name = NULL, *group_id = NULL;  	struct msn_soap_req_data *soap_req = data;  	struct im_connection *ic = soap_req->ic; -	struct msn_data *md = soap_req->ic->proto_data;  	struct msn_group *group;  	if( ( p = xt_find_path( node, "../contactId" ) ) ) @@ -704,14 +703,15 @@ static xt_status msn_soap_addressbook_contact( struct xt_node *node, gpointer da  	if( type && g_strcasecmp( type, "me" ) == 0 )  	{ -#if 0 -		g_free( md->myid ); -		md->myid = g_strdup( id ); -#endif		  		set_t *set = set_find( &ic->acc->set, "display_name" );  		g_free( set->value );  		set->value = g_strdup( display_name ); +		/* Try to fetch the profile; if the user has one, that's where +		   we can find the persistent display_name. */ +		if( ( p = xt_find_node( node->children, "CID" ) ) && p->text ) +			msn_soap_profile_get( ic, p->text ); +		  		return XT_HANDLED;  	} @@ -881,3 +881,67 @@ int msn_soap_ab_contact_del( struct im_connection *ic, bee_user_t *bu )  	                       msn_soap_ab_contact_del_handle_response,  	                       msn_soap_ab_contact_del_free_data );  } + + + +/* Storage stuff: Fetch profile. */ +static int msn_soap_profile_get_build_request( struct msn_soap_req_data *soap_req ) +{ +	struct msn_data *md = soap_req->ic->proto_data; +	 +	soap_req->url = g_strdup( SOAP_STORAGE_URL ); +	soap_req->action = g_strdup( SOAP_PROFILE_GET_ACTION ); +	soap_req->payload = g_markup_printf_escaped( SOAP_PROFILE_GET_PAYLOAD, +		md->tokens[3], (char*) soap_req->data ); +	 +	return 1; +} + +static xt_status msn_soap_profile_get_result( struct xt_node *node, gpointer data ) +{ +	struct msn_soap_req_data *soap_req = data; +	struct im_connection *ic = soap_req->ic; +	struct msn_data *md = soap_req->ic->proto_data; +	struct xt_node *dn; +	 +	if( ( dn = xt_find_node( node->children, "DisplayName" ) ) && dn->text ) +	{ +		set_t *set = set_find( &ic->acc->set, "display_name" ); +		g_free( set->value ); +		set->value = g_strdup( dn->text ); +		 +		md->flags |= MSN_GOT_PROFILE_DN; +	} +	 +	return XT_HANDLED; +} + +static const struct xt_handler_entry msn_soap_profile_get_parser[] = { +	{ "ExpressionProfile", "GetProfileResult", msn_soap_profile_get_result }, +	{ NULL,               NULL,     NULL                        } +}; + +static int msn_soap_profile_get_handle_response( struct msn_soap_req_data *soap_req ) +{ +	struct msn_data *md = soap_req->ic->proto_data; +	 +	md->flags |= MSN_GOT_PROFILE; +	msn_ns_finish_login( soap_req->ic ); +	 +	return MSN_SOAP_OK; +} + +static int msn_soap_profile_get_free_data( struct msn_soap_req_data *soap_req ) +{ +	g_free( soap_req->data ); +	return 0; +} + +int msn_soap_profile_get( struct im_connection *ic, const char *cid ) +{ +	return msn_soap_start( ic, g_strdup( cid ), +	                       msn_soap_profile_get_build_request, +	                       msn_soap_profile_get_parser, +	                       msn_soap_profile_get_handle_response, +	                       msn_soap_profile_get_free_data ); +} diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index 19a5c6ae..9fba5366 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -125,6 +125,15 @@                 "</wsp:AppliesTo>" \                 "<wsse:PolicyReference xmlns=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" URI=\"MBI_SSL\"></wsse:PolicyReference>" \             "</wst:RequestSecurityToken>" \ +           "<wst:RequestSecurityToken Id=\"RST3\">" \ +               "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \ +               "<wsp:AppliesTo>" \ +                   "<wsa:EndpointReference>" \ +                       "<wsa:Address>storage.msn.com</wsa:Address>" \ +                   "</wsa:EndpointReference>" \ +               "</wsp:AppliesTo>" \ +               "<wsse:PolicyReference xmlns=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" URI=\"MBI_SSL\"></wsse:PolicyReference>" \ +           "</wst:RequestSecurityToken>" \         "</ps:RequestMultipleSecurityTokens>" \     "</Body>" \  "</Envelope>" @@ -286,4 +295,52 @@ int msn_soap_addressbook_set_display_name( struct im_connection *ic, const char  int msn_soap_ab_contact_add( struct im_connection *ic, bee_user_t *bu );  int msn_soap_ab_contact_del( struct im_connection *ic, bee_user_t *bu ); + +#define SOAP_STORAGE_URL "https://storage.msn.com/storageservice/SchematizedStore.asmx" +#define SOAP_PROFILE_GET_ACTION "http://www.msn.com/webservices/storage/w10/GetProfile" + +#define SOAP_PROFILE_GET_PAYLOAD \ +"<?xml version=\"1.0\" encoding=\"utf-8\"?>" \ +"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ +  "<soap:Header xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ +    "<StorageApplicationHeader xmlns=\"http://www.msn.com/webservices/storage/w10\">" \ +      "<ApplicationID>Messenger Client 9.0</ApplicationID>" \ +      "<Scenario>Initial</Scenario>" \ +    "</StorageApplicationHeader>" \ +    "<StorageUserHeader xmlns=\"http://www.msn.com/webservices/storage/w10\">" \ +      "<Puid>0</Puid>" \ +      "<TicketToken>%s</TicketToken>" \ +    "</StorageUserHeader>" \ +  "</soap:Header>" \ +  "<soap:Body xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ +    "<GetProfile xmlns=\"http://www.msn.com/webservices/storage/w10\">" \ +      "<profileHandle>" \ +        "<Alias>" \ +          "<Name>%s</Name>" \ +          "<NameSpace>MyCidStuff</NameSpace>" \ +        "</Alias>" \ +        "<RelationshipName>MyProfile</RelationshipName>" \ +      "</profileHandle>" \ +      "<profileAttributes>" \ +        "<ResourceID>true</ResourceID>" \ +        "<DateModified>true</DateModified>" \ +        "<ExpressionProfileAttributes>" \ +          "<ResourceID>true</ResourceID>" \ +          "<DateModified>true</DateModified>" \ +          "<DisplayName>true</DisplayName>" \ +          "<DisplayNameLastModified>true</DisplayNameLastModified>" \ +          "<PersonalStatus>true</PersonalStatus>" \ +          "<PersonalStatusLastModified>true</PersonalStatusLastModified>" \ +          "<StaticUserTilePublicURL>true</StaticUserTilePublicURL>" \ +          "<Photo>true</Photo>" \ +          "<Flags>true</Flags>" \ +        "</ExpressionProfileAttributes>" \ +      "</profileAttributes>" \ +    "</GetProfile>" \ +  "</soap:Body>" \ +"</soap:Envelope>" + +int msn_soap_profile_get( struct im_connection *ic, const char *cid ); + +  #endif /* __SOAP_H__ */ | 
