changeset 20534:7e69275a4eef

oim migrated to new soap code, quadruply duplicated message! the timestamp seems to be off too, but I didn't change that part at all, I need to sleep now though
author Ka-Hing Cheung <khc@hxbc.us>
date Mon, 01 Oct 2007 07:20:35 +0000
parents 66921a5c9ae9
children a9ee3fbabf81
files libpurple/protocols/msn/msn.c libpurple/protocols/msn/notification.c libpurple/protocols/msn/oim.c libpurple/protocols/msn/oim.h libpurple/protocols/msn/session.c libpurple/protocols/msn/soap2.c
diffstat 6 files changed, 239 insertions(+), 455 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/msn/msn.c	Mon Oct 01 01:22:37 2007 +0000
+++ b/libpurple/protocols/msn/msn.c	Mon Oct 01 07:20:35 2007 +0000
@@ -948,20 +948,17 @@
 	}else	{
 		/*send Offline Instant Message,only to MSN Passport User*/
 		MsnSession *session;
-		MsnOim *oim;
 		char *friendname;
 
 		purple_debug_info("MSNP14","prepare to send offline Message\n");
 		session = gc->proto_data;
-		/* XXX/khc: hack */
-		if (!session->oim)
-			session->oim = msn_oim_new(session);
 
-		oim = session->oim;
 		friendname = msn_encode_mime(account->username);
-		msn_oim_prep_send_msg_info(oim, purple_account_get_username(account),
-								   friendname, who,	message);
-		msn_oim_send_msg(oim);
+		msn_oim_prep_send_msg_info(session->oim,
+			purple_account_get_username(account),
+			friendname, who,	message);
+		msn_oim_send_msg(session->oim);
+		g_free(friendname);
 	}
 
 	return 1;
--- a/libpurple/protocols/msn/notification.c	Mon Oct 01 01:22:37 2007 +0000
+++ b/libpurple/protocols/msn/notification.c	Mon Oct 01 07:20:35 2007 +0000
@@ -421,6 +421,7 @@
 	{
 		g_return_if_fail(cmd->payload_cb != NULL);
 
+		purple_debug_info("valgrind", "MSG len: %d [%c] [%c]\n", cmd->payload_len, cmd->payload[cmd->payload_len - 2], cmd->payload[cmd->payload_len - 1]);
 		purple_debug_info("MSNP14","MSG payload:{%s}\n",cmd->payload);
 		cmd->payload_cb(cmdproc, cmd, cmd->payload, cmd->payload_len);
 	}
@@ -1801,7 +1802,7 @@
 		return;
 
 	/*new a oim session*/
-	session->oim = msn_oim_new(session);
+//	session->oim = msn_oim_new(session);
 //	msn_oim_connect(session->oim);
 
 	table = msn_message_get_hashtable_from_body(msg);
--- a/libpurple/protocols/msn/oim.c	Mon Oct 01 01:22:37 2007 +0000
+++ b/libpurple/protocols/msn/oim.c	Mon Oct 01 07:20:35 2007 +0000
@@ -24,24 +24,29 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include "msn.h"
-#include "soap.h"
+#include "soap2.h"
 #include "oim.h"
 #include "msnutils.h"
 
+typedef struct _MsnOimSendReq MsnOimSendReq;
+
+struct _MsnOimSendReq
+{
+	char *from_member;
+	char *friendname;
+	char *to_member;
+	char *oim_msg;
+};
+
 /*Local Function Prototype*/
 static void msn_oim_post_single_get_msg(MsnOim *oim,const char *msgid);
 static MsnOimSendReq *msn_oim_new_send_req(const char *from_member,
 										   const char *friendname,
 										   const char* to_member,
-										   gint send_seq,
 										   const char *msg);
-static void msn_oim_retrieve_connect_init(MsnSoapConn *soapconn);
-static void msn_oim_send_connect_init(MsnSoapConn *soapconn);
 static void msn_oim_free_send_req(MsnOimSendReq *req);
 static void msn_oim_report_to_user(MsnOim *oim, const char *msg_str);
-static void msn_oim_get_process(MsnOim *oim, const char *oim_msg);
 static char *msn_oim_msg_to_str(MsnOim *oim, const char *body);
-static void msn_oim_send_process(MsnOim *oim, const char *body, int len);
 
 /*new a OIM object*/
 MsnOim *
@@ -51,10 +56,7 @@
 
 	oim = g_new0(MsnOim, 1);
 	oim->session = session;
-	oim->retrieveconn = msn_soap_new(session,oim,1);
-	
 	oim->oim_list	= NULL;
-	oim->sendconn = msn_soap_new(session,oim,1);
 	oim->run_id = rand_guid();
 	oim->challenge = NULL;
 	oim->send_queue = g_queue_new();
