aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--protocols/msn/msn.c11
-rw-r--r--protocols/msn/msn.h14
-rw-r--r--protocols/msn/ns.c29
-rw-r--r--protocols/msn/soap.c76
-rw-r--r--protocols/msn/soap.h57
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__ */