changeset 20539:2c8c6d77f12c

Make use of the GQueue in MsnSoapConn to manage the SOAP requests, allowing them to work perfectly even when dispatching multiple requests at once. Delete a user from the userlist after the contact is deleted from the server.
author Carlos Silva <typ0@pidgin.im>
date Wed, 19 Sep 2007 06:08:42 +0000
parents 5bef3197383a
children ce701480237b
files libpurple/protocols/msn/contact.c libpurple/protocols/msn/contact.h libpurple/protocols/msn/nexus.c libpurple/protocols/msn/oim.c libpurple/protocols/msn/soap.c libpurple/protocols/msn/soap.h libpurple/protocols/msn/userlist.c libpurple/protocols/msn/userlist.h
diffstat 8 files changed, 617 insertions(+), 421 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/msn/contact.c	Sun Sep 16 18:47:12 2007 +0000
+++ b/libpurple/protocols/msn/contact.c	Wed Sep 19 06:08:42 2007 +0000
@@ -83,6 +83,9 @@
 	if (state->who != NULL)
 		g_free(state->who);
 	
+	if (state->uid != NULL)
+		g_free(state->uid);
+
 	if (state->old_group_name != NULL)
 		g_free(state->old_group_name);
 	
@@ -91,7 +94,7 @@
 	
 	if (state->guid != NULL)
 		g_free(state->guid);
-	
+
 	g_free(state);
 }
 	
@@ -112,6 +115,22 @@
 }
 
 void
+msn_callback_state_set_uid(MsnCallbackState *state, const gchar *uid)
+{
+        gchar *new_str = NULL;
+
+        g_return_if_fail(state != NULL);
+
+        if (uid != NULL)
+                new_str = g_strdup(uid);
+
+        if (state->uid != NULL)
+                g_free(state->uid);
+
+        state->uid = new_str;
+}
+
+void
 msn_callback_state_set_old_group_name(MsnCallbackState *state, const gchar *old_group_name)
 {
 	gchar *new_str = NULL;
@@ -178,9 +197,8 @@
 		       
 /*contact SOAP server login error*/
 static void
-msn_contact_login_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error, void *data)
+msn_contact_login_error_cb(MsnSoapConn *soapconn, PurpleSslConnection *gsc, PurpleSslErrorType error)
 {
-	MsnSoapConn *soapconn = data;
 	MsnSession *session;
 
 	session = soapconn->session;
@@ -190,22 +208,21 @@
 }
 
 /*msn contact SOAP server connect process*/
-static void
-msn_contact_login_connect_cb(gpointer data, PurpleSslConnection *gsc,
-				 PurpleInputCondition cond)
+static gboolean
+msn_contact_login_connect_cb(MsnSoapConn *soapconn, PurpleSslConnection *gsc)
 {
-	MsnSoapConn *soapconn = data;
 	MsnSession * session;
 	MsnContact *contact;
 
 	contact = soapconn->parent;
-	g_return_if_fail(contact != NULL);
+	g_return_val_if_fail(contact != NULL, TRUE);
 
 	session = contact->session;
-	g_return_if_fail(session != NULL);
+	g_return_val_if_fail(session != NULL, FALSE);
 
 	/*login ok!We can retrieve the contact list*/
 //	msn_get_contact_list(contact, MSN_PS_INITIAL, NULL);
+	return TRUE;
 }
 
 /*get MSN member role utility*/
@@ -243,30 +260,27 @@
 }
 
 /* Create the AddressBook in the server, if we don't have one */
-static void
-msn_create_address_cb(gpointer data, gint source, PurpleInputCondition cond)
+static gboolean
+msn_create_address_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn *soapconn = data;
 	MsnContact *contact;
 
 	if (soapconn->body == NULL)
-		return;
+		return TRUE;
 
 	contact = soapconn->parent;
-	g_return_if_fail(contact != NULL);
+	g_return_val_if_fail(contact != NULL, TRUE);
 
 	purple_debug_info("MSN AddressBook", "Address Book successfully created!\n");
 	msn_get_address_book(contact, MSN_PS_INITIAL, NULL, NULL);
 
 //	msn_soap_free_read_buf(soapconn);
-	return;
+	return TRUE;
 }
 
 static void
-msn_create_address_written_cb(gpointer data, gint source, PurpleInputCondition cond)
+msn_create_address_written_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;
-
 	purple_debug_info("MSN AddressBook","AddressBookAdd written\n");
 	soapconn->read_cb = msn_create_address_cb;
 
@@ -293,8 +307,9 @@
 					body,
 					NULL,
 					msn_create_address_cb,
-					msn_create_address_written_cb);
-	msn_soap_post(contact->soapconn, soap_request, msn_contact_connect_init);
+					msn_create_address_written_cb,
+					msn_contact_connect_init);
+	msn_soap_post(contact->soapconn, soap_request);
 
 	g_free(body);
 	
@@ -527,10 +542,9 @@
 	xmlnode_free(node);	/* Free the whole XML tree */
 }
 
-static void
-msn_get_contact_list_cb(gpointer data, gint source, PurpleInputCondition cond)
+static gboolean
+msn_get_contact_list_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn *soapconn = data;
 	MsnContact *contact;
 	MsnSession *session;
 	const char *abLastChange;
@@ -538,15 +552,15 @@
 	gchar *partner_scenario;
 
 	if (soapconn->body == NULL)
-		return;
+		return TRUE;
 
 	purple_debug_misc("MSNCL","Got the contact list!\n");
 
 	contact = soapconn->parent;
-	g_return_if_fail(contact != NULL);
+	g_return_val_if_fail(contact != NULL, TRUE);
 	session = soapconn->session;
-	g_return_if_fail(session != NULL);
-	g_return_if_fail(soapconn->data_cb != NULL);
+	g_return_val_if_fail(session != NULL, FALSE);
+	g_return_val_if_fail(soapconn->data_cb != NULL, TRUE);
 
 	partner_scenario = soapconn->data_cb;
 
@@ -570,19 +584,18 @@
 	} else {
 		msn_soap_free_read_buf(soapconn);
 	}
+
+	return TRUE;
 }
 
 static void
-msn_get_contact_written_cb(gpointer data, gint source, PurpleInputCondition cond)
+msn_get_contact_written_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;	
-
 	purple_debug_misc("MSNCL","Sent SOAP request for the contact list.\n");
 	soapconn->read_cb = msn_get_contact_list_cb;
-//	msn_soap_read_cb(data,source,cond);
 }
 
-/*SOAP  get contact list*/
+/* SOAP  get contact list*/
 void
 msn_get_contact_list(MsnContact * contact, const MsnSoapPartnerScenario partner_scenario, const char *update_time)
 {
@@ -609,8 +622,9 @@
 					body,
 					(gpointer) partner_scenario_str,
 					msn_get_contact_list_cb,
-					msn_get_contact_written_cb);
-	msn_soap_post(contact->soapconn,soap_request,msn_contact_connect_init);
+					msn_get_contact_written_cb,
+					msn_contact_connect_init);
+	msn_soap_post(contact->soapconn,soap_request);
 	g_free(body);
 }
 
@@ -902,20 +916,19 @@
 	return TRUE;
 }
 
-static void
-msn_get_address_cb(gpointer data, gint source, PurpleInputCondition cond)
+static gboolean
+msn_get_address_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;	
 	MsnContact *contact;
 	MsnSession *session;
 
 	if (soapconn->body == NULL)
-		return;
+		return TRUE;
 
 	contact = soapconn->parent;
-	g_return_if_fail(contact != NULL);
+	g_return_val_if_fail(contact != NULL, TRUE);
 	session = soapconn->session;
-	g_return_if_fail(session != NULL);
+	g_return_val_if_fail(session != NULL, FALSE);
 
 	purple_debug_misc("MSN AddressBook", "Got the Address Book!\n");
 
@@ -926,6 +939,10 @@
 			msn_send_privacy(session->account->gc);
 			msn_notification_dump_contact(session);
 		}
+
+		/*free the read buffer*/
+		msn_soap_free_read_buf(soapconn);
+		return TRUE;
 	} else {
 		/* This is making us loop infinitely when we fail to parse the address book,
 		  disable for now (we should re-enable when we send timestamps)
@@ -935,18 +952,14 @@
 		*/
 		msn_session_disconnect(session);
 		purple_connection_error(session->account->gc, _("Unable to retrieve MSN Address Book"));
+		return FALSE;
 	}
-
-	/*free the read buffer*/
-	msn_soap_free_read_buf(soapconn);
 }
 
 /**/
 static void
-msn_address_written_cb(gpointer data, gint source, PurpleInputCondition cond)
+msn_address_written_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;	
-
 	purple_debug_misc("MSN AddressBook","Sent SOAP request for the Address Book.\n");
 	soapconn->read_cb = msn_get_address_cb;
 }
@@ -984,28 +997,28 @@
 					body,
 					NULL,
 					msn_get_address_cb,
-					msn_address_written_cb);
-	msn_soap_post(contact->soapconn,soap_request,msn_contact_connect_init);
+					msn_address_written_cb,
+					msn_contact_connect_init);
+	msn_soap_post(contact->soapconn,soap_request);
 	g_free(body);
 }
 
-static void
-msn_add_contact_read_cb(gpointer data, gint source, PurpleInputCondition cond)
+static gboolean
+msn_add_contact_read_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;
 	MsnCallbackState *state = NULL;
 	MsnUserList *userlist;
 	MsnUser *user;
 	
-	g_return_if_fail(soapconn->data_cb != NULL);
-	g_return_if_fail(soapconn->session != NULL);
-	g_return_if_fail(soapconn->session->userlist != NULL);
+	g_return_val_if_fail(soapconn->data_cb != NULL, TRUE);
+	g_return_val_if_fail(soapconn->session != NULL, FALSE);
+	g_return_val_if_fail(soapconn->session->userlist != NULL, TRUE);
 
 	state = (MsnCallbackState *) soapconn->data_cb;
 
 	if (soapconn->body == NULL) {
 		msn_callback_state_free(state);
-		return;
+		return TRUE;
 	}
 	
 	userlist = soapconn->session->userlist;
@@ -1032,13 +1045,13 @@
 	}
 	
 	msn_callback_state_free(state);
+
+	return TRUE;
 }
 
 static void