@@ -69,8 +71,6 @@
 	MsnOimSendReq *request;
 	
 	purple_debug_info("OIM","destroy the OIM \n");
-	msn_soap_destroy(oim->retrieveconn);
-	msn_soap_destroy(oim->sendconn);
 	g_free(oim->run_id);
 	g_free(oim->challenge);
 	
@@ -84,8 +84,7 @@
 
 static MsnOimSendReq *
 msn_oim_new_send_req(const char *from_member, const char*friendname,
-					 const char* to_member, gint send_seq,
-					 const char *msg)
+	const char* to_member, const char *msg)
 {
 	MsnOimSendReq *request;
 	
@@ -93,7 +92,6 @@
 	request->from_member	=g_strdup(from_member);
 	request->friendname		= g_strdup(friendname);
 	request->to_member		= g_strdup(to_member);
-	request->send_seq		= send_seq;
 	request->oim_msg		= g_strdup(msg);
 	return request;
 }
@@ -129,134 +127,56 @@
 	return oim_body;
 }
 
-/*oim SOAP server login error*/
-static void
-msn_oim_send_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType 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 OIM server"));
-}
-
-/*msn oim SOAP server connect process*/
-static void
-msn_oim_send_connect_cb(gpointer data, PurpleSslConnection *gsc,
-				 PurpleInputCondition cond)
-{
-	MsnSoapConn *soapconn = data;
-	MsnSession * session;
-	MsnOim *oim;
-
-	oim = soapconn->parent;
-	g_return_if_fail(oim != NULL);
-
-	session = oim->session;
-	g_return_if_fail(session != NULL);
-}
-
 /*
  * Process the send return SOAP string
  * If got SOAP Fault,get the lock key,and resend it.
  */
 static void
