changeset 19783:995aea35b05c

[gaim-migrate @ 16329] change it to windows Live Messenger Basic TWN authentication OK now committer: Ethan Blanton <elb@pidgin.im>
author Ma Yuan <mayuan2006@gmail.com>
date Sat, 24 Jun 2006 12:04:32 +0000
parents 0e1e59770cb0
children bc30c6270d9f
files src/protocols/msn/cmdproc.c src/protocols/msn/command.c src/protocols/msn/msn.c src/protocols/msn/msn.h src/protocols/msn/nexus.c src/protocols/msn/nexus.h src/protocols/msn/notification.c src/protocols/msn/servconn.c src/protocols/msn/session.c src/protocols/msn/sync.c
diffstat 10 files changed, 273 insertions(+), 232 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/msn/cmdproc.c	Thu Jun 22 08:33:54 2006 +0000
+++ b/src/protocols/msn/cmdproc.c	Sat Jun 24 12:04:32 2006 +0000
@@ -228,8 +228,7 @@
 {
 	MsnMsgTypeCb cb;
 
-	if (msn_message_get_content_type(msg) == NULL)
-	{
+	if (msn_message_get_content_type(msg) == NULL){
 		gaim_debug_misc("msn", "failed to find message content\n");
 		return;
 	}
@@ -237,8 +236,7 @@
 	cb = g_hash_table_lookup(cmdproc->cbs_table->msgs,
 							 msn_message_get_content_type(msg));
 
-	if (cb == NULL)
-	{
+	if (cb == NULL){
 		gaim_debug_warning("msn", "Unhandled content-type '%s'\n",
 						   msn_message_get_content_type(msg));
 
--- a/src/protocols/msn/command.c	Thu Jun 22 08:33:54 2006 +0000
+++ b/src/protocols/msn/command.c	Sat Jun 24 12:04:32 2006 +0000
@@ -36,12 +36,67 @@
 	return TRUE;
 }
 
+/*
+ * check the command is the command with payload content
+ *  if it is	return TRUE
+ *  else 		return FALSE
+ */
+static gboolean
+isPayloadCmd(char *str)
+{
+	if( (!strcmp(str,"ADL")) ||
+		(!strcmp(str,"GCF")) ||
+		(!strcmp(str,"MSG")) ||
+		(!strcmp(str,"QRY")) ||
+		(!strcmp(str,"RML")) ||
+		(!strcmp(str,"UBX")) ||
+		(!strcmp(str,"UBN")) ||
+		(!strcmp(str,"UUN")) ||
+		(!strcmp(str,"UUX"))){
+			return TRUE;
+		}
+
+	return FALSE;
+}
+
+/*get the payload positon*/
+int getPayloadPosition(char *str)
+{
+	/*because MSG has "MSG hotmail hotmail [payload length]"*/
+	if(!(strcmp(str,"MSG"))){
+		return 2;
+	}
+	return 1;
+}
+/*
+ * set command Payload length
+ */
+int
+setPayloadLen(MsnCommand *cmd)
+{
+	char * param;
+
+	if(isPayloadCmd(cmd->command)){
+		if(!(strcmp(cmd->command,"MSG"))){
+			param = cmd->params[2];
+		}else{
+			param = cmd->params[1];
+		}
+		cmd->payload_len = is_num(param) ? atoi(param) : 0;
+	}else{
+		cmd->payload_len = 0;
+	}
+	return 0;
+}
+
 MsnCommand *
 msn_command_from_string(const char *string)
 {
 	MsnCommand *cmd;
 	char *tmp;
 	char *param_start;
+	char *param;
+	int c;
 
 	g_return_val_if_fail(string != NULL, NULL);
 
@@ -51,11 +106,7 @@
 	cmd = g_new0(MsnCommand, 1);
 	cmd->command = tmp;
 
-	if (param_start)
-	{
-		char *param;
-		int c;
-
+	if (param_start){
 		*param_start++ = '\0';
 		cmd->params = g_strsplit(param_start, " ", 0);
 
@@ -65,9 +116,13 @@
 		param = cmd->params[0];
 
 		cmd->trId = is_num(param) ? atoi(param) : 0;
+	}else{
+		cmd->trId = 0;
 	}
-	else
-		cmd->trId = 0;
+
+	/*add payload Length checking*/
+	setPayloadLen(cmd);
+	gaim_debug_info("MaYuan","get payload len:%d\n",cmd->payload_len);
 
 	msn_command_ref(cmd);
 
--- a/src/protocols/msn/msn.c	Thu Jun 22 08:33:54 2006 +0000
+++ b/src/protocols/msn/msn.c	Sat Jun 24 12:04:32 2006 +0000
@@ -2025,10 +2025,10 @@
 	"MSN",                                            /**< name           */
 	VERSION,                                          /**< version        */
 	                                                  /**  summary        */
-	N_("MSN Protocol Plugin"),
+	N_("Windows Live Messenger Protocol Plugin"),
 	                                                  /**  description    */
-	N_("MSN Protocol Plugin"),
-	"Christian Hammond <chipx86@gnupdate.org>",       /**< author         */
+	N_("Windows Live Messenger Protocol Plugin"),
+	"MaYuan <mayuan2006@gmail.com>",				/**< author         */
 	GAIM_WEBSITE,                                     /**< homepage       */
 
 	msn_load,                                         /**< load           */
@@ -2047,11 +2047,11 @@
 	GaimAccountOption *option;
 
 	option = gaim_account_option_string_new(_("Server"), "server",
-											MSN_SERVER);
+											WLM_SERVER);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
 											   option);
 
-	option = gaim_account_option_int_new(_("Port"), "port", 1863);
+	option = gaim_account_option_int_new(_("Port"), "port", WLM_PORT);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
 											   option);
 
--- a/src/protocols/msn/msn.h	Thu Jun 22 08:33:54 2006 +0000
+++ b/src/protocols/msn/msn.h	Sat Jun 24 12:04:32 2006 +0000
@@ -62,6 +62,12 @@
 #define USEROPT_MSNPORT 4
 #define MSN_PORT 1863
 
+/* Windows Live Messenger Server*/
+#define WLM_SERVER			"muser.messenger.hotmail.com"
+#define WLM_PORT			1863
+#define WLM_PROT_VER		13
+#define WLM_MIN_PROTOCOL	13
+
 #define MSN_TYPING_RECV_TIMEOUT 6
 #define MSN_TYPING_SEND_TIMEOUT	4
 
--- a/src/protocols/msn/nexus.c	Thu Jun 22 08:33:54 2006 +0000
+++ b/src/protocols/msn/nexus.c	Sat Jun 24 12:04:32 2006 +0000
@@ -68,19 +68,25 @@
 msn_ssl_read(MsnNexus *nexus)
 {
 	gssize len;
+	gssize total_len = 0;
 	char temp_buf[4096];
 
-	if ((len = gaim_ssl_read(nexus->gsc, temp_buf,
+	if((len = gaim_ssl_read(nexus->gsc, temp_buf,
 			sizeof(temp_buf))) > 0)
 	{
+#if 0
+		g_string_append(nexus->read_buf,temp_buf);
+#else
+		total_len += len;
 		nexus->read_buf = g_realloc(nexus->read_buf,
 			nexus->read_len + len + 1);
 		strncpy(nexus->read_buf + nexus->read_len, temp_buf, len);
 		nexus->read_len += len;
 		nexus->read_buf[nexus->read_len] = '\0';
+#endif
 	}
-
-	return len;
+//	gaim_debug_info("MaYuan","nexus ssl read:{%s}\n",nexus->read_buf);
+	return total_len;
 }
 
 static void
@@ -91,6 +97,10 @@
 
 	total_len = strlen(nexus->write_buf);
 
+	/* 
+	 * write the content to SSL server,
+	 * We use SOAP to request Windows Live ID authentication
+	 */
 	len = gaim_ssl_write(nexus->gsc,
 		nexus->write_buf + nexus->written_len,
 		total_len - nexus->written_len);
@@ -157,12 +167,11 @@
 		nexus->input_handler = gaim_input_add(nexus->gsc->fd,
 			GAIM_INPUT_READ, nexus_login_written_cb, nexus);
 
-
+	/*read the request header*/
 	len = msn_ssl_read(nexus);
-
-	if (len < 0 && errno == EAGAIN)
+	if (len < 0 && errno == EAGAIN){
 		return;
-	else if (len < 0) {
+	}else if (len < 0) {
 		gaim_input_remove(nexus->input_handler);
 		nexus->input_handler = -1;
 		g_free(nexus->read_buf);
@@ -172,20 +181,22 @@
 		return;
 	}
 
+	if(nexus->read_buf == NULL){
+		return;
+	}
 	if (g_strstr_len(nexus->read_buf, nexus->read_len,
-			"\r\n\r\n") == NULL)
+			"</S:Envelope>") == NULL){
 		return;
+	}
 
 	gaim_input_remove(nexus->input_handler);
 	nexus->input_handler = -1;
-
 	gaim_ssl_close(nexus->gsc);
 	nexus->gsc = NULL;
 
-	gaim_debug_misc("msn", "ssl buffer: {%s}", nexus->read_buf);
+//	gaim_debug_misc("msn", "TWN Server Reply: {%s}", nexus->read_buf);
 
-	if (strstr(nexus->read_buf, "HTTP/1.1 302") != NULL)
-	{
+	if (strstr(nexus->read_buf, "HTTP/1.1 302") != NULL){
 		/* Redirect. */
 		char *location, *c;
 
@@ -221,15 +232,11 @@
 		gaim_ssl_connect(session->account, nexus->login_host,
 			GAIM_SSL_DEFAULT_PORT, login_connect_cb,
 			login_error_cb, nexus);
-	}
-	else if (strstr(nexus->read_buf, "HTTP/1.1 401 Unauthorized") != NULL)
-	{
+	}else if (strstr(nexus->read_buf, "HTTP/1.1 401 Unauthorized") != NULL){
 		const char *error;
 
-		if ((error = strstr(nexus->read_buf, "WWW-Authenticate")) != NULL)
-		{
-			if ((error = strstr(error, "cbtxt=")) != NULL)
-			{
+		if ((error = strstr(nexus->read_buf, "WWW-Authenticate")) != NULL)	{
+			if ((error = strstr(error, "cbtxt=")) != NULL){
 				const char *c;
 				char *temp;
 
@@ -243,45 +250,60 @@
 				g_free(temp);
 			}
 		}
-
 		msn_session_set_error(session, MSN_ERROR_AUTH, error);
-	}
-	else if (strstr(nexus->read_buf, "HTTP/1.1 200 OK"))
-	{
+	}else if (strstr(nexus->read_buf, "HTTP/1.1 200 OK")){
+		/*reply OK, we should process the SOAP body*/
 		char *base, *c;
 		char *login_params;
-
-#if 0
-		/* All your base are belong to us. */
-		base = buffer;
+		char *length_start,*length_end,*body_len;
 
-		/* For great cookie! */
-		while ((base = strstr(base, "Set-Cookie: ")) != NULL)
-		{
-			base += strlen("Set-Cookie: ");
-
-			c = strchr(base, ';');
+		char **elems, **cur, **tokens;
+		const char * cert_str;
 
-			session->login_cookies =
-				g_list_append(session->login_cookies,
-							  g_strndup(base, c - base));
-		}
-#endif
+		gaim_debug_info("MaYuan","Receive 200\n");
+#if 0
+		length_start = strstr(nexus->read_buf, "Content-Length: ");
+		length_start += strlen("Content-Length: ");
+		length_end = strstr(length_start, "\r\n");
+		body_len = g_strndup(length_start,length_end - length_start);
+//		gaim_debug_info("MaYuan","body length is :%s\n",body_len);
 
-		base  = strstr(nexus->read_buf, "Authentication-Info: ");
-
-		g_return_if_fail(base != NULL);
-
-		base  = strstr(base, "from-PP='");
-		base += strlen("from-PP='");
-		c     = strchr(base, '\'');
-
+		g_free(body_len);
+//		g_return_if_fail(body_len != NULL);
+#endif
+		//TODO: we should parse it using XML
+		base  = strstr(base, TWN_START_TOKEN);
+		base += strlen(TWN_START_TOKEN);
+//		gaim_debug_info("MaYuan","base is :%s\n",base);
+		c     = strstr(base, TWN_END_TOKEN);
+//		gaim_debug_info("MaYuan","c is :%s\n",c);
+//		gaim_debug_info("MaYuan","len is :%d\n",c-base);
 		login_params = g_strndup(base, c - base);
 
-		msn_got_login_params(session, login_params);
+		gaim_debug_info("msn", "TWN Cert: {%s}\n", login_params);
+
+		/* Parse the challenge data. */
+		elems = g_strsplit(login_params, "&amp;", 0);
+
+		for (cur = elems; *cur != NULL; cur++){
+				tokens = g_strsplit(*cur, "=", 2);
+				g_hash_table_insert(session->nexus->challenge_data, tokens[0], tokens[1]);
+				/* Don't free each of the tokens, only the array. */
+				g_free(tokens);
+		}
 
+		g_strfreev(elems);
+
+		cert_str = g_strdup_printf("t=%s&p=%s",
+			(char *)g_hash_table_lookup(nexus->challenge_data, "t"),
+			(char *)g_hash_table_lookup(nexus->challenge_data, "p")
+		);
+		msn_got_login_params(session, cert_str);
+
+		g_free(cert_str);
+//		g_free(body_len);
 		g_free(login_params);
-
+//		return;
 		msn_nexus_destroy(nexus);
 		session->nexus = NULL;
 		return;
@@ -290,7 +312,6 @@
 	g_free(nexus->read_buf);
 	nexus->read_buf = NULL;
 	nexus->read_len = 0;
-
 }
 
 
@@ -301,10 +322,11 @@
 	MsnNexus *nexus;
 	MsnSession *session;
 	char *username, *password;
-	char *request_str, *head, *tail;
+	char *request_str, *head, *tail,*challenge_str;
 	char *buffer = NULL;
 	guint32 ctint;
 
+	gaim_debug_info("MaYuan","starting Windows Live ID authentication\n");
 	nexus = data;
 	g_return_if_fail(nexus != NULL);
 
@@ -315,44 +337,44 @@
 
 	msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE);
 
-	username =
-		g_strdup(gaim_url_encode(gaim_account_get_username(session->account)));
-
-	password =
-		g_strdup(gaim_url_encode(gaim_connection_get_password(session->account->gc)));
-
-	ctint = strtoul((char *)g_hash_table_lookup(nexus->challenge_data, "ct"), NULL, 10) + 200;
+	username = g_strdup(gaim_account_get_username(session->account));
 
-	head = g_strdup_printf(
-		"GET %s HTTP/1.1\r\n"
-		"Authorization: Passport1.4 OrgVerb=GET,OrgURL=%s,sign-in=%s",
-		nexus->login_path,
-		(char *)g_hash_table_lookup(nexus->challenge_data, "ru"),
-		username);
+	password = g_strdup(gaim_connection_get_password(session->account->gc));
+//		g_strdup(gaim_url_encode(gaim_connection_get_password(session->account->gc)));
 
-	tail = g_strdup_printf(
-		"lc=%s,id=%s,tw=%s,fs=%s,ru=%s,ct=%" G_GUINT32_FORMAT ",kpp=%s,kv=%s,ver=%s,tpf=%s\r\n"
-		"User-Agent: MSMSGS\r\n"
-		"Host: %s\r\n"
-		"Connection: Keep-Alive\r\n"
-		"Cache-Control: no-cache\r\n",
+	challenge_str = g_strdup_printf(
+		"lc=%s&amp;id=%s&amp;tw=%s&amp;fs=%s&amp;ru=%s&amp;ct=%s&amp;kpp=%s&amp;kv=%s&amp;ver=%s&amp;rn=%s&amp;tpf=%s\r\n",
 		(char *)g_hash_table_lookup(nexus->challenge_data, "lc"),
 		(char *)g_hash_table_lookup(nexus->challenge_data, "id"),
 		(char *)g_hash_table_lookup(nexus->challenge_data, "tw"),
 		(char *)g_hash_table_lookup(nexus->challenge_data, "fs"),
 		(char *)g_hash_table_lookup(nexus->challenge_data, "ru"),
-		ctint,
+		(char *)g_hash_table_lookup(nexus->challenge_data, "ct"),
 		(char *)g_hash_table_lookup(nexus->challenge_data, "kpp"),
 		(char *)g_hash_table_lookup(nexus->challenge_data, "kv"),
 		(char *)g_hash_table_lookup(nexus->challenge_data, "ver"),
-		(char *)g_hash_table_lookup(nexus->challenge_data, "tpf"),
-		nexus->login_host);
+		(char *)g_hash_table_lookup(nexus->challenge_data, "rn"),
+		(char *)g_hash_table_lookup(nexus->challenge_data, "tpf")
+		);
+
+	/*build the SOAP windows Live ID XML body */
+	tail = g_strdup_printf(TWN_ENVELOP_TEMPLATE,username,password,challenge_str	);
 
-	buffer = g_strdup_printf("%s,pwd=XXXXXXXX,%s\r\n", head, tail);
-	request_str = g_strdup_printf("%s,pwd=%s,%s\r\n", head, password, tail);
+	nexus->login_path = g_strdup(TWN_POST_URL);
+	head = g_strdup_printf(
+					"POST %s HTTP/1.1\r\n"
+					"Accept: text/*\r\n"
+					"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n"
+					"Host: %s\r\n"
+					"Content-Length: %d\r\n"
+					"Connection: Keep-Alive\r\n"
+					"Cache-Control: no-cache\r\n\r\n",
+					nexus->login_path,nexus->login_host,strlen(tail));
 
-	gaim_debug_misc("msn", "Sending: {%s}\n", buffer);
+	request_str = g_strdup_printf("%s%s", head,tail);
+//	gaim_debug_misc("msn", "TWN Sending: {%s}\n", request_str);
 
+//	g_free(nexus->login_path);
 	g_free(buffer);
 	g_free(head);
 	g_free(tail);
@@ -372,123 +394,18 @@
 	nexus_write_cb(nexus, gsc->fd, GAIM_INPUT_WRITE);
 
 	return;
-
-
 }
 
-static void
-nexus_connect_written_cb(gpointer data, gint source, GaimInputCondition cond)
+/**************************************************************************
+ * Connect
+ **************************************************************************/
+void
+msn_nexus_connect(MsnNexus *nexus)
 {
-	MsnNexus *nexus = data;
-	int len;
-	char *da_login;
-	char *base, *c;
-
-	if (nexus->input_handler == -1)
-		nexus->input_handler = gaim_input_add(nexus->gsc->fd,
-			GAIM_INPUT_READ, nexus_connect_written_cb, nexus);
-
-	/* Get the PassportURLs line. */
-	len = msn_ssl_read(nexus);
-
-	if (len < 0 && errno == EAGAIN)
-		return;
-	else if (len < 0) {
-		gaim_input_remove(nexus->input_handler);
-		nexus->input_handler = -1;
-		g_free(nexus->read_buf);
-		nexus->read_buf = NULL;
-		nexus->read_len = 0;
-		/* TODO: error handling */
-		return;
-	}
-
-	if (g_strstr_len(nexus->read_buf, nexus->read_len,
-			"\r\n\r\n") == NULL)
-		return;
-
-	gaim_input_remove(nexus->input_handler);
-	nexus->input_handler = -1;
-
-	base = strstr(nexus->read_buf, "PassportURLs");
-
-	if (base == NULL)
-	{
-		g_free(nexus->read_buf);
-		nexus->read_buf = NULL;
-		nexus->read_len = 0;
-		return;
-	}
-
-	if ((da_login = strstr(base, "DALogin=")) != NULL)
-	{
-		if ((da_login = strchr(da_login, '=')) != NULL)
-			da_login++;
-
-		if ((c = strchr(da_login, ',')) != NULL)
-			*c = '\0';
-
-		if ((c = strchr(da_login, '/')) != NULL)
-		{
-			nexus->login_path = g_strdup(c);
-			*c = '\0';
-		}
-
-		nexus->login_host = g_strdup(da_login);
-	}
-
-	g_free(nexus->read_buf);
-	nexus->read_buf = NULL;
-	nexus->read_len = 0;
-
-	gaim_ssl_close(nexus->gsc);
-	nexus->gsc = NULL;
-
-	/* Now begin the connection to the login server. */
+	/*  Authenticate via Windows Live ID. */
+	gaim_debug_info("MaYuan","msn_nexus_connect...\n");
+	nexus->login_host = g_strdup(TWN_SERVER);
 	gaim_ssl_connect(nexus->session->account, nexus->login_host,
 		GAIM_SSL_DEFAULT_PORT, login_connect_cb, login_error_cb,
 		nexus);
 }
-
-
-/**************************************************************************
- * Connect
- **************************************************************************/
-
-static void
-nexus_connect_cb(gpointer data, GaimSslConnection *gsc,
-				 GaimInputCondition cond)
-{
-	MsnNexus *nexus;
-	MsnSession *session;
-
-	nexus = data;
-	g_return_if_fail(nexus != NULL);
-
-	session = nexus->session;
-	g_return_if_fail(session != NULL);
-
-	nexus->gsc = gsc;
-
-	msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH);
-
-	nexus->write_buf = g_strdup("GET /rdr/pprdr.asp\r\n\r\n");
-	nexus->written_len = 0;
-
-	nexus->read_len = 0;
-
-	nexus->written_cb = nexus_connect_written_cb;
-
-	nexus->input_handler = gaim_input_add(gsc->fd, GAIM_INPUT_WRITE,
-		nexus_write_cb, nexus);
-
-	nexus_write_cb(nexus, gsc->fd, GAIM_INPUT_WRITE);
-}
-
-void
-msn_nexus_connect(MsnNexus *nexus)
-{
-	gaim_ssl_connect(nexus->session->account, "nexus.passport.com",
-		GAIM_SSL_DEFAULT_PORT, nexus_connect_cb,
-		login_error_cb, nexus);
-}
--- a/src/protocols/msn/nexus.h	Thu Jun 22 08:33:54 2006 +0000
+++ b/src/protocols/msn/nexus.h	Sat Jun 24 12:04:32 2006 +0000
@@ -24,6 +24,52 @@
 #ifndef _MSN_NEXUS_H_
 #define _MSN_NEXUS_H_
 
+#define TWN_SERVER	"loginnet.passport.com"
+
+#define TWN_START_TOKEN		"<wsse:BinarySecurityToken Id=\"PPToken1\">"
+#define TWN_END_TOKEN		"</wsse:BinarySecurityToken>"
+
+#define TWN_POST_URL			"/RST.srf"
+#define TWN_ENVELOP_TEMPLATE 	"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"\
+						"<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\" xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2002/12/policy\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\" xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2004/04/sc\" xmlns:wst=\"http://schemas.xmlsoap.org/ws/2004/04/trust\">"\
+						"<Header>"\
+						"<ps:AuthInfo xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"PPAuthInfo\">"\
+						"<ps:HostingApp>{3:B}</ps:HostingApp>"\
+						"<ps:BinaryVersion>4</ps:BinaryVersion>"\
+						"<ps:UIVersion>1</ps:UIVersion>"\
+						"<ps:Cookies></ps:Cookies>"\
+						"<ps:RequestParams>AQAAAAIAAABsYwQAAAAzMDg0</ps:RequestParams>"\
+						"</ps:AuthInfo>"\
+						"<wsse:Security>"\
+						"<wsse:UsernameToken Id=\"user\">"\
+						"<wsse:Username>%s</wsse:Username>"\
+						"<wsse:Password>%s</wsse:Password>"\
+						"</wsse:UsernameToken>"\
+						"</wsse:Security>"\
+						"</Header><Body>"\
+						"<ps:RequestMultipleSecurityTokens xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"RSTS\">"\
+						"<wst:RequestSecurityToken Id=\"RST0\">"\
+						"<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\
+						"<wsp:AppliesTo>"\
+						"<wsa:EndpointReference>"\
+						"<wsa:Address>http://Passport.NET/tb</wsa:Address>"\
+						"</wsa:EndpointReference>"\
+						"</wsp:AppliesTo>"\
+						"</wst:RequestSecurityToken>"\
+						"<wst:RequestSecurityToken Id=\"RST1\">"\
+						"<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\
+						"<wsp:AppliesTo>"\
+						"<wsa:EndpointReference>"\
+						"<wsa:Address>messenger.msn.com</wsa:Address>"\
+						"</wsa:EndpointReference>"\
+						"</wsp:AppliesTo>"\
+						"<wsse:PolicyReference URI=\"?%s\">"\
+						"</wsse:PolicyReference>"\
+						"</wst:RequestSecurityToken>"\
+						"</ps:RequestMultipleSecurityTokens>"\
+						"</Body>"\
+						"</Envelope>"
+
 typedef struct _MsnNexus MsnNexus;
 
 struct _MsnNexus
--- a/src/protocols/msn/notification.c	Thu Jun 22 08:33:54 2006 +0000
+++ b/src/protocols/msn/notification.c	Sat Jun 24 12:04:32 2006 +0000
@@ -102,9 +102,9 @@
 	account = session->account;
 
 	/* Allocate an array for CVR0, NULL, and all the versions */
-	a = c = g_new0(char *, session->protocol_ver - 8 + 3);
+	a = c = g_new0(char *, session->protocol_ver - WLM_MIN_PROTOCOL + 3);
 
-	for (i = session->protocol_ver; i >= 8; i--)
+	for (i = session->protocol_ver; i >= WLM_MIN_PROTOCOL; i--)
 		*c++ = g_strdup_printf("MSNP%d", i);
 
 	*c++ = g_strdup("CVR0");
@@ -230,9 +230,8 @@
 	account = session->account;
 	gc = gaim_account_get_connection(account);
 
-	if (!g_ascii_strcasecmp(cmd->params[1], "OK"))
-	{
-		/* OK */
+	if (!g_ascii_strcasecmp(cmd->params[1], "OK")){
+		/* authenticate OK */
 		const char *friendly = gaim_url_decode(cmd->params[3]);
 
 		gaim_connection_set_display_name(gc, friendly);
@@ -240,9 +239,7 @@
 		msn_session_set_login_step(session, MSN_LOGIN_STEP_SYN);
 
 		msn_cmdproc_send(cmdproc, "SYN", "%s", "0");
-	}
-	else if (!g_ascii_strcasecmp(cmd->params[1], "TWN"))
-	{
+	}else if (!g_ascii_strcasecmp(cmd->params[1], "TWN")){
 		/* Passport authentication */
 		char **elems, **cur, **tokens;
 
@@ -252,8 +249,7 @@
 
 		elems = g_strsplit(cmd->params[3], ",", 0);
 
-		for (cur = elems; *cur != NULL; cur++)
-		{
+		for (cur = elems; *cur != NULL; cur++){
 				tokens = g_strsplit(*cur, "=", 2);
 				g_hash_table_insert(session->nexus->challenge_data, tokens[0], tokens[1]);
 				/* Don't free each of the tokens, only the array. */
@@ -322,8 +318,12 @@
 		return;
 	}
 
+	/*
+	 * Windows Live Messenger 8.0 
+	 * Notice :CVR String discriminate!
+	 */
 	msn_cmdproc_send(cmdproc, "CVR",
-					 "0x0409 winnt 5.1 i386 MSNMSGR 6.0.0602 MSMSGS %s",
+					 "0x0409 winnt 5.1 i386 MSG80BETA 8.0.0689 msmsgs %s",
 					 gaim_account_get_username(account));
 }
 
@@ -379,16 +379,16 @@
 static void
 msg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
+	gaim_debug_info("MaYuan","Processing MSG... \n");
+	if(cmd->payload_len == 0){
+		return;
+	}
 	/* NOTE: cmd is not always cmdproc->last_cmd, sometimes cmd is a queued
 	 * command and we are processing it */
-
-	if (cmd->payload == NULL)
-	{
+	if (cmd->payload == NULL){
 		cmdproc->last_cmd->payload_cb  = msg_cmd_post;
 		cmdproc->servconn->payload_len = atoi(cmd->params[2]);
-	}
-	else
-	{
+	}else{
 		g_return_if_fail(cmd->payload_cb != NULL);
 
 		cmd->payload_cb(cmdproc, cmd, cmd->payload, cmd->payload_len);
@@ -1118,6 +1118,27 @@
 	g_free(host);
 }
 
+static void
+gcf_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+{
+	gaim_debug_info("MaYuan","Processing GCF... \n");
+	if(cmd->payload_len == 0){
+//		cmd->payload_len = is_num(cmd->params[1]) ? atoi(cmd->params[1]) : 0;
+		return;
+	}
+	/*get the payload content*/
+}
+
+static void
+sbs_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+{
+	gaim_debug_info("MaYuan","Processing SBS... \n");
+	if(cmd->payload_len == 0){
+		return;
+	}
+	/*get the payload content*/
+}
+
 /**************************************************************************
  * Message Types
  **************************************************************************/
@@ -1387,6 +1408,7 @@
 	msn_table_add_cmd(cbs_table, "REM", "REM", rem_cmd);
 	msn_table_add_cmd(cbs_table, "USR", "USR", usr_cmd);
 	msn_table_add_cmd(cbs_table, "USR", "XFR", xfr_cmd);
+	msn_table_add_cmd(cbs_table, "USR", "GCF", gcf_cmd);
 	msn_table_add_cmd(cbs_table, "SYN", "SYN", syn_cmd);
 	msn_table_add_cmd(cbs_table, "CVR", "CVR", cvr_cmd);
 	msn_table_add_cmd(cbs_table, "VER", "VER", ver_cmd);
@@ -1402,6 +1424,8 @@
 	/* Asynchronous */
 	msn_table_add_cmd(cbs_table, NULL, "IPG", ipg_cmd);
 	msn_table_add_cmd(cbs_table, NULL, "MSG", msg_cmd);
+	msn_table_add_cmd(cbs_table, NULL, "GCF", gcf_cmd);
+	msn_table_add_cmd(cbs_table, NULL, "SBS", sbs_cmd);
 	msn_table_add_cmd(cbs_table, NULL, "NOT", not_cmd);
 
 	msn_table_add_cmd(cbs_table, NULL, "CHL", chl_cmd);
--- a/src/protocols/msn/servconn.c	Thu Jun 22 08:33:54 2006 +0000
+++ b/src/protocols/msn/servconn.c	Sat Jun 24 12:04:32 2006 +0000
@@ -428,14 +428,12 @@
 
 		servconn->rx_len -= cur_len;
 
-		if (servconn->payload_len)
-		{
+		if (servconn->payload_len){
 			msn_cmdproc_process_payload(servconn->cmdproc, cur, cur_len);
 			servconn->payload_len = 0;
-		}
-		else
-		{
+		}else{
 			msn_cmdproc_process_cmd_text(servconn->cmdproc, cur);
+			servconn->payload_len = servconn->cmdproc->last_cmd->payload_len;
 		}
 	} while (servconn->connected && !servconn->wasted && servconn->rx_len > 0);
 
--- a/src/protocols/msn/session.c	Thu Jun 22 08:33:54 2006 +0000
+++ b/src/protocols/msn/session.c	Sat Jun 24 12:04:32 2006 +0000
@@ -43,7 +43,7 @@
 	session->user = msn_user_new(session->userlist,
 								 gaim_account_get_username(account), NULL);
 
-	session->protocol_ver = 9;
+	session->protocol_ver = WLM_PROT_VER;
 	session->conv_seq = 1;
 
 	return session;
--- a/src/protocols/msn/sync.c	Thu Jun 22 08:33:54 2006 +0000
+++ b/src/protocols/msn/sync.c	Sat Jun 24 12:04:32 2006 +0000
@@ -35,8 +35,7 @@
 
 	list_name = cmd->params[0];
 
-	if (!g_ascii_strcasecmp(list_name, "AL"))
-	{
+	if (!g_ascii_strcasecmp(list_name, "AL")){
 		/*
 		 * If the current setting is AL, messages from users who
 		 * are not in BL will be delivered.
@@ -44,9 +43,7 @@
 		 * In other words, deny some.
 		 */
 		gc->account->perm_deny = GAIM_PRIVACY_DENY_USERS;
-	}
-	else
-	{
+	}else{
 		/* If the current setting is BL, only messages from people
 		 * who are in the AL will be delivered.
 		 *