-msn_add_contact_written_cb(gpointer data, gint source, PurpleInputCondition cond)
+msn_add_contact_written_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;	
-
 	purple_debug_info("MSNCL","Add contact request written\n");
 	soapconn->read_cb = msn_add_contact_read_cb;
 }
@@ -1079,23 +1092,23 @@
 					body,
 					state,
 					msn_add_contact_read_cb,
-					msn_add_contact_written_cb);
-	msn_soap_post(contact->soapconn,soap_request,msn_contact_connect_init);
+					msn_add_contact_written_cb,
+					msn_contact_connect_init);
+	msn_soap_post(contact->soapconn,soap_request);
 
 	g_free(soap_action);
 	g_free(body);
 }
 
-static void
-msn_add_contact_to_group_read_cb(gpointer data, gint source, PurpleInputCondition cond)
+static gboolean
+msn_add_contact_to_group_read_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;
 	MsnCallbackState *state; 
 	MsnUserList *userlist;
 
-	g_return_if_fail(soapconn->data_cb != NULL);
-	g_return_if_fail(soapconn->session != NULL);
-	g_return_if_fail(soapconn->session->userlist != NULL);
+	g_return_val_if_fail(soapconn->data_cb != NULL, TRUE);
+	g_return_val_if_fail(soapconn->session != NULL, FALSE);
+	g_return_val_if_fail(soapconn->session->userlist != NULL, TRUE);
 
 	userlist = soapconn->session->userlist;
 
@@ -1103,7 +1116,7 @@
 
 	if (soapconn->body == NULL) {
 		msn_callback_state_free(state);
-		return;
+		return TRUE;
 	}
 	
 	if (msn_userlist_add_buddy_to_group(userlist, state->who, state->new_group_name) == TRUE) {
@@ -1125,7 +1138,7 @@
 		if (msn_userlist_user_is_in_list(user, MSN_LIST_PL)) {
 			msn_del_contact_from_list(soapconn->session->contact, NULL, state->who, MSN_LIST_PL);
 			msn_callback_state_free(state);
-			return;
+			return TRUE;
 		}
 	}
 
@@ -1135,13 +1148,12 @@
 		msn_callback_state_free(state);
 		msn_soap_free_read_buf(soapconn);
 	}
+	return TRUE;
 }
 
 static void
-msn_add_contact_to_group_written_cb(gpointer data, gint source, PurpleInputCondition cond)
+msn_add_contact_to_group_written_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;	
-
 	purple_debug_info("MSNCL","Add contact to group request sent!\n");
 	soapconn->read_cb = msn_add_contact_to_group_read_cb;
 }
@@ -1210,8 +1222,9 @@
 					body,
 					state,
 					msn_add_contact_to_group_read_cb,
-					msn_add_contact_to_group_written_cb);
-	msn_soap_post(contact->soapconn,soap_request,msn_contact_connect_init);
+					msn_add_contact_to_group_written_cb,
+					msn_contact_connect_init);
+	msn_soap_post(contact->soapconn,soap_request);
 
 	g_free(soap_action);
 	g_free(body);
@@ -1219,24 +1232,39 @@
 
 
 
-static void
-msn_delete_contact_read_cb(gpointer data, gint source, PurpleInputCondition cond)
+static gboolean
+msn_delete_contact_read_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;
+	MsnUser *user;
+	MsnCallbackState *state = (MsnCallbackState *) soapconn->data_cb;
+	MsnUserList *userlist; 
+
+	g_return_val_if_fail(soapconn->session != NULL, FALSE);
+	g_return_val_if_fail(soapconn->session->userlist != NULL, TRUE);
+
+	userlist = soapconn->session->userlist;
 
-	if (soapconn->body == NULL)
-		return;
+        if (soapconn->body == NULL) {
+                msn_callback_state_free(state);
+                return TRUE;
+        }
+
+	purple_debug_info("MSNCL","Delete contact successful\n");
 
-	// we should probably delete it from the userlist aswell
-	purple_debug_info("MSNCL","Delete contact successful\n");
+	user = msn_userlist_find_user_with_id(userlist, state->uid);
+	if (user != NULL) {
+		msn_userlist_remove_user(userlist, user);
+	}
+
+	msn_callback_state_free(state);
 	msn_soap_free_read_buf(soapconn);
+
+	return TRUE;
 }
 
 static void
-msn_delete_contact_written_cb(gpointer data, gint source, PurpleInputCondition cond)
+msn_delete_contact_written_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;	
-
 	purple_debug_info("MSNCL","Delete contact request written\n");
 	soapconn->read_cb = msn_delete_contact_read_cb;
 }
@@ -1248,10 +1276,14 @@
 	gchar *body = NULL;
 	gchar *contact_id_xml = NULL ;
 	MsnSoapReq *soap_request;
+	MsnCallbackState *state;
 
 	g_return_if_fail(contactId != NULL);
 	contact_id_xml = g_strdup_printf(MSN_CONTACT_ID_XML, contactId);
 
+	state = msn_callback_state_new();
+	msn_callback_state_set_uid(state, contactId);
+
 	/* build SOAP request */
 	purple_debug_info("MSNCL","Deleting contact with contactId: %s\n", contactId);
 	body = g_strdup_printf(MSN_DEL_CONTACT_TEMPLATE, contact_id_xml);
@@ -1259,27 +1291,27 @@
 					MSN_ADDRESS_BOOK_POST_URL,
 					MSN_CONTACT_DEL_SOAP_ACTION,
 					body,
-					NULL,
+					state,
 					msn_delete_contact_read_cb,
-					msn_delete_contact_written_cb);
+					msn_delete_contact_written_cb,
+					msn_contact_connect_init);
 
 	g_free(contact_id_xml);
 
 	/* POST the SOAP request */
-	msn_soap_post(contact->soapconn, soap_request, msn_contact_connect_init);
+	msn_soap_post(contact->soapconn, soap_request);
 
 	g_free(body);
 }
 
-static void
-msn_del_contact_from_group_read_cb(gpointer data, gint source, PurpleInputCondition cond)
+static gboolean
+msn_del_contact_from_group_read_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;
 	MsnCallbackState *state = (MsnCallbackState *) soapconn->data_cb;
 
 	if (soapconn->body == NULL) {
 		msn_callback_state_free(state);
-		return;
+		return TRUE;
 	}
 	
 	if (msn_userlist_rem_buddy_from_group(soapconn->session->userlist, state->who, state->old_group_name)) {
@@ -1290,14 +1322,13 @@
 	
 	msn_callback_state_free(state);
 	msn_soap_free_read_buf(soapconn);
-	return;
+
+	return TRUE;
 }
 
 static void
-msn_del_contact_from_group_written_cb(gpointer data, gint source, PurpleInputCondition cond)
+msn_del_contact_from_group_written_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;	
-	
 	purple_debug_info("MSN CL","Del contact from group request sent!\n");
 	soapconn->read_cb = msn_del_contact_from_group_read_cb;
 }
@@ -1358,30 +1389,29 @@
 					    body,
 					    state,
 					    msn_del_contact_from_group_read_cb,
-					    msn_del_contact_from_group_written_cb);
-	msn_soap_post(contact->soapconn,soap_request,msn_contact_connect_init);
+					    msn_del_contact_from_group_written_cb,
+					    msn_contact_connect_init);
+	msn_soap_post(contact->soapconn,soap_request);
 	
 	g_free(soap_action);
 	g_free(body);
 }
 
 
-static void
-msn_update_contact_read_cb(gpointer data, gint source, PurpleInputCondition cond)
+static gboolean
+msn_update_contact_read_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn *soapconn = data;
-
 	if (soapconn->body == NULL)
-		return;
+		return TRUE;
 
 	purple_debug_info("MSN CL","Contact updated successfully\n");
+
+	return TRUE;
 }
 
 static void
-msn_update_contact_written_cb(gpointer data, gint source, PurpleInputCondition cond)
+msn_update_contact_written_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;	
-
 	purple_debug_info("MSN CL","Update contact information request sent\n");
 	soapconn->read_cb = msn_update_contact_read_cb;
 }
@@ -1408,60 +1438,60 @@
 					body,
 					NULL,
 					msn_update_contact_read_cb,
-					msn_update_contact_written_cb);
-	msn_soap_post(contact->soapconn, soap_request, msn_contact_connect_init);
+					msn_update_contact_written_cb,
+					msn_contact_connect_init);
+	msn_soap_post(contact->soapconn, soap_request);
 
 	g_free(body);
 }
 
 
-static void
-msn_del_contact_from_list_read_cb(gpointer data, gint source, PurpleInputCondition cond)
+static gboolean
+msn_del_contact_from_list_read_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;
 	MsnCallbackState *state = NULL;
 
-	g_return_if_fail(soapconn->data_cb != NULL);
-	g_return_if_fail(soapconn->session != NULL);
-	g_return_if_fail(soapconn->session->contact != NULL);
+	g_return_val_if_fail(soapconn->data_cb != NULL, TRUE);
+	g_return_val_if_fail(soapconn->session != NULL, FALSE);
+	g_return_val_if_fail(soapconn->session->contact != NULL, FALSE);
 
 	state = (MsnCallbackState *) soapconn->data_cb;
 
 	if (soapconn->body == NULL) {
 		msn_callback_state_free(state);
-		return;
+		return TRUE;
 	}
 	
 	purple_debug_info("MSN CL", "Contact %s deleted successfully from %s list on server!\n", state->who, MsnMemberRole[state->list_id]);
 
 	if (state->list_id == MSN_LIST_PL) {
 		msn_add_contact_to_list(soapconn->session->contact, state, state->who, MSN_LIST_RL);
-		return;
+		return TRUE;
 	}
 
 	if (state->list_id == MSN_LIST_AL) {
 		purple_privacy_permit_remove(soapconn->session->account, state->who, TRUE);
 		msn_add_contact_to_list(soapconn->session->contact, NULL, state->who, MSN_LIST_BL);
 		msn_callback_state_free(state);
-		return;
+		return TRUE;
 	}
 
 	if (state->list_id == MSN_LIST_BL) {
 		purple_privacy_deny_remove(soapconn->session->account, state->who, TRUE);
 		msn_add_contact_to_list(soapconn->session->contact, NULL, state->who, MSN_LIST_AL);
 		msn_callback_state_free(state);
-		return;
+		return TRUE;
 	}
 
 	msn_callback_state_free(state);
 	msn_soap_free_read_buf(soapconn);