-msn_oim_send_process(MsnOim *oim, const char *body, int len)
+msn_oim_send_read_cb(MsnSoapMessage *request, MsnSoapMessage *response,
+	gpointer data)
 {
-	xmlnode *responseNode, *bodyNode;
-	xmlnode	*faultNode, *faultCodeNode, *faultstringNode;
-	xmlnode *detailNode, *challengeNode;
-	char *faultCodeStr = NULL, *faultstring = NULL;
+	MsnOim *oim = data;
+	xmlnode	*faultNode, *challengeNode;
+	MsnOimSendReq *msg = g_queue_pop_head(oim->send_queue);
+
+	g_return_if_fail(msg != NULL);
+
+	if (response == NULL) {
+		purple_debug_info("MSNP14", "cannot send OIM: %s\n", msg->oim_msg);
+	} else {
+		faultNode = msn_soap_xml_get(response->xml, "Body/Fault");
 
-	responseNode = xmlnode_from_str(body,len);
-	g_return_if_fail(responseNode != NULL);
-	bodyNode = xmlnode_get_child(responseNode,"Body");
-	faultNode = xmlnode_get_child(bodyNode,"Fault");
-	if(faultNode == NULL){
-		/*Send OK! return*/
-		MsnOimSendReq *request;
-		
-		purple_debug_info("MSNP14","send OIM OK!");
-		xmlnode_free(responseNode);
-		request = g_queue_pop_head(oim->send_queue);
-		msn_oim_free_send_req(request);
-		/*send next buffered Offline Message*/
-		msn_soap_post(oim->sendconn,NULL,msn_oim_send_connect_init);
-		return;
-	}
-	/*get the challenge,and repost it*/
-	faultCodeNode = xmlnode_get_child(faultNode,"faultcode");
-	if(faultCodeNode == NULL){
-		purple_debug_info("MSNP14","faultcode Node is NULL\n");
-		goto oim_send_process_fail;
-	}
-	faultCodeStr = xmlnode_get_data(faultCodeNode);
-	purple_debug_info("MSNP14","fault code:{%s}\n",faultCodeStr);
-#if 0
-	if(!strcmp(faultCodeStr,"q0:AuthenticationFailed")){
-		/*other Fault Reason?*/
-		goto oim_send_process_fail;
-	}
-#endif
+		if (faultNode == NULL) {
+			/*Send OK! return*/
+			purple_debug_info("MSNP14", "sent OIM: %s\n", msg->oim_msg);
+		} else {
+			/*get the challenge,and repost it*/
+			challengeNode = msn_soap_xml_get(faultNode,
+				"detail/LockKeyChallenge");
+
+			if (challengeNode == NULL) {
+				purple_debug_info("MSNP14", "can't find lock key for OIM: %s\n", msg);
+			} else {
+				char buf[33];
 
-	faultstringNode = xmlnode_get_child(faultNode,"faultstring");
-	faultstring = xmlnode_get_data(faultstringNode);
-	purple_debug_info("MSNP14","fault string :{%s}\n",faultstring);
+				char *challenge = xmlnode_get_data(challengeNode);
+				msn_handle_chl(challenge, buf);
+
+				g_free(oim->challenge);
+				oim->challenge = g_strndup(buf, sizeof(buf));
+				g_free(challenge);
+				purple_debug_info("MSNP14","lockkey:{%s}\n",oim->challenge);
 
-	/* lock key fault reason,
-	 * compute the challenge and resend it
-	 */
-	detailNode = xmlnode_get_child(faultNode, "detail");
-	if(detailNode == NULL){
-		goto oim_send_process_fail;
-	}
-	challengeNode = xmlnode_get_child(detailNode,"LockKeyChallenge");
-	if (challengeNode == NULL) {
-		goto oim_send_process_fail;
+				/*repost the send*/
+				purple_debug_info("MSNP14","resending OIM: %s\n", msg->oim_msg);
+				g_queue_push_head(oim->send_queue, msg);
+				msn_oim_send_msg(oim);
+				return;
+			}
+		}
 	}
 
-	g_free(oim->challenge);
-	oim->challenge = xmlnode_get_data(challengeNode);
-	purple_debug_info("MSNP14","lockkey:{%s}\n",oim->challenge);
-
-	/*repost the send*/
-	purple_debug_info("MSNP14","prepare to repost the send...\n");
-	msn_oim_send_msg(oim);
-
-oim_send_process_fail:
-	g_free(faultstring);
-	g_free(faultCodeStr);
-	xmlnode_free(responseNode);
-	return ;
-}
-
-static void
-msn_oim_send_read_cb(gpointer data, gint source, PurpleInputCondition cond)
-{
-	MsnSoapConn * soapconn = data;
-	MsnSession *session = soapconn->session;
-	MsnOim * oim;
-
-	if (soapconn->body == NULL)
-		return;
-
-	g_return_if_fail(session != NULL);
-	oim = soapconn->session->oim;
-	g_return_if_fail(oim != NULL);
-
-	purple_debug_info("MSNP14","read buffer:{%s}\n",soapconn->body);
-	msn_oim_send_process(oim,soapconn->body,soapconn->body_len);
-}
-
-static void
-msn_oim_send_written_cb(gpointer data, gint source, PurpleInputCondition cond)
-{
-	MsnSoapConn * soapconn = data;	
-
-	soapconn->read_cb = msn_oim_send_read_cb;
-//	msn_soap_read_cb(data,source,cond);
+	msn_oim_free_send_req(msg);
 }
 
 void
@@ -264,45 +184,36 @@
 						   const char* friendname, const char *tomember,
 						   const char * msg)
 {
-	MsnOimSendReq *request;
-
 	g_return_if_fail(oim != NULL);
 
-	request = msn_oim_new_send_req(membername,friendname,tomember,oim->send_seq,msg);
-	g_queue_push_tail(oim->send_queue,request);
+	g_queue_push_tail(oim->send_queue,
+		msn_oim_new_send_req(membername, friendname, tomember, msg));
 }
 
 /*post send single message request to oim server*/
 void 
 msn_oim_send_msg(MsnOim *oim)
 {
-	MsnSoapReq *soap_request;
 	MsnOimSendReq *oim_request;
 	char *soap_body,*mspauth;
 	char *msg_body;
-	char buf[33];
 
 	g_return_if_fail(oim != NULL);
-	oim_request = g_queue_pop_head(oim->send_queue);
+	oim_request = g_queue_peek_head(oim->send_queue);
 	g_return_if_fail(oim_request != NULL);
 
-	purple_debug_info("MSNP14","send single OIM Message\n");
+	purple_debug_info("MSNP14","sending OIM: %s\n", oim_request->oim_msg);
 	mspauth = g_strdup_printf("t=%s&amp;p=%s",
 		oim->session->passport_info.t,
 		oim->session->passport_info.p
 		);
-	g_queue_push_head(oim->send_queue,oim_request);
 
 	/* if we got the challenge lock key, we compute it
 	 * else we go for the SOAP fault and resend it.
 	 */
-	if(oim->challenge != NULL){
-		msn_handle_chl(oim->challenge, buf);
-	}else{
+	if(oim->challenge == NULL){
 		purple_debug_info("MSNP14","no lock key challenge,wait for SOAP Fault and Resend\n");
-		buf[0]='\0';
 	}
-	purple_debug_info("MSNP14","get the lock key challenge {%s}\n",buf);	
 
 	msg_body = msn_oim_msg_to_str(oim, oim_request->oim_msg);
 	soap_body = g_strdup_printf(MSN_OIM_SEND_TEMPLATE,
@@ -311,117 +222,65 @@
 					oim_request->to_member,
 					mspauth,
 					MSNP13_WLM_PRODUCT_ID,
-					buf,
-					oim_request->send_seq,
-					msg_body
-					);
-	soap_request = msn_soap_request_new(MSN_OIM_SEND_HOST,
-					MSN_OIM_SEND_URL,
-					MSN_OIM_SEND_SOAP_ACTION,
-					soap_body,
-					NULL,
-					msn_oim_send_read_cb,
-					msn_oim_send_written_cb);
+					oim->challenge ? oim->challenge : "",
+					oim->send_seq,
+					msg_body);
+
+	msn_soap_message_send(oim->session,
+		msn_soap_message_new(MSN_OIM_SEND_SOAP_ACTION,
+			xmlnode_from_str(soap_body, -1)),
+		MSN_OIM_SEND_HOST, MSN_OIM_SEND_URL, msn_oim_send_read_cb, oim);
+
+	/*increase the offline Sequence control*/
+	if (oim->challenge != NULL) {
+		oim->send_seq++;
+	}
+
 	g_free(mspauth);
 	g_free(msg_body);
 	g_free(soap_body);
-
-	/*increase the offline Sequence control*/
-	if(oim->challenge != NULL){
-		oim->send_seq++;
-	}
-	msn_soap_post(oim->sendconn,soap_request,msn_oim_send_connect_init);
 }
 
 /****************************************
  * OIM delete SOAP request
  * **************************************/
 static void
