changeset 19784:bc30c6270d9f

[gaim-migrate @ 16473] add the Framework of SOAP request Now can retrieve the Contact via SOAP Request. so many bug still exist! commited by MaYuan<mayuan2006@gmail.com> committer: Ethan Blanton <elb@pidgin.im>
author Ma Yuan <mayuan2006@gmail.com>
date Sun, 09 Jul 2006 16:48:25 +0000
parents 995aea35b05c
children 852b32710df0
files src/protocols/msn/Makefile.am src/protocols/msn/cmdproc.c src/protocols/msn/command.c src/protocols/msn/contact.c src/protocols/msn/contact.h src/protocols/msn/msg.c src/protocols/msn/msn-utils.c src/protocols/msn/msn.c src/protocols/msn/nexus.c src/protocols/msn/nexus.h src/protocols/msn/notification.c src/protocols/msn/notification.h src/protocols/msn/session.c src/protocols/msn/session.h src/protocols/msn/soap.c src/protocols/msn/soap.h src/protocols/msn/table.c
diffstat 17 files changed, 875 insertions(+), 271 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/msn/Makefile.am	Sat Jun 24 12:04:32 2006 +0000
+++ b/src/protocols/msn/Makefile.am	Sun Jul 09 16:48:25 2006 +0000
@@ -8,6 +8,8 @@
 	cmdproc.h \
 	command.c \
 	command.h \
+	contact.c\
+	contact.h\
 	dialog.c \
 	dialog.h \
 	directconn.c \
@@ -46,6 +48,8 @@
 	slpmsg.h \
 	slpsession.c \
 	slpsession.h \
+	soap.c\
+	soap.h\
 	state.c \
 	state.h \
 	switchboard.c \
--- a/src/protocols/msn/cmdproc.c	Sat Jun 24 12:04:32 2006 +0000
+++ b/src/protocols/msn/cmdproc.c	Sun Jul 09 16:48:25 2006 +0000
@@ -127,8 +127,7 @@
 		trans->callbacks = g_hash_table_lookup(cmdproc->cbs_table->cmds,
 											   trans->command);
 