+
+	return TRUE;
 }
 
 static void
-msn_del_contact_from_list_written_cb(gpointer data, gint source, PurpleInputCondition cond)
+msn_del_contact_from_list_written_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;
-
 	purple_debug_info("MSN CL","Delete contact from list SOAP request sent!\n");
 	soapconn->read_cb = msn_del_contact_from_list_read_cb;
 }
@@ -1514,36 +1544,36 @@
 					     body,
 					     state,
 					     msn_del_contact_from_list_read_cb,
-					     msn_del_contact_from_list_written_cb);
+					     msn_del_contact_from_list_written_cb,
+					     msn_contact_connect_init);
 
-	msn_soap_post(contact->soapconn,soap_request,msn_contact_connect_init);
+	msn_soap_post(contact->soapconn,soap_request);
 	
 	g_free(body);
 }
 
-static void
-msn_add_contact_to_list_read_cb(gpointer data, gint source, PurpleInputCondition cond)
+static gboolean
+msn_add_contact_to_list_read_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;
 	MsnCallbackState *state = NULL;
 
-	g_return_if_fail(soapconn->data_cb != NULL);
+	g_return_val_if_fail(soapconn->data_cb != NULL, TRUE);
 
 	state = (MsnCallbackState *) soapconn->data_cb;
 	
 	if (soapconn->body == NULL) {
 		msn_callback_state_free(state);
-		return;
+		return TRUE;
 	}
 	
 	purple_debug_info("MSN CL", "Contact %s added successfully to %s list on server!\n", state->who, MsnMemberRole[state->list_id]);
 
 	if (state->list_id == MSN_LIST_RL && (state->action & MSN_DENIED_BUDDY) ) {
-		g_return_if_fail(soapconn->session != NULL);
-		g_return_if_fail(soapconn->session->contact != NULL);
+		g_return_val_if_fail(soapconn->session != NULL, FALSE);
+		g_return_val_if_fail(soapconn->session->contact != NULL, FALSE);
 
 		msn_add_contact_to_list(soapconn->session->contact, NULL, state->who, MSN_LIST_BL);
-		return;
+		return TRUE;
 	}
 
 	if (state->list_id == MSN_LIST_AL) {
@@ -1554,14 +1584,13 @@
 
 	msn_callback_state_free(state);
 	msn_soap_free_read_buf(soapconn);
+	return TRUE;
 }
 
 
 static void
-msn_add_contact_to_list_written_cb(gpointer data, gint source, PurpleInputCondition cond)
+msn_add_contact_to_list_written_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;
-
 	purple_debug_info("MSN CL","Add contact to list SOAP request sent!\n");
 	soapconn->read_cb = msn_add_contact_to_list_read_cb;
 }
@@ -1603,26 +1632,26 @@
 					     body,
 					     state,
 					     msn_add_contact_to_list_read_cb,
-					     msn_add_contact_to_list_written_cb);
+					     msn_add_contact_to_list_written_cb,
+					     msn_contact_connect_init);
 
-	msn_soap_post(contact->soapconn, soap_request, msn_contact_connect_init);
+	msn_soap_post(contact->soapconn, soap_request);
 
 	g_free(body);
 }
 
 
 #if 0
-static void
-msn_gleams_read_cb(gpointer data, gint source, PurpleInputCondition cond)
+static gboolean
+msn_gleams_read_cb(MsnSoapConn * soapconn)
 {
-	purple_debug_info("MSNP14","Gleams read done\n");
+	purple_debug_info("MSN CL","Gleams read done\n");
+	return TRUE;
 }
 
 static void
-msn_gleams_written_cb(gpointer data, gint source, PurpleInputCondition cond)
+msn_gleams_written_cb(MsnSoapConn * soapconn)
 {
-	MsnSoapConn * soapconn = data;	
-
 	purple_debug_info("MSNP14","finish Group written\n");
 	soapconn->read_cb = msn_gleams_read_cb;
 //	msn_soap_read_cb(data,source,cond);
@@ -1642,8 +1671,9 @@
 					MSN_GLEAMS_TEMPLATE,
 					NULL,
 					msn_gleams_read_cb,
-					msn_gleams_written_cb);
-	msn_soap_post(contact->soapconn,soap_request,msn_contact_connect_init);
+					msn_gleams_written_cb,
+					msn_contact_connect_init);
+	msn_soap_post(contact->soapconn,soap_request);
 }
 #endif
 
@@ -1652,24 +1682,23 @@
  * Group Operations
  ***************************************************************/
 
-static void
-msn_group_read_cb(gpointer data, gint source, PurpleInputCondition cond)
+static gboolean
+msn_group_read_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;
 	MsnUserList *userlist;
 	MsnCallbackState *state = NULL;
 	
 	purple_debug_info("MSN CL", "Group request successful.\n");
 	
-	g_return_if_fail(soapconn->session != NULL);
-	g_return_if_fail(soapconn->session->userlist != NULL);
-	g_return_if_fail(soapconn->session->contact != NULL);
+	g_return_val_if_fail(soapconn->session != NULL, FALSE);
+	g_return_val_if_fail(soapconn->session->userlist != NULL, TRUE);
+	g_return_val_if_fail(soapconn->session->contact != NULL, FALSE);
 
 	state = (MsnCallbackState *) soapconn->data_cb;
 	
 	if (soapconn->body == NULL) {
 		msn_callback_state_free(state);
-		return;
+		return TRUE;
 	}
 	
 	if (state) {
@@ -1697,12 +1726,12 @@
 						       state->who,
 						       state->new_group_name);
 				msn_callback_state_free(state);
-				return;
+				return TRUE;
 			}
 			
 			if (state->action & MSN_MOVE_BUDDY) {
 				msn_add_contact_to_group(soapconn->session->contact, state, state->who, guid); 
-				return;
+				return TRUE;
 			}
 		}
 		
@@ -1720,13 +1749,12 @@
 	}
 	
 	msn_soap_free_read_buf(soapconn);
+	return TRUE;
 }
 
 static void
-msn_group_written_cb(gpointer data, gint source, PurpleInputCondition cond)
+msn_group_written_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;	
-
 	purple_debug_info("MSN CL","Sent group request.\n");
 	soapconn->read_cb = msn_group_read_cb;
 }
@@ -1767,8 +1795,9 @@
 					body,
 					state,
 					msn_group_read_cb,
-					msn_group_written_cb);
-	msn_soap_post(contact->soapconn,soap_request,msn_contact_connect_init);
+					msn_group_written_cb,
+					msn_contact_connect_init);
+	msn_soap_post(contact->soapconn,soap_request);
 	
 	g_free(body);
 }
@@ -1816,8 +1845,9 @@
 					    body,
 					    state,
 					    msn_group_read_cb,
-					    msn_group_written_cb);
-	msn_soap_post(contact->soapconn, soap_request, msn_contact_connect_init);
+					    msn_group_written_cb,
+					    msn_contact_connect_init);
+	msn_soap_post(contact->soapconn, soap_request);
 
 	g_free(body);
 }
@@ -1867,8 +1897,9 @@
 					    body,
 					    state,
 					    msn_group_read_cb,
-					    msn_group_written_cb);
-	msn_soap_post(contact->soapconn, soap_request, msn_contact_connect_init);
+					    msn_group_written_cb,
+					    msn_contact_connect_init);
+	msn_soap_post(contact->soapconn, soap_request);
 	
 	g_free(escaped_group_name);
 	g_free(body);
@@ -1878,6 +1909,6 @@
 msn_contact_connect_init(MsnSoapConn *soapconn)
 {
 	msn_soap_init(soapconn, MSN_CONTACT_SERVER, 1,
-					msn_contact_login_connect_cb,
-					msn_contact_login_error_cb);
+		      msn_contact_login_connect_cb,
+		      msn_contact_login_error_cb);
 }
--- a/libpurple/protocols/msn/contact.h	Sun Sep 16 18:47:12 2007 +0000
+++ b/libpurple/protocols/msn/contact.h	Wed Sep 19 06:08:42 2007 +0000
@@ -374,6 +374,7 @@
 struct _MsnCallbackState
 {
 	gchar * who;
+	gchar * uid;
 	gchar * old_group_name;
 	gchar * new_group_name;
 	gchar * guid;
@@ -399,6 +400,7 @@
 MsnCallbackState * msn_callback_state_new(void);
 void msn_callback_state_free(MsnCallbackState *state);
 void msn_callback_state_set_who(MsnCallbackState *state, const gchar *who);
+void msn_callback_state_set_uid(MsnCallbackState *state, const gchar *uid);
 void msn_callback_state_set_old_group_name(MsnCallbackState *state,
 					   const gchar *old_group_name);
 void msn_callback_state_set_new_group_name(MsnCallbackState *state, 
--- a/libpurple/protocols/msn/nexus.c	Sun Sep 16 18:47:12 2007 +0000
+++ b/libpurple/protocols/msn/nexus.c	Wed Sep 19 06:08:42 2007 +0000
@@ -29,7 +29,7 @@
 #undef NEXUS_LOGIN_TWN
 
 /*Local Function Prototype*/
-static void nexus_login_connect_cb(gpointer data, PurpleSslConnection *gsc,PurpleInputCondition cond);
+static gboolean nexus_login_connect_cb(MsnSoapConn *soapconn, PurpleSslConnection *gsc);
 
 /**************************************************************************
  * Main
@@ -125,9 +125,8 @@
  * Login
  **************************************************************************/
 static void
-nexus_login_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error, void *data)
+nexus_login_error_cb(MsnSoapConn *soapconn, PurpleSslConnection *gsc, PurpleSslErrorType error)
 {
-	MsnSoapConn * soapconn = data;
 	MsnSession *session;
 
 	session = soapconn->session;
@@ -141,10 +140,9 @@
 }
 
 /*process the SOAP reply, get the Authentication Info*/
-static void
-nexus_login_read_cb(gpointer data, gint source, PurpleInputCondition cond)
+static gboolean
+nexus_login_read_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;	
 	MsnNexus *nexus;
 	MsnSession *session;
 
@@ -155,9 +153,9 @@
 	char * cert_str;
 
 	nexus = soapconn->parent;
-	g_return_if_fail(nexus != NULL);
+	g_return_val_if_fail(nexus != NULL, TRUE);
 	session = nexus->session;
-	g_return_if_fail(session != NULL);
+	g_return_val_if_fail(session != NULL, FALSE);
 
 	/*reply OK, we should process the SOAP body*/
 	purple_debug_info("MSN Nexus","TWN Server Windows Live ID Reply OK!\n");
@@ -210,25 +208,21 @@
 	msn_nexus_destroy(nexus);
 	session->nexus = NULL;
 
-	return;
+	return FALSE;
 }
 
 static void