-msn_oim_delete_read_cb(gpointer data, gint source, PurpleInputCondition cond)
+msn_oim_delete_read_cb(MsnSoapMessage *request, MsnSoapMessage *response,
+	gpointer data)
 {
-	MsnSoapConn * soapconn = data;
-
-	if (soapconn->body == NULL)
-		return;
-	purple_debug_info("MSNP14","OIM delete read buffer:{%s}\n",soapconn->body);
-
-	msn_soap_free_read_buf(soapconn);
-	/*get next single Offline Message*/
-	msn_soap_post(soapconn,NULL,msn_oim_retrieve_connect_init);
-}
-
-static void
-msn_oim_delete_written_cb(gpointer data, gint source, PurpleInputCondition cond)
-{
-	MsnSoapConn * soapconn = data;
-
-	soapconn->read_cb = msn_oim_delete_read_cb;
+	if (response) {
+		purple_debug_info("msnoim", "delete OIM success\n");
+	} else {
+		purple_debug_info("msnoim", "delete OIM failed\n");
+	}
 }
 
 /*Post to get the Offline Instant Message*/
 static void
 msn_oim_post_delete_msg(MsnOim *oim,const char *msgid)
 {
-	MsnSoapReq *soap_request;
-	const char *soap_body,*t,*p;
+	char *soap_body;
 
 	g_return_if_fail(oim != NULL);
 	g_return_if_fail(msgid != NULL);
 
 	purple_debug_info("MSNP14","Delete single OIM Message {%s}\n",msgid);
-	t = oim->session->passport_info.t;
-	p = oim->session->passport_info.p;
 
 	soap_body = g_strdup_printf(MSN_OIM_DEL_TEMPLATE,
-					t,
-					p,
-					msgid
-					);
-	soap_request = msn_soap_request_new(MSN_OIM_RETRIEVE_HOST,
-					MSN_OIM_RETRIEVE_URL,
-					MSN_OIM_DEL_SOAP_ACTION,
-					soap_body,
-					NULL,
-					msn_oim_delete_read_cb,
-					msn_oim_delete_written_cb);
-	msn_soap_post(oim->retrieveconn,soap_request,msn_oim_retrieve_connect_init);
+		oim->session->passport_info.t, oim->session->passport_info.p, msgid);
+
+	msn_soap_message_send(oim->session,
+		msn_soap_message_new(MSN_OIM_DEL_SOAP_ACTION,
+			xmlnode_from_str(soap_body, -1)),
+		MSN_OIM_RETRIEVE_HOST, MSN_OIM_RETRIEVE_URL,
+		msn_oim_delete_read_cb, NULL);
+
+	g_free(soap_body);
 }
 
 /****************************************
  * OIM get SOAP request
  * **************************************/
-/*oim SOAP server login error*/
-static void
-msn_oim_get_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error, void *data)
-{
-	MsnSoapConn *soapconn = data;
-	MsnSession *session;
-
-	session = soapconn->session;
-	g_return_if_fail(session != NULL);
-	msn_soap_clean_unhandled_request(soapconn);
-
-//	msn_session_set_error(session, MSN_ERROR_SERV_DOWN, _("Unable to connect to OIM server"));
-}
-
-/*msn oim SOAP server connect process*/
-static void
-msn_oim_get_connect_cb(gpointer data, PurpleSslConnection *gsc,
-				 PurpleInputCondition cond)
-{
-	MsnSoapConn *soapconn = data;
-	MsnSession * session;
-	MsnOim *oim;
-
-	oim = soapconn->parent;
-	g_return_if_fail(oim != NULL);
-
-	session = oim->session;
-	g_return_if_fail(session != NULL);
-
-	purple_debug_info("MSNP14","oim get SOAP Server connected!\n");
-}
-
 /* like purple_str_to_time, but different. The format of the timestamp
  * is like this: 5 Sep 2007 21:42:12 -0700 */
 static time_t
