Make use of the GQueue in MsnSoapConn to manage the SOAP requests, allowing them to work perfectly even when dispatching multiple requests at once. cpw.khc.msnp14

Wed, 19 Sep 2007 06:08:42 +0000

author
Carlos Silva <typ0@pidgin.im>
date
Wed, 19 Sep 2007 06:08:42 +0000
branch
cpw.khc.msnp14
changeset 20609
b92d0b5ab89d
parent 20608
907a459c1ba4
child 20610
211ab3cb7a38

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.

libpurple/protocols/msn/contact.c file | annotate | diff | comparison | revisions
libpurple/protocols/msn/contact.h file | annotate | diff | comparison | revisions
libpurple/protocols/msn/nexus.c file | annotate | diff | comparison | revisions
libpurple/protocols/msn/oim.c file | annotate | diff | comparison | revisions
libpurple/protocols/msn/soap.c file | annotate | diff | comparison | revisions
libpurple/protocols/msn/soap.h file | annotate | diff | comparison | revisions
libpurple/protocols/msn/userlist.c file | annotate | diff | comparison | revisions
libpurple/protocols/msn/userlist.h file | annotate | diff | comparison | revisions
--- 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);

mercurial