-nexus_login_written_cb(gpointer data, gint source, PurpleInputCondition cond)
+nexus_login_written_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;	
-
 	soapconn->read_cb = nexus_login_read_cb;
 //	msn_soap_read_cb(data,source,cond);
 }
 
 
 /*when connect, do the SOAP Style windows Live ID authentication */
-void
-nexus_login_connect_cb(gpointer data, PurpleSslConnection *gsc,
-				 PurpleInputCondition cond)
+gboolean
+nexus_login_connect_cb(MsnSoapConn *soapconn, PurpleSslConnection *gsc)
 {
-	MsnSoapConn *soapconn;
 	MsnNexus * nexus;
 	MsnSession *session;
 	char *ru,*lc,*id,*tw,*ct,*kpp,*kv,*ver,*rn,*tpf;
@@ -240,17 +234,18 @@
 #else
 	char *rst1_str,*rst2_str,*rst3_str;
 #endif
-
+	
 	purple_debug_info("MSN Nexus","Starting Windows Live ID authentication\n");
 
-	soapconn = data;
-	g_return_if_fail(soapconn != NULL);
+	g_return_val_if_fail(soapconn != NULL, FALSE);
 
 	nexus = soapconn->parent;
-	g_return_if_fail(nexus != NULL);
+	g_return_val_if_fail(nexus != NULL, TRUE);
 
 	session = soapconn->session;
-	g_return_if_fail(session != NULL);
+	g_return_val_if_fail(session != NULL, FALSE);
+
+	msn_soap_set_process_step(soapconn, MSN_SOAP_PROCESSING);
 
 	msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE);
 
@@ -283,7 +278,7 @@
 		purple_ssl_close(gsc);
 		msn_nexus_destroy(nexus);
 		session->nexus = NULL;
-		return;
+		return FALSE;
 	}
 
 	/*
@@ -328,10 +323,10 @@
 					"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"
+					"Content-Length: %" G_GSIZE_FORMAT "\r\n"
 					"Connection: Keep-Alive\r\n"
 					"Cache-Control: no-cache\r\n\r\n",
-					soapconn->login_path,soapconn->login_host,(int)strlen(tail));
+					soapconn->login_path, soapconn->login_host, strlen(tail));
 
 	request_str = g_strdup_printf("%s%s", head,tail);
 
@@ -344,9 +339,9 @@
 	g_free(password);
 
 	/*prepare to send the SOAP request*/
-	msn_soap_write(soapconn,request_str,nexus_login_written_cb);
+	msn_soap_write(soapconn, request_str, nexus_login_written_cb);
 
-	return;
+	return TRUE;
 }
 
 #if 0 /* khc */
@@ -468,7 +463,6 @@
 msn_nexus_connect(MsnNexus *nexus)
 {
 	/*  Authenticate via Windows Live ID. */
-	purple_debug_info("MSN Nexus","msn_nexus_connect()\n");
-	msn_soap_init(nexus->soapconn,MSN_TWN_SERVER,1,nexus_login_connect_cb,nexus_login_error_cb);
+	msn_soap_init(nexus->soapconn, MSN_TWN_SERVER, 1, nexus_login_connect_cb, nexus_login_error_cb);
 	msn_soap_connect(nexus->soapconn);
 }
--- a/libpurple/protocols/msn/oim.c	Sun Sep 16 18:47:12 2007 +0000
+++ b/libpurple/protocols/msn/oim.c	Wed Sep 19 06:08:42 2007 +0000
@@ -31,10 +31,10 @@
 /*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);
+					   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);
@@ -120,9 +120,9 @@
 {
 	char *oim_body,*oim_base64;
 	
-	purple_debug_info("MSNP14","encode OIM Message...\n");	
+	purple_debug_info("MSN OIM","encode OIM Message...\n");	
 	oim_base64 = purple_base64_encode((const guchar *)body, strlen(body));
-	purple_debug_info("MSNP14","encoded base64 body:{%s}\n",oim_base64);	
+	purple_debug_info("MSN OIM","encoded base64 body:{%s}\n",oim_base64);	
 	oim_body = g_strdup_printf(MSN_OIM_MSG_TEMPLATE,
 				oim->run_id,oim->send_seq,oim_base64);
 
@@ -131,9 +131,8 @@
 
 /*oim SOAP server login error*/
 static void
-msn_oim_send_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error, void *data)
+msn_oim_send_error_cb(MsnSoapConn *soapconn, PurpleSslConnection *gsc, PurpleSslErrorType error)
 {
-	MsnSoapConn *soapconn = data;
 	MsnSession *session;
 
 	session = soapconn->session;
@@ -143,19 +142,19 @@
 }
 
 /*msn oim SOAP server connect process*/
-static void
-msn_oim_send_connect_cb(gpointer data, PurpleSslConnection *gsc,
-				 PurpleInputCondition cond)
+static gboolean
+msn_oim_send_connect_cb(MsnSoapConn *soapconn, PurpleSslConnection *gsc)
 {
-	MsnSoapConn *soapconn = data;
 	MsnSession * session;
 	MsnOim *oim;
 
 	oim = soapconn->parent;
-	g_return_if_fail(oim != NULL);
+	g_return_val_if_fail(oim != NULL, TRUE);
 
 	session = oim->session;
-	g_return_if_fail(session != NULL);
+	g_return_val_if_fail(session != NULL, FALSE);
+
+	return TRUE;
 }
 
 /*
@@ -178,22 +177,22 @@
 		/*Send OK! return*/
 		MsnOimSendReq *request;
 		
-		purple_debug_info("MSNP14","send OIM OK!");
+		purple_debug_info("MSN OIM","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);
+		msn_soap_post(oim->sendconn, NULL);
 		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");
+		purple_debug_info("MSN OIM","faultcode Node is NULL\n");
 		goto oim_send_process_fail;
 	}
 	faultCodeStr = xmlnode_get_data(faultCodeNode);
-	purple_debug_info("MSNP14","fault code:{%s}\n",faultCodeStr);
+	purple_debug_info("MSN OIM","fault code:{%s}\n",faultCodeStr);
 #if 0
 	if(!strcmp(faultCodeStr,"q0:AuthenticationFailed")){
 		/*other Fault Reason?*/
@@ -203,7 +202,7 @@
 
 	faultstringNode = xmlnode_get_child(faultNode,"faultstring");
 	faultstring = xmlnode_get_data(faultstringNode);
-	purple_debug_info("MSNP14","fault string :{%s}\n",faultstring);
+	purple_debug_info("MSN OIM","fault string :{%s}\n",faultstring);
 
 	/* lock key fault reason,
 	 * compute the challenge and resend it
@@ -219,10 +218,10 @@
 
 	g_free(oim->challenge);
 	oim->challenge = xmlnode_get_data(challengeNode);
-	purple_debug_info("MSNP14","lockkey:{%s}\n",oim->challenge);
+	purple_debug_info("MSN OIM","lockkey:{%s}\n",oim->challenge);
 
 	/*repost the send*/
-	purple_debug_info("MSNP14","prepare to repost the send...\n");
+	purple_debug_info("MSN OIM","prepare to repost the send...\n");
 	msn_oim_send_msg(oim);
 
 oim_send_process_fail:
@@ -232,29 +231,28 @@
 	return ;
 }
 
-static void
-msn_oim_send_read_cb(gpointer data, gint source, PurpleInputCondition cond)
+static gboolean
+msn_oim_send_read_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;
 	MsnSession *session = soapconn->session;
 	MsnOim * oim;
 
 	if (soapconn->body == NULL)
-		return;
+		return TRUE;
 
-	g_return_if_fail(session != NULL);
+	g_return_val_if_fail(session != NULL, FALSE);
 	oim = soapconn->session->oim;
-	g_return_if_fail(oim != NULL);
+	g_return_val_if_fail(oim != NULL, TRUE);
 
-	purple_debug_info("MSNP14","read buffer:{%s}\n",soapconn->body);
+	purple_debug_info("MSN OIM","read buffer:{%s}\n", soapconn->body);
 	msn_oim_send_process(oim,soapconn->body,soapconn->body_len);
+
+	return TRUE;
 }
 
 static void
-msn_oim_send_written_cb(gpointer data, gint source, PurpleInputCondition cond)
+msn_oim_send_written_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;	
-
 	soapconn->read_cb = msn_oim_send_read_cb;
 //	msn_soap_read_cb(data,source,cond);
 }
@@ -286,7 +284,7 @@
 	oim_request = g_queue_pop_head(oim->send_queue);
 	g_return_if_fail(oim_request != NULL);
 
-	purple_debug_info("MSNP14","send single OIM Message\n");
+	purple_debug_info("MSN OIM","send single OIM Message\n");
 	mspauth = g_strdup_printf("t=%s&amp;p=%s",
 		oim->session->passport_info.t,
 		oim->session->passport_info.p
@@ -299,10 +297,10 @@
 	if(oim->challenge != NULL){
 		msn_handle_chl(oim->challenge, buf);
 	}else{
-		purple_debug_info("MSNP14","no lock key challenge,wait for SOAP Fault and Resend\n");
+		purple_debug_info("MSN OIM","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);	
+	purple_debug_info("MSN OIM","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,
@@ -321,7 +319,8 @@
 					soap_body,
 					NULL,
 					msn_oim_send_read_cb,
-					msn_oim_send_written_cb);
+					msn_oim_send_written_cb,
+					msn_oim_send_connect_init);
 	g_free(mspauth);
 	g_free(msg_body);
 	g_free(soap_body);
@@ -330,31 +329,28 @@
 	if(oim->challenge != NULL){
 		oim->send_seq++;
 	}
-	msn_soap_post(oim->sendconn,soap_request,msn_oim_send_connect_init);
+	msn_soap_post(oim->sendconn,soap_request);
 }
 
 /****************************************
  * OIM delete SOAP request
  * **************************************/
-static void
-msn_oim_delete_read_cb(gpointer data, gint source, PurpleInputCondition cond)
+static gboolean
+msn_oim_delete_read_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;
-
 	if (soapconn->body == NULL)
-		return;
-	purple_debug_info("MSNP14","OIM delete read buffer:{%s}\n",soapconn->body);
+		return TRUE;
+	purple_debug_info("MSN OIM","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);
+//	msn_soap_post(soapconn,NULL);	/* we already do this in soap.c */
+	return TRUE;
 }
 
 static void
-msn_oim_delete_written_cb(gpointer data, gint source, PurpleInputCondition cond)
+msn_oim_delete_written_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;
-
 	soapconn->read_cb = msn_oim_delete_read_cb;
 }
 