@@ -549,53 +408,29 @@
 	g_free(passport);
 }
 
-/* Parse the XML data,
- * prepare to report the OIM to user
- */
 static void
-msn_oim_get_process(MsnOim *oim, const char *oim_msg)
-{
-	xmlnode *oim_node,*bodyNode,*responseNode,*msgNode;
-	char *msg_str;
-
-	oim_node = xmlnode_from_str(oim_msg, strlen(oim_msg));
-	bodyNode = xmlnode_get_child(oim_node,"Body");
-	responseNode = xmlnode_get_child(bodyNode,"GetMessageResponse");
-	msgNode = xmlnode_get_child(responseNode,"GetMessageResult");
-	msg_str = xmlnode_get_data(msgNode);
-	purple_debug_info("OIM","msg:{%s}\n",msg_str);
-	msn_oim_report_to_user(oim,msg_str);
-
-	g_free(msg_str);
-	xmlnode_free(oim_node);
-}
-
-static void
-msn_oim_get_read_cb(gpointer data, gint source, PurpleInputCondition cond)
+msn_oim_get_read_cb(MsnSoapMessage *request, MsnSoapMessage *response,
+	gpointer data)
 {
-	MsnSoapConn * soapconn = data;
-	MsnOim * oim = soapconn->session->oim;
-
-	if (soapconn->body == NULL)
-		return;
+	MsnOim *oim = data;
 
-	purple_debug_info("MSNP14","OIM get read buffer:{%s}\n",soapconn->body);
-
-	/*we need to process the read message!*/
-	msn_oim_get_process(oim,soapconn->body);
-	msn_soap_free_read_buf(soapconn);
+	if (response != NULL) {
+		xmlnode *msg_node = msn_soap_xml_get(response->xml,
+			"Body/GetMessageResponse/GetMessageResult");
 
-	/*get next single Offline Message*/
-	msn_soap_post(soapconn,NULL,msn_oim_retrieve_connect_init);
-}
-
-static void
-msn_oim_get_written_cb(gpointer data, gint source, PurpleInputCondition cond)
-{
-	MsnSoapConn * soapconn = data;
-
-	soapconn->read_cb = msn_oim_get_read_cb;
-//	msn_soap_read_cb(data,source,cond);
+		if (msg_node) {
+			char *msg_str = xmlnode_get_data(msg_node);
+			msn_oim_report_to_user(oim, msg_str);
+			g_free(msg_str);
+			return;
+		} else {
+			char *str = xmlnode_to_str(response->xml, NULL);
+			purple_debug_info("msnoim", "Unknown response: %s\n", str);
+			g_free(str);
+		}
+	} else {
+		purple_debug_info("msnoim", "Failed to get OIM\n");
+	}
 }
 
 /* parse the oim XML data 
@@ -604,67 +439,63 @@
 void
 msn_parse_oim_msg(MsnOim *oim,const char *xmlmsg)
 {
-	xmlnode *node, *mNode,*ENode,*INode,*rtNode,*nNode;
-	char *passport,*msgid,*nickname, *unread, *rTime = NULL;
+	xmlnode *node, *mNode;
+	xmlnode *iu_node;
 	MsnSession *session = oim->session;
 
 	purple_debug_info("MSNP14:OIM", "%s", xmlmsg);
 
-	node = xmlnode_from_str(xmlmsg, strlen(xmlmsg));
+	node = xmlnode_from_str(xmlmsg, -1);
 	if (strcmp(node->name, "MD") != 0) {
+		purple_debug_info("msnoim", "WTF is this? %s\n", xmlmsg);
 		xmlnode_free(node);
 		return;
 	}
 
-	ENode = xmlnode_get_child(node, "E");
-	INode = xmlnode_get_child(ENode, "IU");
-	unread = xmlnode_get_data(INode);
-
-	if (unread != NULL && purple_account_get_check_mail(session->account))
-	{
-		int count = atoi(unread);
+	iu_node = msn_soap_xml_get(node, "E/IU");
 
-		if (count > 0)
-		{
-			const char *passport;
-			const char *url;
+	if (iu_node != NULL && purple_account_get_check_mail(session->account))
+	{
+		char *unread = xmlnode_get_data(iu_node);
+		const char *passport = msn_user_get_passport(session->user);
+		const char *url = session->passport_info.file;
 
-			passport = msn_user_get_passport(session->user);
-			url = session->passport_info.file;
-
-			purple_notify_emails(session->account->gc, atoi(unread), FALSE, NULL, NULL,
-					&passport, &url, NULL, NULL);
-		}
+		/* XXX/khc: pretty sure this is wrong */
+		purple_notify_emails(session->account->gc, atoi(unread), FALSE, NULL,
+			NULL, &passport, &url, NULL, NULL);
+		g_free(unread);
 	}
 
 	for(mNode = xmlnode_get_child(node, "M"); mNode;
 					mNode = xmlnode_get_next_twin(mNode)){
-		/*email Node*/
-		ENode = xmlnode_get_child(mNode,"E");
-		passport = xmlnode_get_data(ENode);
-		/*Index */
-		INode = xmlnode_get_child(mNode,"I");
-		msgid = xmlnode_get_data(INode);
-		/*Nickname*/
-		nNode = xmlnode_get_child(mNode,"N");
-		nickname = xmlnode_get_data(nNode);
-		/*receive time*/
-		rtNode = xmlnode_get_child(mNode,"RT");
-		if(rtNode != NULL) {
-			rTime = xmlnode_get_data(rtNode);
-			rtNode = NULL;
+		char *passport, *msgid, *nickname, *rtime = NULL;
+		xmlnode *e_node, *i_node, *n_node, *rt_node;
+
+		e_node = xmlnode_get_child(mNode, "E");
+		passport = xmlnode_get_data(e_node);
+
+		i_node = xmlnode_get_child(mNode, "I");
+		msgid = xmlnode_get_data(i_node);
+
+		n_node = xmlnode_get_child(mNode, "N");
+		nickname = xmlnode_get_data(n_node);
+
+		rt_node = xmlnode_get_child(mNode, "RT");
+		if (rt_node != NULL) {
+			rtime = xmlnode_get_data(rt_node);
 		}
-/*		purple_debug_info("MSNP14","E:{%s},I:{%s},rTime:{%s}\n",passport,msgid,rTime); */
+/*		purple_debug_info("msnoim","E:{%s},I:{%s},rTime:{%s}\n",passport,msgid,rTime); */
 
-		oim->oim_list = g_list_append(oim->oim_list,strdup(msgid));
-		msn_oim_post_single_get_msg(oim,msgid);
+		oim->oim_list = g_list_append(oim->oim_list, msgid);
+		msn_oim_post_single_get_msg(oim, msgid);
+		msgid = NULL;
+
 		g_free(passport);
 		g_free(msgid);
-		g_free(rTime);
-		rTime = NULL;
+		g_free(rtime);
 		g_free(nickname);
 	}
-	g_free(unread);
+
 	xmlnode_free(node);
 }
 