-	if (trans->payload != NULL)
-	{
+	if (trans->payload != NULL){
 		data = g_realloc(data, len + trans->payload_len);
 		memcpy(data + len, trans->payload, trans->payload_len);
 		len += trans->payload_len;
--- a/src/protocols/msn/command.c	Sat Jun 24 12:04:32 2006 +0000
+++ b/src/protocols/msn/command.c	Sun Jul 09 16:48:25 2006 +0000
@@ -42,7 +42,7 @@
  *  else 		return FALSE
  */
 static gboolean
-isPayloadCmd(char *str)
+msn_check_payload_cmd(char *str)
 {
 	if( (!strcmp(str,"ADL")) ||
 		(!strcmp(str,"GCF")) ||
@@ -60,7 +60,7 @@
 }
 
 /*get the payload positon*/
-int getPayloadPosition(char *str)
+int msn_get_payload_position(char *str)
 {
 	/*because MSG has "MSG hotmail hotmail [payload length]"*/
 	if(!(strcmp(str,"MSG"))){
@@ -72,11 +72,11 @@
  * set command Payload length
  */
 int
-setPayloadLen(MsnCommand *cmd)
+msn_set_payload_len(MsnCommand *cmd)
 {
 	char * param;
 
-	if(isPayloadCmd(cmd->command)){
+	if(msn_check_payload_cmd(cmd->command)){
 		if(!(strcmp(cmd->command,"MSG"))){
 			param = cmd->params[2];
 		}else{
@@ -121,7 +121,7 @@
 	}
 
 	/*add payload Length checking*/
-	setPayloadLen(cmd);
+	msn_set_payload_len(cmd);
 	gaim_debug_info("MaYuan","get payload len:%d\n",cmd->payload_len);
 
 	msn_command_ref(cmd);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/msn/contact.c	Sun Jul 09 16:48:25 2006 +0000
@@ -0,0 +1,220 @@
+/**
+ * @file contact.c 
+ * 	get MSN contacts via SOAP request
+ *	created by MaYuan<mayuan2006@gmail.com>
+ *
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "msn.h"
+#include "soap.h"
+#include "contact.h"
+#include "xmlnode.h"
+
+/*new a contact*/
+MsnContact *
+msn_contact_new(MsnSession *session)
+{
+	MsnContact *contact;
+
+	contact = g_new0(MsnContact, 1);
+	contact->session = session;
+	contact->soapconn = msn_soap_new(session);
+	contact->soapconn->parent = contact;
+	contact->soapconn->ssl_conn = 1;
+
+	return contact;
+}
+
+/*destroy the contact*/
+void
+msn_contact_destroy(MsnContact *contact)
+{
+	msn_soap_destroy(contact->soapconn);
+	g_free(contact);
+}
+
+/*contact SOAP server login error*/
+static void
+msn_contact_login_error_cb(GaimSslConnection *gsc, GaimSslErrorType error, void *data)
+{
+	MsnSoapConn *soapconn = data;
+	MsnSession *session;
+
+	session = soapconn->session;
+	g_return_if_fail(session != NULL);
+
+	msn_session_set_error(session, MSN_ERROR_SERV_DOWN, _("Unable to connect to contact server"));
+}
+
+/*msn contact SOAP server connect process*/
+static void
+msn_contact_login_connect_cb(gpointer data, GaimSslConnection *gsc,
+				 GaimInputCondition cond)
+{
+	MsnSoapConn *soapconn = data;
+	MsnSession * session;
+	MsnContact *contact;
+
+	contact = soapconn->parent;
+	g_return_if_fail(contact != NULL);
+
+	session = contact->session;
+	g_return_if_fail(session != NULL);
+
+	/*login ok!We can retrieve the contact list*/
+	msn_get_contact_list(contact);
+}
+
+static void
+msn_parse_contact_list(MsnContact * contact)
+{
+	xmlnode * node,*envelop,*body,*response,*result,*services,*service,*memberships;
+	xmlnode *membershipnode,*members,*member,*passport,*role;
+	int len;
+
+	gaim_debug_misc("xml","parse contact list:{%s}\nsize:%d\n",contact->soapconn->body,contact->soapconn->body_len);
+	node = 	xmlnode_from_str(contact->soapconn->body, contact->soapconn->body_len);
+//	node = 	xmlnode_from_str(contact->soapconn->body, -1);
+
+	if(node == NULL){
+		gaim_debug_misc("xml","parse from str err!\n");
+		return;
+	}
+	gaim_debug_misc("xml","node{%p},name:%s,child:%s,last:%s\n",node,node->name,node->child->name,node->lastchild->name);
+	body = xmlnode_get_child(node,"Body");
+	gaim_debug_misc("xml","body{%p},name:%s\n",body,body->name);
+	response = xmlnode_get_child(body,"FindMembershipResponse");
+	gaim_debug_misc("xml","response{%p},name:%s\n",response,response->name);
+	result =xmlnode_get_child(response,"FindMembershipResult");
+	gaim_debug_misc("xml","result{%p},name:%s\n",result,result->name);
+	services =xmlnode_get_child(result,"Services");
+	gaim_debug_misc("xml","services{%p},name:%s\n",services,services->name);
+	service =xmlnode_get_child(services,"Service");
+	gaim_debug_misc("xml","service{%p},name:%s\n",service,service->name);
+	memberships =xmlnode_get_child(service,"Memberships");
+	gaim_debug_misc("xml","memberships{%p},name:%s\n",memberships,memberships->name);
+	for(membershipnode = xmlnode_get_child(memberships, "Membership"); membershipnode;
+					membershipnode = xmlnode_get_next_twin(membershipnode)){
+		role = xmlnode_get_child(membershipnode,"MemberRole");
+		gaim_debug_misc("memberrole","role:%s\n",xmlnode_get_data(role));
+		members = xmlnode_get_child(membershipnode,"Members");
+			for(member = xmlnode_get_child(members, "Member"); member;
+					member = xmlnode_get_next_twin(member)){
+				passport = xmlnode_get_child(member,"PassportName");
+				gaim_debug_misc("Passport","name:%s\n",xmlnode_get_data(passport));
+			}
+	}
+
+	xmlnode_free(node);
+}
+
+static void
+msn_get_contact_list_cb(gpointer data, gint source, GaimInputCondition cond)
+{
+	MsnSoapConn * soapconn = data;	
+	MsnContact *contact;
+	MsnSession *session;
+
+	contact = soapconn->parent;
+	g_return_if_fail(contact != NULL);
+	session = soapconn->session;
+	g_return_if_fail(session != NULL);
+
+//	gaim_debug_misc("msn", "soap contact server Reply: {%s}\n", soapconn->read_buf);
+	msn_parse_contact_list(contact);
+}
+
+static void
+msn_contact_written_cb(gpointer data, gint source, GaimInputCondition cond)
+{
+	MsnSoapConn * soapconn = data;	
+
+	gaim_debug_info("MaYuan","finish contact written\n");
+	soapconn->read_cb = msn_get_contact_list_cb;
+	msn_soap_read_cb(data,source,cond);
+}
+
+void
+msn_get_contact_list(MsnContact * contact)
+{
+	char * soap_head = NULL;
+	char * soap_body = NULL;
+	char * request_str = NULL;
+
+	gaim_debug_info("MaYuan","msn_get_contact_list()...\n");
+	contact->soapconn->login_path = g_strdup(MSN_GET_CONTACT_POST_URL);
+	soap_body = g_strdup_printf(MSN_GET_CONTACT_TEMPLATE);
+	soap_head = g_strdup_printf(
+					"POST %s HTTP/1.1\r\n"
+					"SOAPAction: http://www.msn.com/webservices/AddressBook/FindMembership\r\n"
+					"Content-Type:text/xml; charset=utf-8\r\n"
+					"Cookie: MSPAuth=%s\r\n"
+					"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n"
+					"Accept: text/*\r\n"
+					"Host: %s\r\n"
+					"Content-Length: %d\r\n"
+					"Connection: Keep-Alive\r\n"
+					"Cache-Control: no-cache\r\n\r\n",
+					contact->soapconn->login_path,
+					contact->session->passport_info.mspauth,
+					contact->soapconn->login_host,
+					strlen(soap_body)
+					);
+	request_str = g_strdup_printf("%s%s", soap_head,soap_body);
+	g_free(soap_head);
+	g_free(soap_body);
+
+//	gaim_debug_info("MaYuan","send to contact server{%s}\n",request_str);
+	msn_soap_write(contact->soapconn,request_str,msn_contact_written_cb);
+}
+
+msn_add_contact()
+{
+}
+
+msn_delete_contact()
+{
+}
+
+msn_block_contact()
+{
+}
+
+msn_unblock_contact()
+{
+}
+
+msn_get_gleams()
+{
+}
+
+void
+msn_contact_connect(MsnContact *contact)
+{
+	/*  Authenticate via Windows Live ID. */
+	gaim_debug_info("MaYuan","msn_contact_connect...\n");
+
+	msn_soap_init(contact->soapconn,MSN_CONTACT_SERVER,1,
+					msn_contact_login_connect_cb,
+					msn_contact_login_error_cb);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/msn/contact.h	Sun Jul 09 16:48:25 2006 +0000
@@ -0,0 +1,118 @@
+/**
+ * @file contact.h			Header file for contact.c
+ *	Author
+ * 		MaYuan<mayuan2006@gmail.com>
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _MSN_CONTACT_H_
+#define _MSN_CONTACT_H_
+
+#define MSN_CONTACT_SERVER	"contacts.msn.com"
+
+#define MSN_GET_CONTACT_POST_URL	"/abservice/SharingService.asmx"
+#define MSN_GET_CONTACT_TEMPLATE	"<?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/\">"\
+		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+			"<ApplicationId xmlns=\"http://www.msn.com/webservices/AddressBook\">09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId>"\
+			"<IsMigration xmlns=\"http://www.msn.com/webservices/AddressBook\">false</IsMigration>"\
+			"<PartnerScenario xmlns=\"http://www.msn.com/webservices/AddressBook\">Initial</PartnerScenario>"\
+		 "</ABApplicationHeader>"\
+		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+		"<ManagedGroupRequest xmlns=\"http://www.msn.com/webservices/AddressBook\">false</ManagedGroupRequest>"\
+		"</ABAuthHeader>"\
+	"</soap:Header>"\
+	"<soap:Body xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
+		"<FindMembership xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+			"<serviceFilter xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+			"<Types xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+				"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Messenger</ServiceType>"\
+				"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Invitation</ServiceType>"\
+				"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">SocialNetwork</ServiceType>"\
+				"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Space</ServiceType>"\
+				"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Profile</ServiceType>"\
+			"</Types>"\
+			"</serviceFilter>"\
+		"</FindMembership>"\
+	"</soap:Body>"\
+"</soap:Envelope>"
+
+#define MSN_ADDRESS_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
+	"<soap:Header>"\
+		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+			"<ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId>"\
+			"<IsMigration>false</IsMigration>"\
+			"<PartnerScenario>Initial</PartnerScenario>"\
+		"</ABApplicationHeader>"\
+		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
+		"</ABAuthHeader>"\
+	"</soap:Header>"\
+	"<soap:Body>"\
+		"<ABFindAll xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
+			"<abView>Full</abView>"\
+		"</ABFindAll>"\
+	"</soap:Body>"\
+"</soap:Envelope>"
+
+#define MSN_GLEAMS_TEMPLATE = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
+	"<soap:Header>"\
+		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+			"<ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId>"\
+			"<IsMigration>false</IsMigration>"\
+			"<PartnerScenario>Initial</PartnerScenario>"\
+		"</ABApplicationHeader>"\
+		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
+		"</ABAuthHeader>"\
+	"</soap:Header>"\
+	"<soap:Body>"\
+		"<ABFindAll xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+			"<abId>00000000-0000-0000-0000-000000000000</abId>"\
+			"<abView>Full</abView>"\
+			"<dynamicItemView>Gleam</dynamicItemView>"\
+			"<dynamicItemLastChange>0001-01-01T00:00:00.0000000-08:00</dynamicItemLastChange>"\
+		"</ABFindAll>"\
+	"</soap:Body>"\
+"</soap:Envelope>"
+
+typedef struct _MsnContact MsnContact;
+
+struct _MsnContact
+{
+	MsnSession *session;
+
+	MsnSoapConn *soapconn;
+};
+
+/*function prototype*/
+MsnContact * msn_contact_new(MsnSession *session);
+void msn_get_contact_list(MsnContact * contact);
+void msn_contact_connect(MsnContact *contact);
+
+void msn_contact_destroy(MsnContact *contact);
+void msn_get_contact_list(MsnContact * contact);
+
+#endif/* _MSN_CMDPROC_H_*/
+
--- a/src/protocols/msn/msg.c	Sat Jun 24 12:04:32 2006 +0000
+++ b/src/protocols/msn/msg.c	Sun Jul 09 16:48:25 2006 +0000
@@ -231,8 +231,7 @@
 
 	elems = g_strsplit(tmp, "\r\n", 0);
 
-	for (cur = elems; *cur != NULL; cur++)
-	{
+	for (cur = elems; *cur != NULL; cur++){
 		const char *key, *value;
 
 		tokens = g_strsplit(*cur, ": ", 2);
@@ -240,20 +239,17 @@
 		key = tokens[0];
 		value = tokens[1];
 
-		if (!strcmp(key, "MIME-Version"))
-		{
+		/*if not MIME content ,then return*/
+		if (!strcmp(key, "MIME-Version")){
 			g_strfreev(tokens);
 			continue;
 		}
 
-		if (!strcmp(key, "Content-Type"))
-		{
+		if (!strcmp(key, "Content-Type")){
 			char *charset, *c;
 
-			if ((c = strchr(value, ';')) != NULL)
-			{
-				if ((charset = strchr(c, '=')) != NULL)
-				{
+			if ((c = strchr(value, ';')) != NULL){
+				if ((charset = strchr(c, '=')) != NULL)	{
 					charset++;
 					msn_message_set_charset(msg, charset);
 				}
@@ -262,9 +258,7 @@
 			}
 
 			msn_message_set_content_type(msg, value);
-		}
-		else
-		{
+		}else{
 			msn_message_set_attr(msg, key, value);
 		}
 
@@ -280,8 +274,7 @@
 	content_type = msn_message_get_content_type(msg);
 
 	if (content_type != NULL &&
-		!strcmp(content_type, "application/x-msnmsgrp2p"))
-	{
+		!strcmp(content_type, "application/x-msnmsgrp2p")){
 		MsnSlpHeader header;
 		MsnSlpFooter footer;
 		int body_len;
@@ -323,9 +316,7 @@
 			tmp += sizeof(footer);
 			msg->msnslp_footer.value = GUINT32_FROM_BE(footer.value);
 		}
-	}
-	else
-	{
+	}else{
 		if (payload_len - (tmp - tmp_base) > 0) {
 			msg->body_len = payload_len - (tmp - tmp_base);
 			msg->body = g_malloc0(msg->body_len + 1);
@@ -785,3 +776,4 @@
 
 	g_string_free(str, TRUE);
 }
+
--- a/src/protocols/msn/msn-utils.c	Sat Jun 24 12:04:32 2006 +0000
+++ b/src/protocols/msn/msn-utils.c	Sun Jul 09 16:48:25 2006 +0000
@@ -351,14 +351,14 @@
 
 	host = g_strdup(str);
 
-	if ((c = strchr(host, ':')) != NULL)
-	{
+	if ((c = strchr(host, ':')) != NULL){
 		*c = '\0';
 		port = atoi(c + 1);
+	}else{
+		port = 1863;
 	}
-	else
-		port = 1863;
 
 	*ret_host = host;
 	*ret_port = port;
 }
+
--- a/src/protocols/msn/msn.c	Sat Jun 24 12:04:32 2006 +0000
+++ b/src/protocols/msn/msn.c	Sun Jul 09 16:48:25 2006 +0000
@@ -892,8 +892,7 @@
 
 	gc = gaim_account_get_connection(account);
 
-	if (gc != NULL)
-	{
+	if (gc != NULL){
 		session = gc->proto_data;
 		msn_change_status(session);
 	}
--- a/src/protocols/msn/nexus.c	Sat Jun 24 12:04:32 2006 +0000
+++ b/src/protocols/msn/nexus.c	Sun Jul 09 16:48:25 2006 +0000
@@ -22,6 +22,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include "msn.h"
+#include "soap.h"
 #include "nexus.h"
 #include "notification.h"
 
@@ -36,6 +37,10 @@
 
 	nexus = g_new0(MsnNexus, 1);
 	nexus->session = session;
+	nexus->soapconn = msn_soap_new(session);
+	nexus->soapconn->parent = nexus;
+	/*we must use SSL connection to do Windows Live ID authentication*/
+	nexus->soapconn->ssl_conn = 1;
 	nexus->challenge_data = g_hash_table_new_full(g_str_hash,
 		g_str_equal, g_free, g_free);
 
@@ -45,90 +50,14 @@
 void
 msn_nexus_destroy(MsnNexus *nexus)
 {
-	g_free(nexus->login_host);
-
-	g_free(nexus->login_path);
-
 	if (nexus->challenge_data != NULL)
 		g_hash_table_destroy(nexus->challenge_data);
 
-	if (nexus->input_handler > 0)
-		gaim_input_remove(nexus->input_handler);
-	g_free(nexus->write_buf);
-	g_free(nexus->read_buf);
-
+	msn_soap_destroy(nexus->soapconn);
 	g_free(nexus);
 }
 
 /**************************************************************************
- * Util
- **************************************************************************/
-
-static gssize
-msn_ssl_read(MsnNexus *nexus)
-{
-	gssize len;
-	gssize total_len = 0;
-	char temp_buf[4096];
-
-	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
-	}
-//	gaim_debug_info("MaYuan","nexus ssl read:{%s}\n",nexus->read_buf);
-	return total_len;
-}
-
-static void
-nexus_write_cb(gpointer data, gint source, GaimInputCondition cond)
-{
-	MsnNexus *nexus = data;
-	int len, total_len;
-
-	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);
-
-	if (len < 0 && errno == EAGAIN)
-		return;
-	else if (len <= 0) {
-		gaim_input_remove(nexus->input_handler);
-		nexus->input_handler = -1;
-		/* TODO: notify of the error */
-		return;
-	}
-	nexus->written_len += len;
-
-	if (nexus->written_len < total_len)
-		return;
-
-	gaim_input_remove(nexus->input_handler);
-	nexus->input_handler = -1;
-
-	g_free(nexus->write_buf);
-	nexus->write_buf = NULL;
-	nexus->written_len = 0;
-
-	nexus->written_cb(nexus, source, 0);
-}
-
-/**************************************************************************
  * Login
  **************************************************************************/
 
@@ -139,74 +68,38 @@
 static void
 login_error_cb(GaimSslConnection *gsc, GaimSslErrorType error, void *data)
 {
-	MsnNexus *nexus;
+	MsnSoapConn * soapconn = data;
 	MsnSession *session;
 
-	nexus = data;
-	g_return_if_fail(nexus != NULL);
-
-	session = nexus->session;
+	session = soapconn->session;
 	g_return_if_fail(session != NULL);
 
-	msn_session_set_error(session, MSN_ERROR_AUTH, _("Unable to connect"));
+	msn_session_set_error(session, MSN_ERROR_AUTH, _("Windows Live ID authentication:Unable to connect"));
 	/* the above line will result in nexus being destroyed, so we don't want
 	 * to destroy it here, or we'd crash */
 }
 
 static void
-nexus_login_written_cb(gpointer data, gint source, GaimInputCondition cond)
+nexus_login_read_cb(gpointer data, gint source, GaimInputCondition cond)
 {
-	MsnNexus *nexus = data;
+	MsnSoapConn * soapconn = data;	
+	MsnNexus *nexus;
 	MsnSession *session;
-	int len;
 
+	nexus = soapconn->parent;
+	g_return_if_fail(nexus != NULL);
 	session = nexus->session;
 	g_return_if_fail(session != NULL);
 
-	if (nexus->input_handler == -1)
-		nexus->input_handler = gaim_input_add(nexus->gsc->fd,
-			GAIM_INPUT_READ, nexus_login_written_cb, nexus);
+	gaim_debug_misc("msn", "TWN Server Reply: {%s}\n", soapconn->read_buf);
 
-	/*read the request header*/
-	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(nexus->read_buf == NULL){
-		return;
-	}
-	if (g_strstr_len(nexus->read_buf, nexus->read_len,
-			"</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", "TWN Server Reply: {%s}", nexus->read_buf);
-
-	if (strstr(nexus->read_buf, "HTTP/1.1 302") != NULL){
+	if (strstr(soapconn->read_buf, "HTTP/1.1 302") != NULL){
 		/* Redirect. */
 		char *location, *c;
 
-		location = strstr(nexus->read_buf, "Location: ");
-		if (location == NULL)
-		{
-			g_free(nexus->read_buf);
-			nexus->read_buf = NULL;
-			nexus->read_len = 0;
-
+		location = strstr(soapconn->read_buf, "Location: ");
+		if (location == NULL){
+			msn_soap_free_read_buf(soapconn);
 			return;
 		}
 		location = strchr(location, ' ') + 1;
@@ -218,24 +111,19 @@
 		if ((c = strchr(location, '/')) != NULL)
 			location = c + 2;
 
-		if ((c = strchr(location, '/')) != NULL)
-		{
-			g_free(nexus->login_path);
-			nexus->login_path = g_strdup(c);
+		if ((c = strchr(location, '/')) != NULL){
+			g_free(soapconn->login_path);
+			soapconn->login_path = g_strdup(c);
 
 			*c = '\0';
 		}
-
-		g_free(nexus->login_host);
-		nexus->login_host = g_strdup(location);
+		g_free(soapconn->login_host);
 
-		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){
+		msn_soap_init(soapconn,location,1,login_connect_cb,login_error_cb);
+	}else if (strstr(soapconn->read_buf, "HTTP/1.1 401 Unauthorized") != NULL){
 		const char *error;
 
-		if ((error = strstr(nexus->read_buf, "WWW-Authenticate")) != NULL)	{
+		if ((error = strstr(soapconn->read_buf, "WWW-Authenticate")) != NULL)	{
 			if ((error = strstr(error, "cbtxt=")) != NULL){
 				const char *c;
 				char *temp;
@@ -251,67 +139,70 @@
 			}
 		}
 		msn_session_set_error(session, MSN_ERROR_AUTH, error);
-	}else if (strstr(nexus->read_buf, "HTTP/1.1 200 OK")){
+	}else if (strstr(soapconn->read_buf, "HTTP/1.1 200 OK")){
 		/*reply OK, we should process the SOAP body*/
 		char *base, *c;
+		char *msn_twn_t,*msn_twn_p;
 		char *login_params;
-		char *length_start,*length_end,*body_len;
 
 		char **elems, **cur, **tokens;
-		const char * cert_str;
+		char * cert_str;
 
-		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);
+		gaim_debug_info("MaYuan","Windows Live ID Reply OK!\n");
 
-		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  = g_strstr_len(soapconn->read_buf, soapconn->read_len, 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);
+		c     = g_strstr_len(soapconn->read_buf, soapconn->read_len, TWN_END_TOKEN);
 		login_params = g_strndup(base, c - base);
 
-		gaim_debug_info("msn", "TWN Cert: {%s}\n", 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]);
+				g_hash_table_insert(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_twn_t = (char *)g_hash_table_lookup(nexus->challenge_data, "t");
+		msn_twn_p = (char *)g_hash_table_lookup(nexus->challenge_data, "p");
+
+		/*setup the t and p parameter for session*/
+		if (session->passport_info.t != NULL){
+			g_free(session->passport_info.t);
+		}
+		session->passport_info.t = g_strdup(msn_twn_t);
+
+		if (session->passport_info.p != NULL)
+			g_free(session->passport_info.p);
+		session->passport_info.p = g_strdup(msn_twn_p);
+
+		cert_str = g_strdup_printf("t=%s&p=%s",msn_twn_t,msn_twn_p);
 		msn_got_login_params(session, cert_str);
 
+		gaim_debug_info("MaYuan","close nexus connection! \n");
 		g_free(cert_str);
-//		g_free(body_len);
 		g_free(login_params);
-//		return;
 		msn_nexus_destroy(nexus);
 		session->nexus = NULL;
 		return;
 	}
+	msn_soap_free_read_buf(soapconn);
+}
 
-	g_free(nexus->read_buf);
-	nexus->read_buf = NULL;
-	nexus->read_len = 0;
+static void
+nexus_login_written_cb(gpointer data, gint source, GaimInputCondition cond)
+{
+	MsnSoapConn * soapconn = data;	
+
+	soapconn->read_cb = nexus_login_read_cb;
+	msn_soap_read_cb(data,source,cond);
 }
 
 
@@ -319,26 +210,27 @@
 login_connect_cb(gpointer data, GaimSslConnection *gsc,
 				 GaimInputCondition cond)
 {
-	MsnNexus *nexus;
+	MsnSoapConn *soapconn;
+	MsnNexus * nexus;
 	MsnSession *session;
 	char *username, *password;
 	char *request_str, *head, *tail,*challenge_str;
-	char *buffer = NULL;
-	guint32 ctint;
 
 	gaim_debug_info("MaYuan","starting Windows Live ID authentication\n");
-	nexus = data;
+
+	soapconn = data;
+	g_return_if_fail(soapconn != NULL);
+
+	nexus = soapconn->parent;
 	g_return_if_fail(nexus != NULL);
 
-	session = nexus->session;
+	session = soapconn->session;
 	g_return_if_fail(session != NULL);
 
-	nexus->gsc = gsc;
-
 	msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE);
 
+	/*prepare the Windows Live ID authentication token*/
 	username = g_strdup(gaim_account_get_username(session->account));
-
 	password = g_strdup(gaim_connection_get_password(session->account->gc));
 //		g_strdup(gaim_url_encode(gaim_connection_get_password(session->account->gc)));
 
@@ -360,7 +252,7 @@
 	/*build the SOAP windows Live ID XML body */
 	tail = g_strdup_printf(TWN_ENVELOP_TEMPLATE,username,password,challenge_str	);
 
-	nexus->login_path = g_strdup(TWN_POST_URL);
+	soapconn->login_path = g_strdup(TWN_POST_URL);
 	head = g_strdup_printf(
 					"POST %s HTTP/1.1\r\n"
 					"Accept: text/*\r\n"
@@ -369,29 +261,18 @@
 					"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));
+					soapconn->login_path,soapconn->login_host,strlen(tail));
 
 	request_str = g_strdup_printf("%s%s", head,tail);
-//	gaim_debug_misc("msn", "TWN Sending: {%s}\n", request_str);
+	gaim_debug_misc("msn", "TWN Sending: {%s}\n", request_str);
 
-//	g_free(nexus->login_path);
-	g_free(buffer);
 	g_free(head);
 	g_free(tail);
 	g_free(username);
 	g_free(password);
 
-	nexus->write_buf = request_str;
-	nexus->written_len = 0;
-
-	nexus->read_len = 0;
-
-	nexus->written_cb = nexus_login_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);
+	/*prepare to send the SOAP request*/
+	msn_soap_write(soapconn,request_str,nexus_login_written_cb);
 
 	return;
 }
@@ -404,8 +285,7 @@
 {
 	/*  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);
+
+	msn_soap_init(nexus->soapconn,MSN_TWN_SERVER,1,login_connect_cb,login_error_cb);
 }
+
--- a/src/protocols/msn/nexus.h	Sat Jun 24 12:04:32 2006 +0000
+++ b/src/protocols/msn/nexus.h	Sun Jul 09 16:48:25 2006 +0000
@@ -24,7 +24,9 @@
 #ifndef _MSN_NEXUS_H_
 #define _MSN_NEXUS_H_
 
-#define TWN_SERVER	"loginnet.passport.com"
+#include "soap.h"
+
+#define MSN_TWN_SERVER	"loginnet.passport.com"
 
 #define TWN_START_TOKEN		"<wsse:BinarySecurityToken Id=\"PPToken1\">"
 #define TWN_END_TOKEN		"</wsse:BinarySecurityToken>"
@@ -75,20 +77,8 @@
 struct _MsnNexus
 {
 	MsnSession *session;
-
-	char *login_host;
-	char *login_path;
+	MsnSoapConn *soapconn;	
 	GHashTable *challenge_data;
-	GaimSslConnection *gsc;
-
-	guint input_handler;
-
-	char *write_buf;
-	gsize written_len;
-	GaimInputFunction written_cb;
-
-	char *read_buf;
-	gsize read_len;
 };
 
 void msn_nexus_connect(MsnNexus *nexus);
--- a/src/protocols/msn/notification.c	Sat Jun 24 12:04:32 2006 +0000
+++ b/src/protocols/msn/notification.c	Sun Jul 09 16:48:25 2006 +0000
@@ -238,7 +238,8 @@
 
 		msn_session_set_login_step(session, MSN_LOGIN_STEP_SYN);
 
-		msn_cmdproc_send(cmdproc, "SYN", "%s", "0");
+//		msn_cmdproc_send(cmdproc, "SYN", "%s", "0");
+		//TODO we should use SOAP contact to fetch contact list
 	}else if (!g_ascii_strcasecmp(cmd->params[1], "TWN")){
 		/* Passport authentication */
 		char **elems, **cur, **tokens;
@@ -397,8 +398,8 @@
 
 /**************************************************************************
  * Challenges
+ *  we use MD5 to caculate the Chanllenges 
  **************************************************************************/
-
 static void
 chl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
@@ -416,7 +417,7 @@
 	gaim_cipher_context_append(context, (const guchar *)cmd->params[1],
 							   strlen(cmd->params[1]));
 
-	challenge_resp = "VT6PX?UQTM4WM%YR";
+	challenge_resp = MSNP13_WLM_PRODUCT_KEY;
 
 	gaim_cipher_context_append(context, (const guchar *)challenge_resp,
 							   strlen(challenge_resp));
@@ -426,7 +427,7 @@
 	for (i = 0; i < 16; i++)
 		g_snprintf(buf + (i*2), 3, "%02x", digest[i]);
 
-	trans = msn_transaction_new(cmdproc, "QRY", "%s 32", "PROD0038W!61ZTF9");
+	trans = msn_transaction_new(cmdproc, "QRY", "%s 32", MSNP13_WLM_PRODUCT_ID);
 
 	msn_transaction_set_payload(trans, buf, 32);
 
@@ -436,7 +437,6 @@
 /**************************************************************************
  * Buddy Lists
  **************************************************************************/
-
 static void
 add_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
@@ -554,6 +554,10 @@
 	g_strfreev(params);
 }
 
+static void adl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+{
+}
+
 static void
 adg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
@@ -1100,12 +1104,9 @@
 
 	msn_parse_socket(cmd->params[2], &host, &port);
 
-	if (!strcmp(cmd->params[1], "SB"))
-	{
+	if (!strcmp(cmd->params[1], "SB")){
 		gaim_debug_error("msn", "This shouldn't be handled here.\n");
-	}
-	else if (!strcmp(cmd->params[1], "NS"))
-	{
+	}else if (!strcmp(cmd->params[1], "NS")){
 		MsnSession *session;
 
 		session = cmdproc->session;
@@ -1123,7 +1124,6 @@
 {
 	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*/
@@ -1149,49 +1149,53 @@
 	MsnSession *session;
 	const char *value;
 
+	gaim_debug_info("MaYuan","profile_msg... \n");
 	session = cmdproc->session;
 
 	if (strcmp(msg->remote_user, "Hotmail"))
 		/* This isn't an official message. */
 		return;
 
-	if ((value = msn_message_get_attr(msg, "kv")) != NULL)
-	{
+	if ((value = msn_message_get_attr(msg, "kv")) != NULL){
 		if (session->passport_info.kv != NULL)
 			g_free(session->passport_info.kv);
 
 		session->passport_info.kv = g_strdup(value);
 	}
 
-	if ((value = msn_message_get_attr(msg, "sid")) != NULL)
-	{
+	if ((value = msn_message_get_attr(msg, "sid")) != NULL){
 		if (session->passport_info.sid != NULL)
 			g_free(session->passport_info.sid);
 
 		session->passport_info.sid = g_strdup(value);
 	}
 
-	if ((value = msn_message_get_attr(msg, "MSPAuth")) != NULL)
-	{
+	if ((value = msn_message_get_attr(msg, "MSPAuth")) != NULL){
 		if (session->passport_info.mspauth != NULL)
 			g_free(session->passport_info.mspauth);
 
+		gaim_debug_info("MaYuan","MSPAuth:%s\n",value);
 		session->passport_info.mspauth = g_strdup(value);
 	}
 
-	if ((value = msn_message_get_attr(msg, "ClientIP")) != NULL)
-	{
+	if ((value = msn_message_get_attr(msg, "ClientIP")) != NULL){
 		if (session->passport_info.client_ip != NULL)
 			g_free(session->passport_info.client_ip);
 
 		session->passport_info.client_ip = g_strdup(value);
 	}
 
-	if ((value = msn_message_get_attr(msg, "ClientPort")) != NULL)
+	if ((value = msn_message_get_attr(msg, "ClientPort")) != NULL){
 		session->passport_info.client_port = ntohs(atoi(value));
+	}
 
 	if ((value = msn_message_get_attr(msg, "LoginTime")) != NULL)
 		session->passport_info.sl = atol(value);
+
+	/*starting retrieve the contact list*/
+	session->contact = msn_contact_new(session);
+	msn_contact_connect(session->contact);
+
 }
 
 static void
--- a/src/protocols/msn/notification.h	Sat Jun 24 12:04:32 2006 +0000
+++ b/src/protocols/msn/notification.h	Sun Jul 09 16:48:25 2006 +0000
@@ -24,6 +24,14 @@
 #ifndef _MSN_NOTIFICATION_H_
 #define _MSN_NOTIFICATION_H_
 
+/*MSN protocol challenge info*/
+/*MSNP13 challenge*/
+#define MSNP13_WLM_PRODUCT_KEY	"O4BG@C7BWLYQX?5G"
+#define MSNP13_WLM_PRODUCT_ID	"PROD01065C%ZFN6F"
+
+#define MSNP10_PRODUCT_KEY		"VT6PX?UQTM4WM%YR"
+#define MSNP10_PRODUCT_ID		"PROD0038W!61ZTF9" 
+
 typedef struct _MsnNotification MsnNotification;
 
 #include "session.h"
--- a/src/protocols/msn/session.c	Sat Jun 24 12:04:32 2006 +0000
+++ b/src/protocols/msn/session.c	Sun Jul 09 16:48:25 2006 +0000
@@ -70,6 +70,8 @@
 
 	msn_userlist_destroy(session->userlist);
 
+	g_free(session->passport_info.t);
+	g_free(session->passport_info.p);
 	g_free(session->passport_info.kv);
 	g_free(session->passport_info.sid);
 	g_free(session->passport_info.mspauth);
--- a/src/protocols/msn/session.h	Sat Jun 24 12:04:32 2006 +0000
+++ b/src/protocols/msn/session.h	Sun Jul 09 16:48:25 2006 +0000
@@ -38,6 +38,7 @@
 #include "cmdproc.h"
 #include "nexus.h"
 #include "httpconn.h"
+#include "contact.h"
 
 #include "userlist.h"
 #include "sync.h"
@@ -94,6 +95,7 @@
 
 	MsnNotification *notification;
 	MsnNexus *nexus;
+	MsnContact *contact;
 	MsnSync *sync;
 
 	MsnUserList *userlist;
@@ -107,6 +109,10 @@
 
 	struct
 	{
+		/*t and p, get via USR TWN*/
+		char *t;
+		char *p;
+
 		char *kv;
 		char *sid;
 		char *mspauth;
@@ -114,7 +120,6 @@
 		char *file;
 		char *client_ip;
 		int client_port;
-
 	} passport_info;
 };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/msn/soap.c	Sun Jul 09 16:48:25 2006 +0000
@@ -0,0 +1,302 @@
+/**
+ * @file soap.c 
+ * 	SOAP connection related process
+ *	Author
+ * 		MaYuan<mayuan2006@gmail.com>
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include "msn.h"
+#include "soap.h"
+
+/*new a soap connection*/
+MsnSoapConn *
+msn_soap_new(MsnSession *session)
+{
+	MsnSoapConn *soapconn;
+
+	soapconn = g_new0(MsnSoapConn, 1);
+	soapconn->session = session;
+	soapconn->input_handler = -1;
+	soapconn->output_handler = -1;
+	return soapconn;
+}
+
+/*ssl soap connect callback*/
+void
+msn_soap_connect_cb(gpointer data, GaimSslConnection *gsc,
+				 GaimInputCondition cond)
+{
+	MsnSoapConn * soapconn;
+	MsnSession *session;
+
+	gaim_debug_info("MaYuan","Soap connection connected!\n");
+	soapconn = data;
+	g_return_if_fail(soapconn != NULL);
+
+	session = soapconn->session;
+	g_return_if_fail(session != NULL);
+
+	soapconn->gsc = gsc;
+
+	/*connection callback*/
+	if(soapconn->connect_cb != NULL){
+		soapconn->connect_cb(data,gsc,cond);
+	}
+}
+
+/*ssl soap error callback*/
+static void
+msn_soap_error_cb(GaimSslConnection *gsc, GaimSslErrorType error, void *data)
+{	
+	MsnSoapConn * soapconn = data;
+	g_return_if_fail(data != NULL);
+	gaim_debug_info("MaYuan","Soap connection error!\n");
+	/*error callback*/
+	if(soapconn->error_cb != NULL){
+		soapconn->error_cb(gsc,error,data);
+	}
+}
+
+/*init the soap connection*/
+void
+msn_soap_init(MsnSoapConn *soapconn,char * host,int ssl,
+				GaimSslInputFunction	connect_cb,
+				GaimSslErrorFunction	error_cb)
+{
+	soapconn->login_host = g_strdup(host);
+	soapconn->ssl_conn = ssl;
+	soapconn->connect_cb = connect_cb;
+	soapconn->error_cb = error_cb;
+	if(soapconn->ssl_conn){
+		gaim_ssl_connect(soapconn->session->account, soapconn->login_host,
+				GAIM_SSL_DEFAULT_PORT, msn_soap_connect_cb, msn_soap_error_cb,
+				soapconn);
+	}else{
+	}
+}
+
+/*destroy the soap connection*/
+void
+msn_soap_destroy(MsnSoapConn *soapconn)
+{
+	g_free(soapconn->login_host);
+	g_free(soapconn->login_path);
+
+	/*remove the write handler*/
+	if (soapconn->output_handler > 0){
+		gaim_input_remove(soapconn->output_handler);
+	}
+	/*remove the read handler*/
+	if (soapconn->input_handler > 0){
+		gaim_input_remove(soapconn->input_handler);
+	}
+	msn_soap_free_read_buf(soapconn);
+	msn_soap_free_write_buf(soapconn);
+
+	/*close ssl connection*/
+	gaim_ssl_close(soapconn->gsc);
+	soapconn->gsc = NULL;
+
+	g_free(soapconn);
+}
+
+/*read and append the content to the buffer*/
+static gssize
+msn_soap_read(MsnSoapConn *soapconn)
+{
+	gssize len;
+	gssize total_len = 0;
+	char temp_buf[10240];
+
+	if(soapconn->ssl_conn){
+		len = gaim_ssl_read(soapconn->gsc, temp_buf,sizeof(temp_buf));
+	}else{
+		len = read(soapconn->fd, temp_buf,sizeof(temp_buf));
+	}
+	if(len >0){
+		total_len += len;
+		soapconn->read_buf = g_realloc(soapconn->read_buf,
+						soapconn->read_len + len + 1);
+//		strncpy(soapconn->read_buf + soapconn->read_len, temp_buf, len);
+		memcpy(soapconn->read_buf + soapconn->read_len, temp_buf, len);
+		soapconn->read_len += len;
+		soapconn->read_buf[soapconn->read_len] = '\0';
+	}
+//	gaim_debug_info("MaYuan","nexus ssl read:{%s}\n",soapconn->read_buf);
+	return total_len;
+}
+
+/*read the whole SOAP server response*/
+void 
+msn_soap_read_cb(gpointer data, gint source, GaimInputCondition cond)
+{
+	MsnSoapConn *soapconn = data;
+	MsnSession *session;
+	int len;
+	char * body_start,*body_len;
+	char *length_start,*length_end;
+
+	gaim_debug_misc("MaYuan", "soap read cb\n");
+	session = soapconn->session;
+	g_return_if_fail(session != NULL);
+
+	if (soapconn->input_handler == -1){
+		soapconn->input_handler = gaim_input_add(soapconn->gsc->fd,
+			GAIM_INPUT_READ, msn_soap_read_cb, soapconn);
+	}
+
+	/*read the request header*/
+	len = msn_soap_read(soapconn);
+	if (len < 0 && errno == EAGAIN){
+		return;
+	}else if (len < 0) {
+		gaim_debug_error("msn", "read Error!len:%d\n",len);
+		gaim_input_remove(soapconn->input_handler);
+		soapconn->input_handler = -1;
+		g_free(soapconn->read_buf);
+		soapconn->read_buf = NULL;
+		soapconn->read_len = 0;
+		/* TODO: error handling */
+		return;
+	}
+
+	if(soapconn->read_buf == NULL){
+		return;
+	}
+
+	body_start = (char *)g_strstr_len(soapconn->read_buf, soapconn->read_len,"\r\n\r\n");
+	if(!body_start){
+		return;
+	}
+	body_start += 4;
+
+//	gaim_debug_misc("msn", "Soap Read: {%s}\n", soapconn->read_buf);
+
+	/* we read the content-length*/
+	length_start = strstr(soapconn->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);
+
+	/*setup the conn body */
+	soapconn->body		= body_start;
+	soapconn->body_len	= atoi(body_len);
+//	gaim_debug_misc("MaYuan","content length :%d",soapconn->body_len);
+
+	if(soapconn->read_len < body_start - soapconn->read_buf + atoi(body_len)){
+			return;
+	}
+
+	g_free(body_len);
+
+	/*call the read callback*/
+	if(soapconn->read_cb != NULL){
+		soapconn->read_cb(soapconn,source,0);
+	}
+#if 0
+	/*clear the read buffer*/
+	msn_soap_free_read_buf(soapconn);
+
+	/*remove the read handler*/
+	gaim_input_remove(soapconn->input_handler);
+	soapconn->input_handler = -1;
+	gaim_ssl_close(soapconn->gsc);
+	soapconn->gsc = NULL;
+#endif
+}
+
+void 
+msn_soap_free_read_buf(MsnSoapConn *soapconn)
+{
+	if(soapconn->read_buf){
+		g_free(soapconn->read_buf);
+	}
+	soapconn->read_buf = NULL;
+	soapconn->read_len = 0;
+}
+
+void
+msn_soap_free_write_buf(MsnSoapConn *soapconn)
+{
+	if(soapconn->write_buf){
+		g_free(soapconn->write_buf);
+	}
+	soapconn->write_buf = NULL;
+	soapconn->written_len = 0;
+}
+
+/*Soap write process func*/
+static void
+msn_soap_write_cb(gpointer data, gint source, GaimInputCondition cond)
+{
+	MsnSoapConn *soapconn = data;
+	int len, total_len;
+
+	total_len = strlen(soapconn->write_buf);
+
+	/* 
+	 * write the content to SSL server,
+	 */
+	len = gaim_ssl_write(soapconn->gsc,
+		soapconn->write_buf + soapconn->written_len,
+		total_len - soapconn->written_len);
+
+	if (len < 0 && errno == EAGAIN)
+		return;
+	else if (len <= 0){
+		/*SSL write error!*/
+		gaim_input_remove(soapconn->output_handler);
+		soapconn->output_handler = -1;
+		/* TODO: notify of the error */
+		return;
+	}
+	soapconn->written_len += len;
+
+	if (soapconn->written_len < total_len)
+		return;
+
+	gaim_input_remove(soapconn->output_handler);
+	soapconn->output_handler = -1;
+
+	/*clear the write buff*/
+	msn_soap_free_write_buf(soapconn);
+
+	/* Write finish!
+	 * callback for write done
+	 */
+	if(soapconn->written_cb != NULL){
+		soapconn->written_cb(soapconn, source, 0);
+	}
+}
+
+/*write the buffer to SOAP connection*/
+void
+msn_soap_write(MsnSoapConn * soapconn, char *write_buf, GaimInputFunction written_cb)
+{
+	soapconn->write_buf = write_buf;
+	soapconn->written_len = 0;
+	soapconn->written_cb = written_cb;
+	/*start the write*/
+	soapconn->output_handler = gaim_input_add(soapconn->gsc->fd, GAIM_INPUT_WRITE,
+													msn_soap_write_cb, soapconn);
+	msn_soap_write_cb(soapconn, soapconn->gsc->fd, GAIM_INPUT_WRITE);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/msn/soap.h	Sun Jul 09 16:48:25 2006 +0000
@@ -0,0 +1,87 @@
+/**
+ * @file soap.h
+ * 	header file for SOAP connection related process
+ *	Author
+ * 		MaYuan<mayuan2006@gmail.com>
+ * gaim
+ *
+ * Gaim is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _MSN_SOAP_H_
+#define _MSN_SOAP_H_
+
+/*MSN Https connection structure*/
+typedef struct _MsnSoapConn MsnSoapConn;
+
+struct _MsnSoapConn{
+	MsnSession *session;
+	gpointer parent;
+
+	char *login_host;
+	char *login_path;
+
+	/*ssl connection?*/
+	guint	ssl_conn;
+	/*normal connection*/
+	guint	fd;
+	/*SSL connection*/
+	GaimSslConnection *gsc;
+	/*ssl connection callback*/
+	GaimSslInputFunction	connect_cb;
+	/*ssl error callback*/
+	GaimSslErrorFunction	error_cb;
+
+	/*read handler*/
+	guint input_handler;
+	/*write handler*/
+	guint output_handler;
+
+	/*write buffer*/
+	char *write_buf;
+	gsize written_len;
+	GaimInputFunction written_cb;
+
+	/*read buffer*/
+	char *read_buf;
+	gsize read_len;
+	GaimInputFunction read_cb;
+
+	/*HTTP reply body part*/
+	char *body;
+	int body_len;
+};
+
+/*Function Prototype*/
+/*new a soap conneciton */
+MsnSoapConn *msn_soap_new(MsnSession *session);
+/*destroy */
+void msn_soap_destroy(MsnSoapConn *soapconn);
+
+/*init a soap conneciton */
+void msn_soap_init(MsnSoapConn *soapconn,char * host,int ssl,GaimSslInputFunction connect_cb,GaimSslErrorFunction error_cb);
+
+/*write to soap*/
+void msn_soap_write(MsnSoapConn * soapconn, char *write_buf, GaimInputFunction written_cb);
+void  msn_soap_free_read_buf(MsnSoapConn *soapconn);
+void msn_soap_free_write_buf(MsnSoapConn *soapconn);
+void msn_soap_connect_cb(gpointer data, GaimSslConnection *gsc, GaimInputCondition cond);
+void msn_soap_read_cb(gpointer data, gint source, GaimInputCondition cond);
+
+#endif/*_MSN_SOAP_H_*/
+
--- a/src/protocols/msn/table.c	Sat Jun 24 12:04:32 2006 +0000
+++ b/src/protocols/msn/table.c	Sun Jul 09 16:48:25 2006 +0000
@@ -77,20 +77,14 @@
 
 	cbs = NULL;
 
-	if (command == NULL)
-	{
+	if (command == NULL){
 		cbs = table->async;
-	}
-	else if (strcmp(command, "fallback") == 0)
-	{
+	}else if (strcmp(command, "fallback") == 0)	{
 		cbs = table->fallback;
-	}
-	else
-	{
+	}else{
 		cbs = g_hash_table_lookup(table->cmds, command);
 
-		if (cbs == NULL)
-		{
+		if (cbs == NULL){
 			cbs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
 			g_hash_table_insert(table->cmds, command, cbs);
 		}