@@ -368,7 +364,7 @@
 	g_return_if_fail(oim != NULL);
 	g_return_if_fail(msgid != NULL);
 
-	purple_debug_info("MSNP14","Delete single OIM Message {%s}\n",msgid);
+	purple_debug_info("MSN OIM","Delete single OIM Message {%s}\n",msgid);
 	t = oim->session->passport_info.t;
 	p = oim->session->passport_info.p;
 
@@ -383,8 +379,9 @@
 					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);
+					msn_oim_delete_written_cb,
+					msn_oim_retrieve_connect_init);
+	msn_soap_post(oim->retrieveconn,soap_request);
 }
 
 /****************************************
@@ -392,34 +389,33 @@
  * **************************************/
 /*oim SOAP server login error*/
 static void
-msn_oim_get_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error, void *data)
+msn_oim_get_error_cb(MsnSoapConn *soapconn, PurpleSslConnection *gsc, PurpleSslErrorType error)
 {
-	MsnSoapConn *soapconn = data;
 	MsnSession *session;
 
 	session = soapconn->session;
 	g_return_if_fail(session != NULL);
-	msn_soap_clean_unhandled_request(soapconn);
+	msn_soap_clean_unhandled_requests(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)
+static gboolean
+msn_oim_get_connect_cb(MsnSoapConn *soapconn, PurpleSslConnection *gsc)
 {
-	MsnSoapConn *soapconn = data;
 	MsnSession * session;
 	MsnOim *oim;
 
 	oim = soapconn->parent;
-	g_return_if_fail(oim != NULL);
+	g_return_val_if_fail(oim != NULL, TRUE);
 
 	session = oim->session;
-	g_return_if_fail(session != NULL);
+	g_return_val_if_fail(session != NULL, FALSE);
 
-	purple_debug_info("MSNP14","oim get SOAP Server connected!\n");
+	purple_debug_info("MSN OIM","Connected and ready to get OIM!\n");
+
+	return TRUE;
 }
 
 /* like purple_str_to_time, but different. The format of the timestamp
@@ -485,7 +481,7 @@
 		}
 	}
 
-	purple_debug_info("MSNP14:OIM", "Can't parse timestamp %s\n", timestamp);
+	purple_debug_info("MSN OIM:OIM", "Can't parse timestamp %s\n", timestamp);
 	return time(NULL);
 }
 
@@ -507,7 +503,7 @@
 
 	msn_message_parse_payload(message, msg_str, strlen(msg_str),
 							  MSG_OIM_LINE_DEM, MSG_OIM_BODY_DEM);
-	purple_debug_info("MSNP14","oim body:{%s}\n",message->body);
+	purple_debug_info("MSN OIM","oim body:{%s}\n",message->body);
 	decode_msg = (char *)purple_base64_decode(message->body,&body_len);
 	date =	(char *)g_hash_table_lookup(message->attr_table, "Date");
 	from =	(char *)g_hash_table_lookup(message->attr_table, "From");
@@ -517,12 +513,12 @@
 	if(has_nick){
 		tokens = g_strsplit(from , " " , 2);
 		passport_str = g_strdup(tokens[1]);
-		purple_debug_info("MSNP14","oim Date:{%s},nickname:{%s},tokens[1]:{%s} passport{%s}\n",
+		purple_debug_info("MSN OIM","oim Date:{%s},nickname:{%s},tokens[1]:{%s} passport{%s}\n",
 							date,tokens[0],tokens[1],passport_str);
 		g_strfreev(tokens);
 	}else{
 		passport_str = g_strdup(from);
-		purple_debug_info("MSNP14","oim Date:{%s},passport{%s}\n",
+		purple_debug_info("MSN OIM","oim Date:{%s},passport{%s}\n",
 					date,passport_str);
 	}
 	start = strstr(passport_str,"<");
@@ -530,7 +526,7 @@
 	end = strstr(passport_str,">");
 	passport = g_strndup(start,end - start);
 	g_free(passport_str);
-	purple_debug_info("MSNP14","oim Date:{%s},passport{%s}\n",date,passport);
+	purple_debug_info("MSN OIM","oim Date:{%s},passport{%s}\n",date,passport);
 
 	stamp = msn_oim_parse_timestamp(date);
 
@@ -570,30 +566,28 @@
 	xmlnode_free(oim_node);
 }
 
-static void
-msn_oim_get_read_cb(gpointer data, gint source, PurpleInputCondition cond)
+static gboolean
+msn_oim_get_read_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;
 	MsnOim * oim = soapconn->session->oim;
 
 	if (soapconn->body == NULL)
-		return;
+		return TRUE;
 
-	purple_debug_info("MSNP14","OIM get read buffer:{%s}\n",soapconn->body);
+	purple_debug_info("MSN OIM","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);
 
 	/*get next single Offline Message*/
-	msn_soap_post(soapconn,NULL,msn_oim_retrieve_connect_init);
+//	msn_soap_post(soapconn,NULL); /* we already do this in soap.c */
+	return TRUE;
 }
 
 static void
-msn_oim_get_written_cb(gpointer data, gint source, PurpleInputCondition cond)
+msn_oim_get_written_cb(MsnSoapConn *soapconn)
 {
-	MsnSoapConn * soapconn = data;
-
 	soapconn->read_cb = msn_oim_get_read_cb;
 //	msn_soap_read_cb(data,source,cond);
 }
@@ -608,7 +602,7 @@
 	char *passport,*msgid,*nickname, *unread, *rTime = NULL;
 	MsnSession *session = oim->session;
 
-	purple_debug_info("MSNP14:OIM", "%s", xmlmsg);
+	purple_debug_info("MSN OIM:OIM", "%s", xmlmsg);
 
 	node = xmlnode_from_str(xmlmsg, strlen(xmlmsg));
 	if (strcmp(node->name, "MD") != 0) {
@@ -654,7 +648,7 @@
 			rTime = xmlnode_get_data(rtNode);
 			rtNode = NULL;
 		}
-/*		purple_debug_info("MSNP14","E:{%s},I:{%s},rTime:{%s}\n",passport,msgid,rTime); */
+/*		purple_debug_info("MSN OIM","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);
@@ -675,7 +669,7 @@
 	MsnSoapReq *soap_request;
 	const char *soap_body,*t,*p;
 
-	purple_debug_info("MSNP14","Get single OIM Message\n");
+	purple_debug_info("MSN OIM","Get single OIM Message\n");
 	t = oim->session->passport_info.t;
 	p = oim->session->passport_info.p;
 
@@ -690,28 +684,29 @@
 					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);
+					msn_oim_get_written_cb,
+					msn_oim_retrieve_connect_init);
+	msn_soap_post(oim->retrieveconn,soap_request);
 }
 
 /*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);
+	purple_debug_info("MSN OIM","Initializing OIM retrieve connection\n");
+	msn_soap_init(soapconn, MSN_OIM_RETRIEVE_HOST, 1,
+		      msn_oim_get_connect_cb,
+		      msn_oim_get_error_cb);
 }
 
 /*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);
+	purple_debug_info("MSN OIM","Initializing OIM send connection\n");
+	msn_soap_init(sendconn, MSN_OIM_SEND_HOST, 1,
+		      msn_oim_send_connect_cb,
+		      msn_oim_send_error_cb);
 }
 
-/*endof oim.c*/
+/* EOF oim.c*/
--- a/libpurple/protocols/msn/soap.c	Sun Sep 16 18:47:12 2007 +0000
+++ b/libpurple/protocols/msn/soap.c	Wed Sep 19 06:08:42 2007 +0000
@@ -34,6 +34,18 @@
 void
 msn_soap_set_process_step(MsnSoapConn *soapconn, MsnSoapStep step)
 {
+#ifdef MSN_SOAP_DEBUG
+	const char *MsnSoapStepText[] =
+	{
+		"Unconnected",
+		"Connecting",
+		"Connected",
+		"Processing",
+		"Connected Idle"
+	};
+
+	purple_debug_info("MSN SOAP", "Setting SOAP process step to %s\n", MsnSoapStepText[step]);
+#endif
 	soapconn->step = step;
 }
 
@@ -53,8 +65,9 @@
 	soapconn->input_handler = 0;
 	soapconn->output_handler = 0;
 
-	msn_soap_set_process_step(soapconn,MSN_SOAP_UNCONNECTED);
+	msn_soap_set_process_step(soapconn, MSN_SOAP_UNCONNECTED);
 	soapconn->soap_queue = g_queue_new();
+
 	return soapconn;
 }
 