@@ -672,46 +503,18 @@
 static void
 msn_oim_post_single_get_msg(MsnOim *oim,const char *msgid)
 {
-	MsnSoapReq *soap_request;
-	const char *soap_body,*t,*p;
+	char *soap_body;
 
 	purple_debug_info("MSNP14","Get single OIM Message\n");
-	t = oim->session->passport_info.t;
-	p = oim->session->passport_info.p;
 
 	soap_body = g_strdup_printf(MSN_OIM_GET_TEMPLATE,
-					t,
-					p,
-					msgid
-					);
-	soap_request = msn_soap_request_new(MSN_OIM_RETRIEVE_HOST,
-					MSN_OIM_RETRIEVE_URL,
-					MSN_OIM_GET_SOAP_ACTION,
-					soap_body,
-					NULL,
-					msn_oim_get_read_cb,
-					msn_oim_get_written_cb);
-	msn_soap_post(oim->retrieveconn,soap_request,msn_oim_retrieve_connect_init);
-}
+		oim->session->passport_info.t, oim->session->passport_info.p, msgid);
 
-/*msn oim retrieve server connect init */
-static void
-msn_oim_retrieve_connect_init(MsnSoapConn *soapconn)
-{
-	purple_debug_info("MSNP14","msn_oim_connect...\n");
-	msn_soap_init(soapconn,MSN_OIM_RETRIEVE_HOST,1,
-					msn_oim_get_connect_cb,
-					msn_oim_get_error_cb);
-}
+	msn_soap_message_send(oim->session,
+		msn_soap_message_new(MSN_OIM_GET_SOAP_ACTION,
+			xmlnode_from_str(soap_body, -1)),
+		MSN_OIM_RETRIEVE_HOST, MSN_OIM_RETRIEVE_URL,
+		msn_oim_get_read_cb, oim);
 
-/*Msn OIM Send Server Connect Init Function*/
-static void
-msn_oim_send_connect_init(MsnSoapConn *sendconn)
-{
-	purple_debug_info("MSNP14","msn oim send connect init...\n");
-	msn_soap_init(sendconn,MSN_OIM_SEND_HOST,1,
-					msn_oim_send_connect_cb,
-					msn_oim_send_error_cb);
+	g_free(soap_body);
 }