@@ -65,6 +78,7 @@
 {
 	MsnSoapConn * soapconn;
 	MsnSession *session;
+	gboolean soapconn_is_valid = FALSE;
 
 	purple_debug_misc("MSN SOAP","SOAP server connection established!\n");
 
@@ -76,12 +90,17 @@
 
 	soapconn->gsc = gsc;
 
+	msn_soap_set_process_step(soapconn, MSN_SOAP_CONNECTED);
+
 	/*connection callback*/
-	if(soapconn->connect_cb != NULL){
-		soapconn->connect_cb(data,gsc,cond);
+	if (soapconn->connect_cb != NULL) {
+		soapconn_is_valid = soapconn->connect_cb(soapconn, gsc);
 	}
 
-	msn_soap_set_process_step(soapconn,MSN_SOAP_CONNECTED);
+	if (!soapconn_is_valid) {
+		return;
+	}
+
 	/*we do the SOAP request here*/
 	msn_soap_post_head_request(soapconn);
 }
@@ -93,20 +112,24 @@
 	MsnSoapConn * soapconn = data;
 
 	g_return_if_fail(data != NULL);
+
 	purple_debug_warning("MSN SOAP","Soap connection error!\n");
+
 	msn_soap_set_process_step(soapconn, MSN_SOAP_UNCONNECTED);
 
 	/*error callback*/
-	if(soapconn->error_cb != NULL){
-		soapconn->error_cb(gsc,error,data);
+	if (soapconn->error_cb != NULL) {
+		soapconn->error_cb(soapconn, gsc, error);
+	} else {
+		msn_soap_post(soapconn, NULL);
 	}
 }
 
 /*init the soap connection*/
 void
 msn_soap_init(MsnSoapConn *soapconn,char * host,int ssl,
-				PurpleSslInputFunction	connect_cb,
-				PurpleSslErrorFunction	error_cb)
+				MsnSoapSslConnectCbFunction connect_cb,
+				MsnSoapSslErrorCbFunction error_cb)
 {
 	purple_debug_misc("MSN SOAP","Initializing SOAP connection\n");
 	soapconn->login_host = g_strdup(host);
@@ -119,32 +142,50 @@
 void
 msn_soap_connect(MsnSoapConn *soapconn)
 {
-	if(soapconn->ssl_conn){
+	if (soapconn->ssl_conn) {
 		purple_ssl_connect(soapconn->session->account, soapconn->login_host,
 				PURPLE_SSL_DEFAULT_PORT, msn_soap_connect_cb, msn_soap_error_cb,
 				soapconn);
-	}else{
+	} else {
 	}
-	msn_soap_set_process_step(soapconn,MSN_SOAP_CONNECTING);
+
+	msn_soap_set_process_step(soapconn, MSN_SOAP_CONNECTING);
 }
 
+
+static void
+msn_soap_close_handler(guint *handler)
+{
+	if (*handler > 0) {
+		purple_input_remove(*handler);
+		*handler = 0;
+	} 
+#ifdef MSN_SOAP_DEBUG
+	else {
+		purple_debug_misc("MSN SOAP", "Handler inactive, not removing\n");
+	}
+#endif
+
+}
+
+
 /*close the soap connection*/
 void
 msn_soap_close(MsnSoapConn *soapconn)
 {
-	if(soapconn->ssl_conn){
-		if(soapconn->gsc != NULL){
+	if (soapconn->ssl_conn) {
+		if (soapconn->gsc != NULL) {
 			purple_ssl_close(soapconn->gsc);
 			soapconn->gsc = NULL;
 		}
-	}else{
+	} else {
 	}
-	msn_soap_set_process_step(soapconn,MSN_SOAP_UNCONNECTED);
+	msn_soap_set_process_step(soapconn, MSN_SOAP_UNCONNECTED);
 }
 
 /*clean the unhandled SOAP request*/
 void
-msn_soap_clean_unhandled_request(MsnSoapConn *soapconn)
+msn_soap_clean_unhandled_requests(MsnSoapConn *soapconn)
 {
 	MsnSoapReq *request;
 
@@ -154,7 +195,7 @@
 
 	while ((request = g_queue_pop_head(soapconn->soap_queue)) != NULL){
 		if (soapconn->read_cb) {
-			soapconn->read_cb(soapconn, -1, 0);
+			soapconn->read_cb(soapconn);
 		}
 		msn_soap_request_free(request);
 	}
@@ -187,7 +228,7 @@
 	msn_soap_close(soapconn);
 
 	/*process the unhandled soap request*/
-	msn_soap_clean_unhandled_request(soapconn);
+	msn_soap_clean_unhandled_requests(soapconn);
 
 	g_queue_free(soapconn->soap_queue);
 	g_free(soapconn);
@@ -199,10 +240,10 @@
 int
 msn_soap_connected(MsnSoapConn *soapconn)
 {
-	if(soapconn->ssl_conn){
-		return (soapconn->gsc == NULL? 0 : 1);
+	if (soapconn->ssl_conn) {
+		return (soapconn->gsc == NULL ? 0 : 1);
 	}
-	return(soapconn->fd>0? 1 : 0);
+	return (soapconn->fd > 0 ? 1 : 0);
 }
 
 /*read and append the content to the buffer*/
@@ -237,7 +278,7 @@
 						"read len: %d, error = %s\n",
 						len, strerror(errno));
 				  purple_input_remove(soapconn->input_handler);
-				  soapconn->input_handler = 0;
+				  //soapconn->input_handler = 0;
 				  g_free(soapconn->read_buf);
 				  soapconn->read_buf = NULL;
 				  soapconn->read_len = 0;
@@ -309,7 +350,12 @@
 		location = strstr(soapconn->read_buf, "Location: ");
 		if (location == NULL)
 		{
-			msn_soap_free_read_buf(soapconn);
+			c = (char *) g_strstr_len(soapconn->read_buf, soapconn->read_len,"\r\n\r\n");
+			if (c != NULL) {
+				/* we have read the whole HTTP headers and found no Location: */
+				msn_soap_free_read_buf(soapconn);
+				msn_soap_post(soapconn, NULL);
+			}
 
 			return;
 		}
@@ -317,6 +363,8 @@
 
 		if ((c = strchr(location, '\r')) != NULL)
 			*c = '\0';
+		else
+			return;
 
 		/* Skip the http:// */
 		if ((c = strchr(location, '/')) != NULL)
@@ -332,10 +380,18 @@
 
 		g_free(soapconn->login_host);
 		soapconn->login_host = g_strdup(location);
+		
+		msn_soap_close_handler( &(soapconn->input_handler) );
+		msn_soap_close(soapconn);
 
-		purple_ssl_connect(session->account, soapconn->login_host,
+		if (purple_ssl_connect(session->account, soapconn->login_host,
 			PURPLE_SSL_DEFAULT_PORT, msn_soap_connect_cb,
-			msn_soap_error_cb, soapconn);
+			msn_soap_error_cb, soapconn) == NULL) {
+		
+			purple_debug_error("MSN SOAP", "Unable to connect to %s !\n", soapconn->login_host);
+			// dispatch next request
+			msn_soap_post(soapconn, NULL);
+		}
 	}
 	/* Another case of redirection, active on May, 2007
 	   See http://msnpiki.msnfanatic.com/index.php/MSNP13:SOAPTweener#Redirect
@@ -345,20 +401,22 @@
 	{
 		char *location, *c;
 
-		location = strstr(soapconn->read_buf, "<psf:redirectUrl>");
+		if ( (location = strstr(soapconn->read_buf, "<psf:redirectUrl>") ) == NULL)
+			return;
+
 		/* Omit the tag preceding the URL */
 		location += strlen("<psf:redirectUrl>");
-		location = strstr(location, ":/");
-		if (location == NULL)
-		{
-			msn_soap_free_read_buf(soapconn);
+		if (location > soapconn->read_buf + soapconn->read_len)
 			return;
-		}
+		if ( (location = strstr(location, "://")) == NULL)
+			return;
 
 		location += strlen("://"); /* Skip http:// or https:// */
 
 		if ( (c = strstr(location, "</psf:redirectUrl>")) != NULL )
 			*c = '\0';
+		else
+			return;
 
 		if ( (c = strstr(location, "/")) != NULL )
 		{
@@ -369,10 +427,18 @@
 
 		g_free(soapconn->login_host);
 		soapconn->login_host = g_strdup(location);
+		
+		msn_soap_close_handler( &(soapconn->input_handler) );
+		msn_soap_close(soapconn);
 
-		purple_ssl_connect(session->account, soapconn->login_host,
-			PURPLE_SSL_DEFAULT_PORT, msn_soap_connect_cb,
-			msn_soap_error_cb, soapconn);
+		if (purple_ssl_connect(session->account, soapconn->login_host,
+				PURPLE_SSL_DEFAULT_PORT, msn_soap_connect_cb,
+				msn_soap_error_cb, soapconn) == NULL) {
+
+			purple_debug_error("MSN SOAP", "Unable to connect to %s !\n", soapconn->login_host);
+			// dispatch next request
+			msn_soap_post(soapconn, NULL);
+		}
 	}
 	else if (strstr(soapconn->read_buf, "HTTP/1.1 401 Unauthorized") != NULL)
 	{
@@ -405,17 +471,23 @@
 	else if (strstr(soapconn->read_buf,
 				"<faultcode>wsse:FailedAuthentication</faultcode>") != NULL)
 	{
-		char *faultstring;
+		gchar *faultstring;
 
 		faultstring = strstr(soapconn->read_buf, "<faultstring>");
 
 		if (faultstring != NULL)
 		{
+			gchar *c;
 			faultstring += strlen("<faultstring>");
-			*strstr(soapconn->read_buf, "</faultstring>") = '\0';
+			if (faultstring < soapconn->read_buf + soapconn->read_len) {
+				c = strstr(soapconn->read_buf, "</faultstring>");
+				if (c != NULL) {
+					*c = '\0';
+					msn_session_set_error(session, MSN_ERROR_AUTH, faultstring);
+				}
+			}
 		}
 		
-		msn_session_set_error(session, MSN_ERROR_AUTH, faultstring);
 	}
 	else if (strstr(soapconn->read_buf, "HTTP/1.1 503 Service Unavailable"))
 	{
@@ -424,69 +496,86 @@
 	else if ((strstr(soapconn->read_buf, "HTTP/1.1 200 OK"))
 		||(strstr(soapconn->read_buf, "HTTP/1.1 500")))
 	{
-			/*OK! process the SOAP body*/
-			body_start = (char *)g_strstr_len(soapconn->read_buf, soapconn->read_len,"\r\n\r\n");
-			if (!body_start) {
-				return;
-			}
-			body_start += 4;
+		gboolean soapconn_is_valid = FALSE;
 
-			//	purple_debug_misc("msn", "Soap Read: {%s}\n", soapconn->read_buf);
+		/*OK! process the SOAP body*/
+		body_start = (char *)g_strstr_len(soapconn->read_buf, soapconn->read_len,"\r\n\r\n");
+		if (!body_start) {
+			return;
+		}
+		body_start += 4;
 
-			/* we read the content-length*/
-			length_start = strstr(soapconn->read_buf, "Content-Length: ");
+		if (body_start > soapconn->read_buf + soapconn->read_len)
+			return;
+
+		/* we read the content-length*/
+		if ( (length_start = g_strstr_len(soapconn->read_buf, soapconn->read_len, "Content-Length: ")) != NULL)
 			length_start += strlen("Content-Length: ");
-			length_end = strstr(length_start, "\r\n");
-			body_len = g_strndup(length_start, length_end - length_start);
+
+		if (length_start > soapconn->read_buf + soapconn->read_len)
+			return;
+
+		if ( (length_end = strstr(length_start, "\r\n")) == NULL )
+			return;
+
+		body_len = g_strndup(length_start, length_end - length_start);
 
-			/*setup the conn body */
-			soapconn->body		= body_start;
-			soapconn->body_len	= atoi(body_len);
-			g_free(body_len);
+		/*setup the conn body */
+		soapconn->body		= body_start;
+		soapconn->body_len	= atoi(body_len);
+		g_free(body_len);
 #ifdef MSN_SOAP_DEBUG
-			purple_debug_misc("MSN SOAP","SOAP bytes read so far: %d, Content-Length: %d\n", soapconn->read_len, soapconn->body_len);
+		purple_debug_misc("MSN SOAP","SOAP bytes read so far: %d, Content-Length: %d\n", soapconn->read_len, soapconn->body_len);
 #endif
-			soapconn->need_to_read = (body_start - soapconn->read_buf + soapconn->body_len) - soapconn->read_len;
-			if ( soapconn->need_to_read > 0 ) {
-				return;
-			}
+		soapconn->need_to_read = (body_start - soapconn->read_buf + soapconn->body_len) - soapconn->read_len;
+		if ( soapconn->need_to_read > 0 ) {
+			return;
+		}
 
 #if defined(MSN_SOAP_DEBUG) && !defined(_WIN32)
 
-			node = xmlnode_from_str(soapconn->body, soapconn->body_len);
+		node = xmlnode_from_str(soapconn->body, soapconn->body_len);
 	
-			if (node != NULL) {
-				formattedxml = xmlnode_to_formatted_str(node, NULL);
-				http_headers = g_strndup(soapconn->read_buf, soapconn->body - soapconn->read_buf);
+		if (node != NULL) {
+			formattedxml = xmlnode_to_formatted_str(node, NULL);
+			http_headers = g_strndup(soapconn->read_buf, soapconn->body - soapconn->read_buf);
 				
-				purple_debug_info("MSN SOAP","Data with XML payload received from the SOAP server:\n%s%s\n", http_headers, formattedxml);
-				g_free(http_headers);
-				g_free(formattedxml);
-				xmlnode_free(node);
-			}
-			else
-				purple_debug_info("MSN SOAP","Data received from the SOAP server:\n%s\n", soapconn->read_buf);
+			purple_debug_info("MSN SOAP","Data with XML payload received from the SOAP server:\n%s%s\n", http_headers, formattedxml);
+			g_free(http_headers);
+			g_free(formattedxml);
+			xmlnode_free(node);
+		}
+		else
+			purple_debug_info("MSN SOAP","Data received from the SOAP server:\n%s\n", soapconn->read_buf);
 #endif
 
-			/*remove the read handler*/
-			purple_input_remove(soapconn->input_handler);
-			soapconn->input_handler = 0;
-			/*
-			 * close the soap connection,if more soap request came,
-			 * Just reconnect to do it,
-			 *
-			 * To solve the problem described below:
-			 * When I post the soap request in one socket one after the other,
-			 * The first read is ok, But the second soap read always got 0 bytes,
-			 * Weird!
-			 * */
-			msn_soap_close(soapconn);
+		/*remove the read handler*/
+		msn_soap_close_handler( &(soapconn->input_handler) );
+//		purple_input_remove(soapconn->input_handler);
+//		soapconn->input_handler = 0;
+		/*
+		 * close the soap connection,if more soap request came,
+		 * Just reconnect to do it,
+		 *
+		 * To solve the problem described below:
+		 * When I post the soap request in one socket one after the other,
+		 * The first read is ok, But the second soap read always got 0 bytes,
+		 * Weird!
+		 * */
+		msn_soap_close(soapconn);
 
-			/*call the read callback*/
-			if ( soapconn->read_cb != NULL ) {
-				soapconn->read_cb(soapconn, source, 0);
-			}
-	}
+		/*call the read callback*/
+		if ( soapconn->read_cb != NULL ) {
+			soapconn_is_valid = soapconn->read_cb(soapconn);
+		}
+		
+		if (!soapconn_is_valid) {
+			return;
+		}
+
+		/* dispatch next request in queue */
+		msn_soap_post(soapconn, NULL);
+	}	
 	return;
 }
 
@@ -524,9 +613,11 @@
 
 	g_return_if_fail(soapconn != NULL);
 	if ( soapconn->write_buf == NULL ) {
-		purple_debug_error("MSN SOAP","SOAP buffer is NULL\n");
-		purple_input_remove(soapconn->output_handler);
-		soapconn->output_handler = -1;
+		purple_debug_error("MSN SOAP","SOAP write buffer is NULL\n");
+	//	msn_soap_check_conn_errors(soapconn);
+	//	purple_input_remove(soapconn->output_handler);
+	//	soapconn->output_handler = 0;
+		msn_soap_close_handler( &(soapconn->output_handler) );
 		return;
 	}
 	total_len = strlen(soapconn->write_buf);
@@ -542,10 +633,17 @@
 		return;
 	else if (len <= 0){
 		/*SSL write error!*/
-		purple_input_remove(soapconn->output_handler);
-		soapconn->output_handler = -1;
+//		msn_soap_check_conn_errors(soapconn);
+
+		msn_soap_close_handler( &(soapconn->output_handler) );
+//		purple_input_remove(soapconn->output_handler);
+//		soapconn->output_handler = 0;
+
+		msn_soap_close(soapconn);
+
 		/* TODO: notify of the error */
-		purple_debug_error("MSN SOAP","Error writing to SSL connection!\n");
+		purple_debug_error("MSN SOAP", "Error writing to SSL connection!\n");
+		msn_soap_post(soapconn, NULL);
 		return;
 	}
 	soapconn->written_len += len;
@@ -553,8 +651,9 @@
 	if (soapconn->written_len < total_len)
 		return;
 
-	purple_input_remove(soapconn->output_handler);
-	soapconn->output_handler = -1;
+	msn_soap_close_handler( &(soapconn->output_handler) );
+//	purple_input_remove(soapconn->output_handler);
+//	soapconn->output_handler = 0;
 
 	/*clear the write buff*/
 	msn_soap_free_write_buf(soapconn);
@@ -563,20 +662,25 @@
 	 * callback for write done
 	 */
 	if(soapconn->written_cb != NULL){
-		soapconn->written_cb(soapconn, source, 0);
+		soapconn->written_cb(soapconn);
 	}
 	/*maybe we need to read the input?*/
-	if (soapconn->input_handler == 0) {
+	if ( soapconn->input_handler == 0 ) {
 		soapconn->input_handler = purple_input_add(soapconn->gsc->fd,
 			PURPLE_INPUT_READ, msn_soap_read_cb, soapconn);
 	}
-//	msn_soap_read_cb(soapconn,source,0);
 }
 
 /*write the buffer to SOAP connection*/
 void
-msn_soap_write(MsnSoapConn * soapconn, char *write_buf, PurpleInputFunction written_cb)
+msn_soap_write(MsnSoapConn * soapconn, char *write_buf, MsnSoapWrittenCbFunction written_cb)
 {
+	if (soapconn == NULL) {
+		return;
+	}
+
+	msn_soap_set_process_step(soapconn, MSN_SOAP_PROCESSING);
+
 	soapconn->write_buf = write_buf;
 	soapconn->written_len = 0;
 	soapconn->written_cb = written_cb;
@@ -586,7 +690,7 @@
 	/*clear the read buffer first*/
 	/*start the write*/
 	soapconn->output_handler = purple_input_add(soapconn->gsc->fd, PURPLE_INPUT_WRITE,
-													msn_soap_write_cb, soapconn);
+						    msn_soap_write_cb, soapconn);
 	msn_soap_write_cb(soapconn, soapconn->gsc->fd, PURPLE_INPUT_WRITE);
 }
 
@@ -594,7 +698,9 @@
 MsnSoapReq *
 msn_soap_request_new(const char *host,const char *post_url,const char *soap_action,
 				const char *body, const gpointer data_cb,
-				PurpleInputFunction read_cb,PurpleInputFunction written_cb)
+				MsnSoapReadCbFunction read_cb,
+				MsnSoapWrittenCbFunction written_cb,
+				MsnSoapConnectInitFunction connect_init)
 {
 	MsnSoapReq *request;
 
@@ -608,6 +714,7 @@
 	request->data_cb 	= data_cb;
 	request->read_cb	= read_cb;
 	request->written_cb	= written_cb;
+	request->connect_init	= connect_init;
 
 	return request;
 }
@@ -624,6 +731,7 @@
 	g_free(request->body);
 	request->read_cb	= NULL;
 	request->written_cb	= NULL;
+	request->connect_init	= NULL;
 
 	g_free(request);
 }
@@ -632,18 +740,24 @@
 void
 msn_soap_post_head_request(MsnSoapConn *soapconn)
 {
-	purple_debug_info("MSN SOAP", "Posting new request from head of the queue\n");
+	g_return_if_fail(soapconn != NULL);
+	g_return_if_fail(soapconn->soap_queue != NULL);
 	
-	g_return_if_fail(soapconn->soap_queue != NULL);
+	if (soapconn->step == MSN_SOAP_CONNECTED ||
+	    soapconn->step == MSN_SOAP_CONNECTED_IDLE) {
+
+		purple_debug_info("MSN SOAP", "Posting new request from head of the queue\n");
 
-	if(!g_queue_is_empty(soapconn->soap_queue)){
-		MsnSoapReq *request;
-		if((request = g_queue_pop_head(soapconn->soap_queue)) != NULL){
-			msn_soap_post_request(soapconn,request);
+		if ( !g_queue_is_empty(soapconn->soap_queue) ) {
+			MsnSoapReq *request;
+
+			if ( (request = g_queue_pop_head(soapconn->soap_queue)) != NULL ) {
+				msn_soap_post_request(soapconn,request);
+			}
+		} else {
+			purple_debug_info("MSN SOAP", "No requests to process found.\n");
+			msn_soap_set_process_step(soapconn, MSN_SOAP_CONNECTED_IDLE);
 		}
-	} else {
-		purple_debug_info("MSN SOAP", "No requests to process found.\n");
-		msn_soap_set_process_step(soapconn,MSN_SOAP_CONNECTED_IDLE);
 	}
 }
 
@@ -651,35 +765,59 @@
  * if not connected, Connected first.
  */
 void
-msn_soap_post(MsnSoapConn *soapconn,MsnSoapReq *request,
-				MsnSoapConnectInitFunction msn_soap_init_func)
+msn_soap_post(MsnSoapConn *soapconn,MsnSoapReq *request)
 {
+	MsnSoapReq *head_request;
+
+	if (soapconn == NULL)
+		return;
+
 	if (request != NULL) {
+#ifdef MSN_SOAP_DEBUG
+		purple_debug_misc("MSN SOAP", "Request added to the queue\n");
+#endif
 		g_queue_push_tail(soapconn->soap_queue, request);
 	}
-	if (!msn_soap_connected(soapconn) && (soapconn->step == MSN_SOAP_UNCONNECTED)
-					&&(!g_queue_is_empty(soapconn->soap_queue))) {
-		/*not connected?and we have something to process connect it first*/
-		purple_debug_misc("MSN SOAP","No connection to SOAP server. Connecting...\n");
-		msn_soap_init_func(soapconn);
-		msn_soap_connect(soapconn);
-		return;
-	}
-	purple_debug_misc("MSN SOAP","Connected to SOAP server\n");
+
+	if ( !g_queue_is_empty(soapconn->soap_queue)) {
+
+		/* we may have to reinitialize the soap connection, so avoid
+		 * reusing the connection for now */
+
+		if (soapconn->step == MSN_SOAP_CONNECTED_IDLE) {
+			purple_debug_misc("MSN SOAP","Already connected to SOAP server, re-initializing\n");
+			msn_soap_close_handler( &(soapconn->input_handler) );
+			msn_soap_close_handler( &(soapconn->output_handler) );
+			msn_soap_close(soapconn);
+		}
+
+		if (!msn_soap_connected(soapconn) && (soapconn->step == MSN_SOAP_UNCONNECTED)) {
 
-	/*if connected, what we only needed to do is to queue the request, 
-	 * when SOAP request in the queue processed done, will do this command.
-	 * we just waiting...
-	 * If we send the request this time,error may occure
-	 */
-	if (soapconn->step == MSN_SOAP_CONNECTED_IDLE){
-		msn_soap_post_head_request(soapconn);
+			/*not connected?and we have something to process connect it first*/
+			purple_debug_misc("MSN SOAP","No connection to SOAP server. Connecting...\n");
+			head_request = g_queue_peek_head(soapconn->soap_queue);
+
+			if (head_request == NULL) {
+				purple_debug_error("MSN SOAP", "Queue is not empty, but failed to peek the head request!\n");
+				return;
+			}
+
+			if (head_request->connect_init != NULL) {
+				head_request->connect_init(soapconn);
+			}
+			msn_soap_connect(soapconn);
+			return;
+		}
+
+		purple_debug_info("MSN SOAP", "Currently processing another SOAP request\n");
+	} else {
+		purple_debug_info("MSN SOAP", "No requests left to dispatch\n");
 	}
 }
 
 /*Post the soap request action*/
 void
-msn_soap_post_request(MsnSoapConn *soapconn,MsnSoapReq *request)
+msn_soap_post_request(MsnSoapConn *soapconn, MsnSoapReq *request)
 {
 	char * soap_head = NULL;
 	char * request_str = NULL;
--- a/libpurple/protocols/msn/soap.h	Sun Sep 16 18:47:12 2007 +0000
+++ b/libpurple/protocols/msn/soap.h	Wed Sep 19 06:08:42 2007 +0000
@@ -29,8 +29,10 @@
 #define MSN_SOAP_READ_BUFF_SIZE		8192
 
 /* define this to debug the communications with the SOAP server */
-/* #define MSN_SOAP_DEBUG  */
+/* #define MSN_SOAP_DEBUG */
 
+#define MSN_SOAP_READ 1
+#define MSN_SOAP_WRITE 2
 
 typedef enum
 {
@@ -41,13 +43,18 @@
 	MSN_SOAP_CONNECTED_IDLE
 }MsnSoapStep;
 
-/*MSN SoapRequest structure*/
+/* MSN SoapRequest structure*/
 typedef struct _MsnSoapReq MsnSoapReq;
 
-/*MSN Https connection structure*/
+/* MSN Https connection structure*/
 typedef struct _MsnSoapConn MsnSoapConn;
 
 typedef void (*MsnSoapConnectInitFunction)(MsnSoapConn *);
+typedef gboolean (*MsnSoapReadCbFunction)(MsnSoapConn *);
+typedef void (*MsnSoapWrittenCbFunction)(MsnSoapConn *);
+
+typedef gboolean (*MsnSoapSslConnectCbFunction)(MsnSoapConn *, PurpleSslConnection *);
+typedef void (*MsnSoapSslErrorCbFunction)(MsnSoapConn *, PurpleSslConnection *, PurpleSslErrorType);
 
 
 struct _MsnSoapReq{
@@ -61,8 +68,9 @@
 	char *body;
 	
 	gpointer data_cb;
-	PurpleInputFunction read_cb;
-	PurpleInputFunction written_cb;
+	MsnSoapReadCbFunction read_cb;
+	MsnSoapWrittenCbFunction written_cb;
+	MsnSoapConnectInitFunction connect_init;
 };
 
 struct _MsnSoapConn{
@@ -81,9 +89,9 @@
 	/*SSL connection*/
 	PurpleSslConnection *gsc;
 	/*ssl connection callback*/
-	PurpleSslInputFunction	connect_cb;
+	MsnSoapSslConnectCbFunction connect_cb;
 	/*ssl error callback*/
-	PurpleSslErrorFunction	error_cb;
+	MsnSoapSslErrorCbFunction error_cb;
 
 	/*read handler*/
 	guint input_handler;
@@ -97,13 +105,13 @@
 	/*write buffer*/
 	char *write_buf;
 	gsize written_len;
-	PurpleInputFunction written_cb;
+	MsnSoapWrittenCbFunction written_cb;
 
 	/*read buffer*/
 	char *read_buf;
 	gsize read_len;
 	gsize need_to_read;
-	PurpleInputFunction read_cb;
+	MsnSoapReadCbFunction read_cb;
 
 	gpointer data_cb;
 
@@ -118,8 +126,9 @@
 MsnSoapReq *msn_soap_request_new(const char *host, const char *post_url,
 				 const char *soap_action, const char *body,
 				 const gpointer data_cb,
-				 PurpleInputFunction read_cb,
-				 PurpleInputFunction written_cb);
+				 MsnSoapReadCbFunction read_cb,
+				 MsnSoapWrittenCbFunction written_cb,
+				 MsnSoapConnectInitFunction connect_init);
 
 void msn_soap_request_free(MsnSoapReq *request);
 void msn_soap_post_request(MsnSoapConn *soapconn,MsnSoapReq *request);
@@ -132,24 +141,27 @@
 void msn_soap_destroy(MsnSoapConn *soapconn);
 
 /*init a soap conneciton */
-void msn_soap_init(MsnSoapConn *soapconn,char * host,int ssl,PurpleSslInputFunction connect_cb,PurpleSslErrorFunction error_cb);
+void msn_soap_init(MsnSoapConn *soapconn, char * host, int ssl,
+		   MsnSoapSslConnectCbFunction connect_cb,
+		   MsnSoapSslErrorCbFunction error_cb);
 void msn_soap_connect(MsnSoapConn *soapconn);
 void msn_soap_close(MsnSoapConn *soapconn);
 
 /*write to soap*/
-void msn_soap_write(MsnSoapConn * soapconn, char *write_buf, PurpleInputFunction written_cb);
-void msn_soap_post(MsnSoapConn *soapconn,MsnSoapReq *request,MsnSoapConnectInitFunction msn_soap_init_func);
+void msn_soap_write(MsnSoapConn * soapconn, char *write_buf, MsnSoapWrittenCbFunction written_cb);
+void msn_soap_post(MsnSoapConn *soapconn,MsnSoapReq *request);
 
 void msn_soap_free_read_buf(MsnSoapConn *soapconn);
 void msn_soap_free_write_buf(MsnSoapConn *soapconn);
 void msn_soap_connect_cb(gpointer data, PurpleSslConnection *gsc, PurpleInputCondition cond);
 void msn_soap_read_cb(gpointer data, gint source, PurpleInputCondition cond);
 
-/*clean the unhandled request*/
-void msn_soap_clean_unhandled_request(MsnSoapConn *soapconn);
+/*clean the unhandled requests*/
+void msn_soap_clean_unhandled_requests(MsnSoapConn *soapconn);
 
 /*check if the soap connection is connected*/
 int msn_soap_connected(MsnSoapConn *soapconn);
+void msn_soap_set_process_step(MsnSoapConn *soapconn, MsnSoapStep step);
 
 #endif/*_MSN_SOAP_H_*/
 
--- a/libpurple/protocols/msn/userlist.c	Sun Sep 16 18:47:12 2007 +0000
+++ b/libpurple/protocols/msn/userlist.c	Wed Sep 19 06:08:42 2007 +0000
@@ -493,6 +493,29 @@
 	return NULL;
 }
 
+MsnUser *
+msn_userlist_find_user_with_id(MsnUserList *userlist, const char *uid)
+{
+ 	GList *l;
+
+        g_return_val_if_fail(uid != NULL, NULL);
+
+        for (l = userlist->users; l != NULL; l = l->next)
+        {
+                MsnUser *user = (MsnUser *)l->data;
+
+		if (user->uid == NULL) {
+			continue;
+		}
+
+		if ( !g_strcasecmp(uid, user->uid) ) {
+			return user;
+		}
+	}
+
+	return NULL;
+}
+
 void
 msn_userlist_add_group(MsnUserList *userlist, MsnGroup *group)
 {
--- a/libpurple/protocols/msn/userlist.h	Sun Sep 16 18:47:12 2007 +0000
+++ b/libpurple/protocols/msn/userlist.h	Wed Sep 19 06:08:42 2007 +0000
@@ -79,6 +79,7 @@
 MsnUser * msn_userlist_find_user(MsnUserList *userlist, const char *passport);
 MsnUser * msn_userlist_find_add_user(MsnUserList *userlist,
 				const char *passport, const char *userName);
+MsnUser * msn_userlist_find_user_with_id(MsnUserList *userlist, const char *uid);
 
 void msn_userlist_add_group(MsnUserList *userlist, MsnGroup *group);
 void msn_userlist_remove_group(MsnUserList *userlist, MsnGroup *group);