-
-/*endof oim.c*/
--- a/libpurple/protocols/msn/oim.h	Mon Oct 01 01:22:37 2007 +0000
+++ b/libpurple/protocols/msn/oim.h	Mon Oct 01 07:20:35 2007 +0000
@@ -95,17 +95,6 @@
 	"</soap:Body>"\
 "</soap:Envelope>"
 
-typedef struct _MsnOimSendReq MsnOimSendReq;
-
-struct _MsnOimSendReq
-{
-	char *from_member;
-	char *friendname;
-	char *to_member;
-	char *oim_msg;
-	gint send_seq;
-};
-
 typedef struct _MsnOim MsnOim;
 
 struct _MsnOim
@@ -127,7 +116,6 @@
  * **************************************************/
 MsnOim * msn_oim_new(MsnSession *session);
 void msn_oim_destroy(MsnOim *oim);
-void msn_oim_connect(MsnOim *oim);
 
 void msn_parse_oim_msg(MsnOim *oim,const char *xmlmsg);
 
@@ -138,11 +126,5 @@
 
 void msn_oim_send_msg(MsnOim *oim);
 
-/*get the OIM message*/
-void msn_oim_get_msg(MsnOim *oim);
-
-/*report the oim message to the conversation*/
-void msn_oim_report_user(MsnOim *oim,const char *passport,char *msg);
-
 #endif/* _MSN_OIM_H_*/
 /*endof oim.h*/
--- a/libpurple/protocols/msn/session.c	Mon Oct 01 01:22:37 2007 +0000
+++ b/libpurple/protocols/msn/session.c	Mon Oct 01 07:20:35 2007 +0000
@@ -24,6 +24,7 @@
 #include "msn.h"
 #include "session.h"
 #include "notification.h"
+#include "oim.h"
 
 #include "dialog.h"
 
@@ -42,6 +43,7 @@
 
 	session->user = msn_user_new(session->userlist,
 								 purple_account_get_username(account), NULL);
+	session->oim = msn_oim_new(session);
 
 	/*if you want to chat with Yahoo Messenger*/
 	//session->protocol_ver = WLM_YAHOO_PROT_VER;
--- a/libpurple/protocols/msn/soap2.c	Mon Oct 01 01:22:37 2007 +0000
+++ b/libpurple/protocols/msn/soap2.c	Mon Oct 01 07:20:35 2007 +0000
@@ -33,9 +33,7 @@
 #include <glib.h>
 #include <error.h>
 
-#define SOAP_TIMEOUT 10
-
-static GHashTable *conn_table = NULL;
+#define SOAP_TIMEOUT (5 * 60)
 
 typedef struct _MsnSoapRequest {
 	char *path;
@@ -122,7 +120,7 @@
 	MsnSoapConnection *conn = NULL;
 
 	if (session->soap_table) {
-		conn = g_hash_table_lookup(conn_table, host);
+		conn = g_hash_table_lookup(session->soap_table, host);
 	} else {
 		session->soap_table = g_hash_table_new_full(g_str_hash, g_str_equal,
 			NULL, (GDestroyNotify)msn_soap_connection_destroy);
@@ -207,12 +205,9 @@
 static gboolean
 msn_soap_handle_body(MsnSoapConnection *conn, MsnSoapMessage *response)
 {
-	xmlnode *node = response->xml;
+	xmlnode *body = xmlnode_get_child(response->xml, "Body");
 
-	if (strcmp(node->name, "Envelope") == 0 &&
-		node->child && strcmp(node->child->name, "Header") == 0 &&
-		node->child->next) {
-		xmlnode *body = node->child->next;
+	if (body) {
 		MsnSoapRequest *request;
 
 		if (strcmp(body->name, "Fault") == 0) {
@@ -297,7 +292,82 @@
 
 	cursor = conn->buf->str + conn->handled_len;
 
-	if (conn->headers_done) {
+	if (!conn->headers_done) {
+		while ((linebreak = strstr(cursor, "\r\n"))	!= NULL) {
+			conn->handled_len = linebreak - conn->buf->str + 2;
+
+			if (conn->response_code == 0) {
+				if (sscanf(cursor, "HTTP/1.1 %d", &conn->response_code) != 1) {
+					/* something horribly wrong */
+					purple_ssl_close(conn->ssl);
+					conn->ssl = NULL;
+					msn_soap_connection_handle_next(conn);
+					handled = TRUE;
+					break;
+				} else if (conn->response_code == 503) {
+					msn_soap_connection_sanitize(conn, TRUE);
+					msn_session_set_error(conn->session, MSN_ERROR_SERV_UNAVAILABLE, NULL);
+					return;
+				}
+			} else if (cursor == linebreak) {
+				/* blank line */
+				conn->headers_done = TRUE;
+				cursor = conn->buf->str + conn->handled_len;
+				break;
+			} else {
+				char *line = g_strndup(cursor, linebreak - cursor);
+				char *sep = strstr(line, ": ");
+				char *key = line;
+				char *value;
+
+				if (sep == NULL) {
+					purple_debug_info("soap", "ignoring malformed line: %s\n", line);
+					g_free(line);
+					goto loop_end;
+				}
+
+				value = sep + 2;
+				*sep = '\0';
+				msn_soap_message_add_header(conn->message, key, value);
+				purple_debug_info("soap", "header %s: %s\n", key, value);
+
+				if ((conn->response_code == 301 || conn->response_code == 300)
+					&& strcmp(key, "Location") == 0) {
+
+					msn_soap_handle_redirect(conn, value);
+
+					handled = TRUE;
+					g_free(line);
+					break;
+				} else if (conn->response_code == 401 &&
+					strcmp(key, "WWW-Authenticate") == 0) {
+					char *error = strstr(value, "cbtxt=");
+
+					if (error) {
+						error += strlen("cbtxt=");
+					}
+
+					msn_soap_connection_sanitize(conn, TRUE);
+					msn_session_set_error(conn->session, MSN_ERROR_AUTH,
+						error ? purple_url_decode(error) : NULL);
+
+					g_free(line);
+					return;
+				} else if (strcmp(key, "Content-Length") == 0) {
+					conn->body_len = atoi(value);
+				} else if (strcmp(key, "Connection") == 0) {
+					if (strcmp(value, "close") == 0) {
+						conn->close_when_done = TRUE;
+					}
+				}
+			}
+
+		loop_end:
+			cursor = conn->buf->str + conn->handled_len;
+		}
+	}
+
+	if (!handled && conn->headers_done) {
 		if (conn->buf->len - conn->handled_len >= 
 			conn->body_len) {
 			xmlnode *node = xmlnode_from_str(cursor, conn->body_len);
@@ -320,77 +390,6 @@
 		return;
 	}
 
-	while ((linebreak = strstr(cursor, "\r\n"))	!= NULL) {
-		conn->handled_len = linebreak - conn->buf->str + 2;
-
-		if (conn->response_code == 0) {
-			if (sscanf(cursor, "HTTP/1.1 %d", &conn->response_code) != 1) {
-				/* something horribly wrong */
-				purple_ssl_close(conn->ssl);
-				conn->ssl = NULL;
-				msn_soap_connection_handle_next(conn);
-				handled = TRUE;
-				break;
-			} else if (conn->response_code == 503) {
-				msn_soap_connection_sanitize(conn, TRUE);
-				msn_session_set_error(conn->session, MSN_ERROR_SERV_UNAVAILABLE, NULL);
-				return;
-			}
-		} else if (cursor == linebreak) {
-			/* blank line */
-			conn->headers_done = TRUE;
-		} else {
-			char *line = g_strndup(cursor, linebreak - cursor);
-			char *sep = strstr(line, ": ");
-			char *key = line;
-			char *value;
-
-			if (sep == NULL) {
-				purple_debug_info("soap", "ignoring malformed line: %s\n", line);
-				g_free(line);
-				goto loop_end;
-			}
-
-			value = sep + 2;
-			*sep = '\0';
-			msn_soap_message_add_header(conn->message, key, value);
-			purple_debug_info("soap", "header %s: %s\n", key, value);
-
-			if ((conn->response_code == 301 || conn->response_code == 300)
-				&& strcmp(key, "Location") == 0) {
-
-				msn_soap_handle_redirect(conn, value);
-
-				handled = TRUE;
-				g_free(line);
-				break;
-			} else if (conn->response_code == 401 &&
-				strcmp(key, "WWW-Authenticate") == 0) {
-				char *error = strstr(value, "cbtxt=");
-
-				if (error) {
-					error += strlen("cbtxt=");
-				}
-
-				msn_soap_connection_sanitize(conn, TRUE);
-				msn_session_set_error(conn->session, MSN_ERROR_AUTH,
-					error ? purple_url_decode(error) : NULL);
-
-				g_free(line);
-				return;
-			} else if (strcmp(key, "Content-Length") == 0) {
-				conn->body_len = atoi(value);
-			} else if (strcmp(key, "Connection") == 0) {
-				if (strcmp(value, "close") == 0) {
-					conn->close_when_done = TRUE;
-				}
-			}
-		}
-
-	loop_end:
-		cursor = conn->buf->str + conn->handled_len;
-	}
-
 	if (handled) {
 		msn_soap_connection_handle_next(conn);
 	}