changeset 20477:9a2a4a0c0003

Add the possibility to create an Address Book, useful for newly registered MSN users. When changing friendly name, send the new one to the SOAP server in the PRP msn command callback, with escaped html entity chars. Fixes #1294 . Handle EBADF error sometimes received in SOAP server read callback (observed in win32). Misc cleanups.
author Carlos Silva <typ0@pidgin.im>
date Tue, 07 Aug 2007 02:37:58 +0000
parents fb52154f3c70
children c1c4468207fa
files libpurple/protocols/msn/contact.c libpurple/protocols/msn/contact.h libpurple/protocols/msn/msn.c libpurple/protocols/msn/nexus.c libpurple/protocols/msn/notification.c libpurple/protocols/msn/servconn.c libpurple/protocols/msn/soap.c libpurple/protocols/msn/soap.h libpurple/protocols/msn/userlist.c
diffstat 9 files changed, 463 insertions(+), 160 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/msn/contact.c	Mon Jul 23 18:16:58 2007 +0000
+++ b/libpurple/protocols/msn/contact.c	Tue Aug 07 02:37:58 2007 +0000
@@ -30,8 +30,6 @@
 #include "xmlnode.h"
 #include "group.h"
 
-/*define This to debug the Contact Server*/
-#undef  MSN_CONTACT_SOAP_DEBUG
 
 /*new a contact*/
 MsnContact *
@@ -122,6 +120,61 @@
 	return MSN_USER_TYPE_UNKNOWN;
 }
 
+/* Create the AddressBook in the server, if we don't have one */
+static void
+msn_create_address_cb(gpointer data, gint source, PurpleInputCondition cond)
+{
+	MsnSoapConn *soapconn = data;
+	MsnContact *contact;
+
+	contact = soapconn->parent;
+	g_return_if_fail(contact != NULL);
+
+	if ( g_strstr_len(soapconn->read_buf, soapconn->read_len, "HTTP/1.1 200") ) {
+		purple_debug_info("MSN AddressBook", "Address Book successfully created!\n");
+		msn_get_address_book(contact, NULL, NULL);
+	}
+	else {
+		 purple_debug_warning("MSN AddressBook", "Failed to create the Address Book!\n");
+	}
+
+	msn_soap_free_read_buf(soapconn);
+	return;
+}
+
+static void
+msn_create_address_written_cb(gpointer data, gint source, PurpleInputCondition cond)
+{
+	MsnSoapConn * soapconn = data;
+
+	purple_debug_info("MSN AddressBook","AddressBookAdd written\n");
+	soapconn->read_cb = msn_create_address_cb;
+
+	return;
+}
+
+static void
+msn_create_address_book(MsnContact * contact)
+{
+	MsnSoapReq *soap_request;
+	gchar *body;
+
+	purple_debug_info("MSN AddressBook","Creating an Address Book.\n");
+
+	body = g_strdup_printf(MSN_ADD_ADDRESSBOOK_TEMPLATE, contact->session->user->passport);
+
+	soap_request = msn_soap_request_new(MSN_CONTACT_SERVER,
+					MSN_ADDRESS_BOOK_POST_URL,MSN_ADD_ADDRESSBOOK_SOAP_ACTION,
+					body,
+					msn_create_address_cb,
+					msn_create_address_written_cb);
+	msn_soap_post(contact->soapconn, soap_request, msn_contact_connect_init);
+
+	g_free(body);
+	
+	return;
+}
+
 /*parse contact list*/
 static void
 msn_parse_contact_list(MsnContact * contact)
@@ -129,6 +182,7 @@
 	MsnSession * session;
 	int list_op = 0;
 	char * passport, *debugdata, *typedata;
+	xmlnode *fault, *faultstringnode, *faultdetail, *errorcode;
 	xmlnode *node, *body, *response, *result, *services;
 	xmlnode *service, *memberships, *info, *handle, *handletype;
 	xmlnode *LastChangeNode;
@@ -140,18 +194,62 @@
 	session = contact->session;
 	node = xmlnode_from_str(contact->soapconn->body, contact->soapconn->body_len);
 
-	debugdata = xmlnode_to_formatted_str(node, NULL);
-	purple_debug_info("MSNCL","Received contact list, parsing:\n%s",debugdata);
-	g_free(debugdata);
-
-	if(node == NULL){
+	if (node == NULL) {
 		purple_debug_error("MSNCL","Unable to parse SOAP data!\n");
 		return;
 	}
 
+#ifdef MSN_SOAP_DEBUG
+	debugdata = xmlnode_to_formatted_str(node, NULL);
+	purple_debug_info("MSNCL","Received contact list, parsing:\n%s", debugdata);
+	g_free(debugdata);
+#endif
+
+
 	purple_debug_info("MSNCL","Root node @ %p: Name: '%s', child: '%s', lastchild: '%s'\n",node,node->name,node->child->name,node->lastchild->name);
 	body = xmlnode_get_child(node,"Body");
+
+	if (body == NULL) {
+		purple_debug_warning("MSNCL", "Failed to parse contact list Body node\n");
+		xmlnode_free(node);
+		return;
+	}
 	purple_debug_info("MSNCL","Body @ %p:  Name: '%s'\n",body,body->name);
+
+	/* Did we receive a <Fault> ? */
+	if ( (fault = xmlnode_get_child(body, "Fault")) != NULL) {
+	        purple_debug_info("MSNCL","Fault received from SOAP server!\n");
+
+		if ( (faultstringnode = xmlnode_get_child(fault, "faultstring")) != NULL ) {
+			gchar * faultstring = xmlnode_get_data(faultstring);
+			purple_debug_info("MSNCL","Faultstring: %s\n", faultstring);
+			g_free(faultstring);
+		}
+		if ( (faultdetail = xmlnode_get_child(fault, "detail")) != NULL ) {
+			purple_debug_info("MSNCL","detail @ %p, name: %s\n",faultdetail, faultdetail->name);
+
+			if ( (errorcode = xmlnode_get_child(faultdetail, "errorcode")) != NULL ) {
+				purple_debug_info("MSNCL","errorcode @ %p, name: %s\n",errorcode, errorcode->name);
+
+				if (errorcode->child != NULL) {
+					gchar *errorcodestring = xmlnode_get_data(errorcode);
+					purple_debug_info("MSNCL", "Error Code: %s\n", errorcodestring);
+
+					if ( !strncmp(errorcodestring, "ABDoesNotExist", 14) ) {
+						xmlnode_free(node);
+						g_free(errorcodestring);
+						msn_create_address_book(contact);
+						return;
+					}
+					g_free(errorcodestring);
+				}
+			}
+		}
+		xmlnode_free(node);
+		msn_get_contact_list(contact, NULL);
+		return;
+	}
+
 	response = xmlnode_get_child(body,"FindMembershipResponse");
 
 	if (response == NULL) {
@@ -160,22 +258,29 @@
 		 * <faultstring>Need to do full sync. Can't sync deltas Client
 		 * has too old a copy for us to do a delta sync</faultstring>
 		 */
+		xmlnode_free(node);
 		msn_get_contact_list(contact, NULL);
 		return;
 	}
-	purple_debug_info("MSNCL","Response @ %p: Name: '%s'\n",response,response->name);
+	purple_debug_info("MSNCL","FindMembershipResponse @ %p: Name: '%s'\n",response,response->name);
 
 	result = xmlnode_get_child(response,"FindMembershipResult");
-	if(result == NULL){
-		purple_debug_warning("MSNCL","receive No Update!\n");
+	if (result == NULL) {
+		purple_debug_warning("MSNCL","Received No Update!\n");
+		xmlnode_free(node);
 		return;
 	}
-	purple_debug_info("MSNCL","Result @ %p: Name: '%s'\n",result,result->name);
+	purple_debug_info("MSNCL","Result @ %p: Name: '%s'\n", result, result->name);
 
-	services = xmlnode_get_child(result,"Services");
+	if ( (services = xmlnode_get_child(result,"Services")) == NULL) {
+		purple_debug_misc("MSNCL","No <Services> received.\n");
+		xmlnode_free(node);
+		return;
+	}
+
 	purple_debug_info("MSNCL","Services @ %p\n",services);
 	
-	for( service = xmlnode_get_child(services, "Service"); service;
+	for (service = xmlnode_get_child(services, "Service"); service;
 	                                service = xmlnode_get_next_twin(service)) {
 		purple_debug_info("MSNCL","Service @ %p\n",service);
 	
@@ -197,7 +302,7 @@
 			continue;
 		}
 
-		purple_debug_info("MSNCL","processing '%s' Service\n",typedata);
+		purple_debug_info("MSNCL","processing '%s' Service\n", typedata);
 
 		if ( !g_strcasecmp(typedata, "Profile") ) {
 			/* Process Windows Live 'Messenger Roaming Identity' */
@@ -211,8 +316,9 @@
 			LastChangeNode = xmlnode_get_child(service, "LastChange");
 			LastChangeStr = xmlnode_get_data(LastChangeNode);
 			purple_debug_info("MSNCL","LastChangeNode: '%s'\n",LastChangeStr);	
-			purple_account_set_string(session->account, "CLLastChange",LastChangeStr);
-	
+			purple_account_set_string(session->account, "CLLastChange", LastChangeStr);
+			g_free(LastChangeStr);
+
 			memberships = xmlnode_get_child(service,"Memberships");
 			if (memberships == NULL) {
 				purple_debug_warning("MSNCL","Memberships = NULL, cleaning up and returning.\n");
@@ -221,7 +327,7 @@
 				return;
 			}
 			purple_debug_info("MSNCL","Memberships @ %p: Name: '%s'\n",memberships,memberships->name);
-			for(membershipnode = xmlnode_get_child(memberships, "Membership"); membershipnode;
+			for (membershipnode = xmlnode_get_child(memberships, "Membership"); membershipnode;
 							membershipnode = xmlnode_get_next_twin(membershipnode)){
 				xmlnode *roleNode;
 				char *role;
@@ -234,14 +340,15 @@
 				g_free(role);
 				
 				members = xmlnode_get_child(membershipnode,"Members");
-				for(member = xmlnode_get_child(members, "Member"); member;
+				for (member = xmlnode_get_child(members, "Member"); member;
 						member = xmlnode_get_next_twin(member)){
 					MsnUser *user;
 					xmlnode * typeNode;
 					char * type;
 
-					purple_debug_info("MSNCL","Member type: %s\n",xmlnode_get_attrib(member,"type"));
-					if(!g_strcasecmp(xmlnode_get_attrib(member,"type"),"PassportMember")){
+					purple_debug_info("MSNCL","Member type: %s\n", xmlnode_get_attrib(member,"type"));
+					
+					if( !g_strcasecmp(xmlnode_get_attrib(member,"type"), "PassportMember") ) {
 						passportNode = xmlnode_get_child(member,"PassportName");
 						passport = xmlnode_get_data(passportNode);
 						typeNode = xmlnode_get_child(member,"Type");
@@ -253,16 +360,18 @@
 						msn_got_lst_user(session, user, list_op, NULL);
 						g_free(passport);
 					}
-					if(!g_strcasecmp(xmlnode_get_attrib(member,"type"),"PhoneMember")){
+					
+					if (!g_strcasecmp(xmlnode_get_attrib(member,"type"),"PhoneMember")) {
 					}
-					if(!g_strcasecmp(xmlnode_get_attrib(member,"type"),"EmailMember")){
+					
+					if (!g_strcasecmp(xmlnode_get_attrib(member,"type"),"EmailMember")) {
 						xmlnode *emailNode;
 
 						emailNode = xmlnode_get_child(member,"Email");
 						passport = xmlnode_get_data(emailNode);
-						purple_debug_info("MSNCL","Email Member: Name: '%s', list_op: %d\n",passport,list_op);
-						user = msn_userlist_find_add_user(session->userlist,passport,NULL);
-						msn_got_lst_user(session,user,list_op,NULL);
+						purple_debug_info("MSNCL","Email Member: Name: '%s', list_op: %d\n", passport, list_op);
+						user = msn_userlist_find_add_user(session->userlist, passport, NULL);
+						msn_got_lst_user(session, user, list_op, NULL);
 						g_free(passport);
 					}
 				}
@@ -290,8 +399,8 @@
 	session = soapconn->session;
 	g_return_if_fail(session != NULL);
 
-#ifdef  MSN_CONTACT_SOAP_DEBUG
-	purple_debug_info("msn", "soap contact server Reply: {%s}\n", soapconn->read_buf);
+#ifdef  MSN_SOAP_DEBUG
+	purple_debug_info("MSNCL", "SOAP server reply: \n%s\n", soapconn->read_buf);
 #endif
 	msn_parse_contact_list(contact);
 	/*free the read buffer*/
@@ -308,6 +417,7 @@
 #else
 	msn_get_address_book(contact, NULL, NULL);
 #endif
+	msn_soap_free_read_buf(soapconn);
 }
 
 static void
@@ -330,21 +440,22 @@
 
 	purple_debug_info("::","msn_get_contact_list()\n");
 
-	purple_debug_info("MSNP14","Getting Contact List...\n");
-	if(update_time != NULL){
+	purple_debug_info("MSNP14","Getting Contact List.\n");
+	if ( update_time != NULL ) {
 		purple_debug_info("MSNCL","last update time:{%s}\n",update_time);
 		update_str = g_strdup_printf(MSN_GET_CONTACT_UPDATE_XML,update_time);
-	}else{
+	} else {
 		update_str = g_strdup("");
 	}
 	body = g_strdup_printf(MSN_GET_CONTACT_TEMPLATE, update_str);
+	g_free(update_str);
+
 	soap_request = msn_soap_request_new(MSN_CONTACT_SERVER,
 					MSN_GET_CONTACT_POST_URL,MSN_GET_CONTACT_SOAP_ACTION,
 					body,
 					msn_get_contact_list_cb,
 					msn_get_contact_written_cb);
 	msn_soap_post(contact->soapconn,soap_request,msn_contact_connect_init);
-	g_free(update_str);
 	g_free(body);
 }
 
@@ -371,6 +482,7 @@
 
 		if (group_id == NULL){
 			/* Group of ungroupped buddies */
+			g_free(group_name);
 			continue;
 		}
 
@@ -413,11 +525,13 @@
 			friendly = xmlnode_get_data(xmlnode_get_child(contactInfo, "displayName"));
 			purple_connection_set_display_name(session->account->gc, purple_url_decode(friendly));
 			g_free(friendly);
+			g_free(uid);
+			g_free(type);
 			continue; /* Not adding own account as buddy to buddylist */
 		}
 		usertype = msn_get_user_type(type);
 		passportName = xmlnode_get_child(contactInfo,"passportName");
-		if(passportName == NULL){
+		if (passportName == NULL) {
 			xmlnode *emailsNode, *contactEmailNode, *emailNode;
 			xmlnode *messengerEnabledNode;
 			char *msnEnabled;
@@ -425,8 +539,10 @@
 			/*TODO: add it to the none-instant Messenger group and recognize as email Membership*/
 			/*Yahoo User?*/
 			emailsNode = xmlnode_get_child(contactInfo,"emails");
-			if(emailsNode == NULL){
+			if (emailsNode == NULL) {
 				/*TODO:  need to support the Mobile type*/
+				g_free(uid);
+				g_free(type);
 				continue;
 			}
 			for(contactEmailNode = xmlnode_get_child(emailsNode,"ContactEmail");contactEmailNode;
@@ -451,18 +567,20 @@
 				}
 				g_free(msnEnabled);
 			}
-		}else{
+		} else {
 			passport = xmlnode_get_data(passportName);
 		}
 
-		if(passport == NULL){
+		if (passport == NULL) {
+			g_free(uid);
+			g_free(type);
 			continue;
 		}
 
 		displayName = xmlnode_get_child(contactInfo,"displayName");
-		if(displayName == NULL){
+		if (displayName == NULL) {
 			Name = g_strdup(passport);
-		}else{
+		} else {
 			Name =xmlnode_get_data(displayName);
 		}
 
@@ -479,8 +597,8 @@
 
 		purple_debug_misc("MsnAB","parse guid...\n");
 		groupIds = xmlnode_get_child(contactInfo,"groupIds");
-		if(groupIds){
-			for(guid = xmlnode_get_child(groupIds, "guid");guid;
+		if (groupIds) {
+			for (guid = xmlnode_get_child(groupIds, "guid");guid;
 							guid = xmlnode_get_next_twin(guid)){
 				char *group_id;
 				group_id = xmlnode_get_data(guid);
@@ -488,7 +606,7 @@
 				purple_debug_misc("MsnAB","guid:%s\n",group_id);
 				g_free(group_id);
 			}
-		}else{
+		} else {
 			/*not in any group,Then set default group*/
 			msn_user_add_group_id(user, MSN_INDIVIDUALS_GROUP_ID);
 		}
@@ -505,23 +623,57 @@
 	xmlnode *groups;
 	xmlnode	*contacts;
 	xmlnode *abNode;
+	xmlnode *fault, *faultstringnode, *faultdetail, *errorcode;
 	gchar *printabledata;
 
 	session = contact->session;
 
+	
+
 	node = xmlnode_from_str(contact->soapconn->body, contact->soapconn->body_len);
 	if ( node == NULL ) {
-		purple_debug_error("MSN SOAP","Error parsing received Address Book with size %d:\n \"%s\"\n", contact->soapconn->body_len, contact->soapconn->body);
+		purple_debug_error("MSN AddressBook","Error parsing received Address Book with size %d:\n \"%s\"\n", contact->soapconn->body_len, contact->soapconn->body);
 		return FALSE;
 	}
 
 	printabledata = xmlnode_to_formatted_str(node, NULL);
-	purple_debug_misc("MSN SOAP","Received Address Book with size %d:\n %s\n", contact->soapconn->body_len, (char *) printabledata);
+	purple_debug_misc("MSN AddressBook","Received Address Book with size %d:\n %s\n", contact->soapconn->body_len, (char *) printabledata);
 	g_free(printabledata);
 
-	purple_debug_misc("MSN SOAP","node{%p},name:%s,child:%s,last:%s\n",node,node->name,node->child->name,node->lastchild->name);
+	purple_debug_misc("MSN AddressBook","node{%p},name:%s,child:%s,last:%s\n",node,node->name,node->child->name,node->lastchild->name);
+	
 	body = xmlnode_get_child(node,"Body");
-	purple_debug_misc("MSN SOAP","body{%p},name:%s\n",body,body->name);
+	purple_debug_misc("MSN AddressBook","body{%p},name:%s\n",body,body->name);
+	
+	if ( (fault = xmlnode_get_child(body, "Fault")) != NULL) {
+		purple_debug_info("MSN AddressBook","Fault received from SOAP server!\n");
+		
+		if ( (faultstringnode = xmlnode_get_child(fault, "faultstring")) != NULL ) {
+			gchar *faultstring = xmlnode_get_data(faultstring);
+			purple_debug_info("MSN AddressBook","Faultstring: %s\n", faultstring);
+			g_free(faultstring);
+		}
+		if ( (faultdetail = xmlnode_get_child(fault, "detail")) != NULL ) {
+			purple_debug_info("MSN AddressBook","detail @ %p, name: %s\n",faultdetail, faultdetail->name);
+
+			if ( (errorcode = xmlnode_get_child(faultdetail, "errorcode")) != NULL ) {
+				gchar *errorcodestring;
+				purple_debug_info("MSN AddressBook","errorcode @ %p, name: %s\n",errorcode, errorcode->name);
+
+				errorcodestring = xmlnode_get_data(errorcode);
+				purple_debug_info("MSN AddressBook", "Error Code: %s\n", errorcodestring);
+						
+				if ( !strncmp(errorcodestring, "ABDoesNotExist", 14) ) {
+					g_free(errorcodestring);
+					return TRUE;
+				}
+				g_free(errorcodestring);
+			}
+		}
+		return FALSE;
+	}
+
+
 	response = xmlnode_get_child(body,"ABFindAllResponse");
 
 	if (response == NULL) {
@@ -581,6 +733,8 @@
 		dynamicChange = xmlnode_get_data(DynamicItemLastChangedNode);
 		purple_debug_info("MsnAB"," DynamicItemLastChanged :{%s}\n",dynamicChange);
 		purple_account_set_string(session->account, "DynamicItemLastChanged", lastchange);
+		g_free(dynamicChange);
+		g_free(lastchange);
 	}
 
 	xmlnode_free(node);
@@ -601,11 +755,20 @@
 	g_return_if_fail(session != NULL);
 
 //	purple_debug_misc("msn", "soap contact server Reply: {%s}\n", soapconn->read_buf);
-	if (msn_parse_addressbook(contact)) {
+	if ( msn_parse_addressbook(contact) ) {
+		msn_soap_free_read_buf(soapconn);
+
 		msn_send_privacy(session->account->gc);
 		msn_notification_dump_contact(session);
 	} 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)
+		*/
+		/*
 		msn_get_address_book(contact, NULL, NULL);
+		*/
+		msn_session_disconnect(session);
+		purple_connection_error(session->account->gc, _("Unable to retrieve MSN Address Book"));
 	}
 
 	/*free the read buffer*/
@@ -631,35 +794,37 @@
 	char *ab_update_str,*update_str;
 
 	purple_debug_info("::","msn_get_address_book()\n");
+
 	/*build SOAP and POST it*/
-	if(LastChanged != NULL){
+	if ( LastChanged != NULL ) {
 		ab_update_str = g_strdup_printf(MSN_GET_ADDRESS_UPDATE_XML,LastChanged);
-	}else{
+	} else {
 		ab_update_str = g_strdup("");
 	}
-	if(dynamicItemLastChange != NULL){
+	if ( dynamicItemLastChange != NULL ) {
 		update_str = g_strdup_printf(MSN_GET_ADDRESS_UPDATE_XML,
 									 dynamicItemLastChange);
-	}else{
+	} else {
 		update_str = g_strdup(ab_update_str);
 	}
 	g_free(ab_update_str);
 	
 	body = g_strdup_printf(MSN_GET_ADDRESS_TEMPLATE,update_str);
+	g_free(update_str);
+
 	soap_request = msn_soap_request_new(MSN_CONTACT_SERVER,
 					MSN_ADDRESS_BOOK_POST_URL,MSN_GET_ADDRESS_SOAP_ACTION,
 					body,
 					msn_get_address_cb,
 					msn_address_written_cb);
 	msn_soap_post(contact->soapconn,soap_request,msn_contact_connect_init);
-	g_free(update_str);
 	g_free(body);
 }
 
 static void
 msn_add_contact_read_cb(gpointer data, gint source, PurpleInputCondition cond)
 {
-	purple_debug_info("MSNP14","add contact read done\n");
+	purple_debug_info("MSNCL","Add contact read done\n");
 }
 
 static void
@@ -667,7 +832,7 @@
 {
 	MsnSoapConn * soapconn = data;	
 
-	purple_debug_info("MSNP14","finish add contact  written\n");
+	purple_debug_info("MSNCL","Add contact request written\n");
 	soapconn->read_cb = msn_add_contact_read_cb;
 //	msn_soap_read_cb(data,source,cond);
 }
@@ -708,7 +873,7 @@
 static void
 msn_delete_contact_read_cb(gpointer data, gint source, PurpleInputCondition cond)
 {
-	purple_debug_info("MSNP14","delete contact read done\n");
+	purple_debug_info("MSNCL","Delete contact read done\n");
 }
 
 static void
@@ -716,7 +881,7 @@
 {
 	MsnSoapConn * soapconn = data;	
 
-	purple_debug_info("MSNP14","delete contact written\n");
+	purple_debug_info("MSNCL","Delete contact request written\n");
 	soapconn->read_cb = msn_delete_contact_read_cb;
 //	msn_soap_read_cb(data,source,cond);
 }
@@ -895,7 +1060,11 @@
 static void
 msn_group_read_cb(gpointer data, gint source, PurpleInputCondition cond)
 {
-	purple_debug_info("MSNP14","Group read \n");
+	MsnSoapConn * soapconn = data;
+	
+	purple_debug_info("MSNCL", "Add Group reply with the SOAP read_buf:\n%s\n",soapconn->read_buf);
+	purple_debug_info("MSNCL", "Add Group reply with the SOAP body:\n%s\n",soapconn->body);
+
 }
 
 static void
@@ -903,7 +1072,7 @@
 {
 	MsnSoapConn * soapconn = data;	
 
-	purple_debug_info("MSNP14","finish Group written\n");
+	purple_debug_info("MSNCL","Finished sending Add Group\n");
 	soapconn->read_cb = msn_group_read_cb;
 //	msn_soap_read_cb(data,source,cond);
 }
@@ -917,7 +1086,7 @@
 
 	g_return_if_fail(session != NULL);
 	contact = session->contact;
-	purple_debug_info("::","msn_add_group...\n");
+	purple_debug_info("::","msn_add_group()\n");
 
 	body = g_strdup_printf(MSN_GROUP_ADD_TEMPLATE,group_name);
 	/*build SOAP and POST it*/
@@ -930,7 +1099,7 @@
 }
 
 /*delete a group*/
-void msn_del_group(MsnSession *session,const char *guid)
+void msn_del_group(MsnSession *session, const char *guid)
 {
 	MsnSoapReq *soap_request;
 	MsnContact *contact;
--- a/libpurple/protocols/msn/contact.h	Mon Jul 23 18:16:58 2007 +0000
+++ b/libpurple/protocols/msn/contact.h	Tue Aug 07 02:37:58 2007 +0000
@@ -65,7 +65,35 @@
  * Address Book SOAP
  * *********************************************/
 #define MSN_ADDRESS_BOOK_POST_URL	"/abservice/abservice.asmx"
-/*get addressbook soap request template*/
+
+/* Add an address book template */
+#define MSN_ADD_ADDRESSBOOK_SOAP_ACTION     "http://www.msn.com/webservices/AddressBook/ABAdd"
+
+#define MSN_ADD_ADDRESSBOOK_TEMPLATE	"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
+	"<soap:Header>"\
+		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+			"<ApplicationId>09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId>"\
+			"<IsMigration>false</IsMigration>"\
+			"<PartnerScenario>Initial</PartnerScenario>"\
+		"</ABApplicationHeader>"\
+		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+			"<ManagedGroupRequest>false</ManagedGroupRequest>"\
+		"</ABAuthHeader>"\
+	"</soap:Header>"\
+	"<soap:Body>"\
+		"<ABAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+			"<abInfo>"\
+				"<name/>"\
+				"<ownerPuid>0</ownerPuid>"\
+				"<ownerEmail>%s</ownerEmail>"\
+				"<fDefault>true</fDefault>"\
+			"</abInfo>"\
+		"</ABAdd>"\
+	"</soap:Body>"\
+"</soap:Envelope>"
+
+/* get addressbook soap request template */
 #define MSN_GET_ADDRESS_SOAP_ACTION	"http://www.msn.com/webservices/AddressBook/ABFindAll"
 #define MSN_GET_ADDRESS_FULL_TIME "0001-01-01T00:00:00.0000000-08:00"
 #define MSN_GET_ADDRESS_UPDATE_XML "<deltasOnly>true</deltasOnly>"\
--- a/libpurple/protocols/msn/msn.c	Mon Jul 23 18:16:58 2007 +0000
+++ b/libpurple/protocols/msn/msn.c	Tue Aug 07 02:37:58 2007 +0000
@@ -131,9 +131,6 @@
 	PurpleAccount *account;
 	const char *alias;
 
-	char *soapbody;
-	MsnSoapReq *soap_request;
-
 	session = gc->proto_data;
 	cmdproc = session->notification->cmdproc;
 	account = purple_connection_get_account(gc);
@@ -156,21 +153,6 @@
 
 	msn_cmdproc_send(cmdproc, "PRP", "MFN %s", alias);
 
-	soapbody = g_strdup_printf(MSN_CONTACT_UPDATE_TEMPLATE, alias);
-	/*build SOAP and POST it*/
-	soap_request = msn_soap_request_new(MSN_CONTACT_SERVER,
-										MSN_ADDRESS_BOOK_POST_URL,
-										MSN_CONTACT_UPDATE_SOAP_ACTION,
-										soapbody,
-										NULL,
-										NULL);
-
-	session->contact->soapconn->read_cb = NULL;
-	msn_soap_post(session->contact->soapconn,
-				  soap_request,
-				  msn_contact_connect_init);
-
-	g_free(soapbody);
 }
 
 static void
--- a/libpurple/protocols/msn/nexus.c	Mon Jul 23 18:16:58 2007 +0000
+++ b/libpurple/protocols/msn/nexus.c	Tue Aug 07 02:37:58 2007 +0000
@@ -335,7 +335,7 @@
 					soapconn->login_path,soapconn->login_host,(int)strlen(tail));
 
 	request_str = g_strdup_printf("%s%s", head,tail);
-	purple_debug_misc("msn", "TWN Sending: {%s}\n", request_str);
+	purple_debug_misc("msn", "TWN Sending:\n%s\n", request_str);
 
 	g_free(head);
 	g_free(tail);
--- a/libpurple/protocols/msn/notification.c	Mon Jul 23 18:16:58 2007 +0000
+++ b/libpurple/protocols/msn/notification.c	Tue Aug 07 02:37:58 2007 +0000
@@ -674,7 +674,19 @@
 	adl_node = xmlnode_new("ml");
 	adl_node->child = NULL;
 	xmlnode_set_attrib(adl_node, "l", "1");
-	
+
+
+	if ( session->userlist->users == NULL ) {
+		/* we have no users yet in our contact list */
+		payload = xmlnode_to_str(adl_node,&payload_len);
+
+		msn_notification_post_adl(session->notification->cmdproc,
+			payload, payload_len);
+
+		g_free(payload);
+		xmlnode_free(adl_node);
+	}
+	else {
 	/*get the userlist*/
 	for (l = session->userlist->users; l != NULL; l = l->next){
 		user = l->data;
@@ -703,11 +715,12 @@
 			}
 		}
 	}
-
+	}
 
 	display_name = purple_connection_get_display_name(session->account->gc);
-	if (display_name && strcmp(display_name,
-							   purple_account_get_username(session->account))) {
+	if (display_name 
+	    && strcmp(display_name, 
+		      purple_account_get_username(session->account))) {
 		msn_act_id(session->account->gc, display_name);
 	}
 
@@ -746,15 +759,11 @@
 static void
 adl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
-	static int initial;
-
 	purple_debug_info("MSNP14","Process ADL\n");
 
-	if (!initial)
-        {
-                purple_debug_misc("MSNP14","Initial ADL received\n");
-                msn_session_finish_login(cmdproc->session);
-        }
+	msn_session_finish_login(cmdproc->session);
+
+	return;
 }
 
 static void
@@ -1136,7 +1145,11 @@
 prp_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
 	MsnSession *session = cmdproc->session;
-	const char *type, *value;
+	const char *type, *value, *friendlyname;
+	gchar *soapname, *soapbody;
+	MsnSoapReq *soap_request;
+
+	purple_debug_info("MSN Notification", "prp_cmd()\n");
 
 	g_return_if_fail(cmd->param_count >= 3);
 
@@ -1163,10 +1176,28 @@
 		else {
 			type = cmd->params[1];
 			if (!strcmp(type, "MFN")) {
+				friendlyname = purple_url_decode(cmd->params[2]);
+				soapname = g_markup_escape_text(friendlyname,-1);
+				soapbody = g_strdup_printf(MSN_CONTACT_UPDATE_TEMPLATE, soapname);
 
+				soap_request = msn_soap_request_new(MSN_CONTACT_SERVER,
+								    MSN_ADDRESS_BOOK_POST_URL,
+								    MSN_CONTACT_UPDATE_SOAP_ACTION,
+								    soapbody,
+								    NULL,
+								    NULL);
+
+				session->contact->soapconn->read_cb = NULL;
+
+				msn_soap_post(session->contact->soapconn,
+					      soap_request,
+					      msn_contact_connect_init);
+
+				g_free(soapbody);
+				g_free(soapname);
 				purple_connection_set_display_name(
 					purple_account_get_connection(session->account),
-					purple_url_decode(cmd->params[2]));
+					friendlyname);
 			}
 		}
 	}
--- a/libpurple/protocols/msn/servconn.c	Mon Jul 23 18:16:58 2007 +0000
+++ b/libpurple/protocols/msn/servconn.c	Tue Aug 07 02:37:58 2007 +0000
@@ -390,14 +390,21 @@
 
 	len = read(servconn->fd, buf, sizeof(buf) - 1);
 
-	if (len < 0 && errno == EAGAIN)
-		return;
-	else if (len <= 0)
-	{
-		purple_debug_error("msn", "servconn read error, len: %d error: %s\n", len, strerror(errno));
-		msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ);
+	if (len <= 0) {
+		switch (errno) {
+
+			case 0:	
 
-		return;
+			case EBADF:
+			case EAGAIN: return;
+	
+			default: purple_debug_error("msn", "servconn read error,"
+						"len: %d, errno: %d, error: %s\n",
+						len, errno, strerror(errno));
+				 msn_servconn_got_error(servconn, 
+						 MSN_SERVCONN_ERROR_READ);
+				 return;
+		}
 	}
 
 	buf[len] = '\0';
--- a/libpurple/protocols/msn/soap.c	Mon Jul 23 18:16:58 2007 +0000
+++ b/libpurple/protocols/msn/soap.c	Tue Aug 07 02:37:58 2007 +0000
@@ -26,8 +26,6 @@
 #include "msn.h"
 #include "soap.h"
 
-/*define this Macro to debug soap server action*/
-#undef MSN_SOAP_DEBUG
 
 /*local function prototype*/
 void msn_soap_set_process_step(MsnSoapConn *soapconn, MsnSoapStep step);
@@ -68,7 +66,8 @@
 	MsnSoapConn * soapconn;
 	MsnSession *session;
 
-	purple_debug_info("MSNP14","Soap connection connected!\n");
+	purple_debug_info("MSN SOAP","SOAP server connection established!\n");
+
 	soapconn = data;
 	g_return_if_fail(soapconn != NULL);
 
@@ -94,7 +93,7 @@
 	MsnSoapConn * soapconn = data;
 
 	g_return_if_fail(data != NULL);
-	purple_debug_info("MSNP14","Soap connection error!\n");
+	purple_debug_info("MSN SOAP","Soap connection error!\n");
 	msn_soap_set_process_step(soapconn, MSN_SOAP_UNCONNECTED);
 
 	/*error callback*/
@@ -109,7 +108,7 @@
 				PurpleSslInputFunction	connect_cb,
 				PurpleSslErrorFunction	error_cb)
 {
-	purple_debug_info("MSNP14","msn_soap_init...\n");
+	purple_debug_info("MSN SOAP","msn_soap_init()\n");
 	soapconn->login_host = g_strdup(host);
 	soapconn->ssl_conn = ssl;
 	soapconn->connect_cb = connect_cb;
@@ -203,26 +202,95 @@
 static gssize
 msn_soap_read(MsnSoapConn *soapconn)
 {
-	gssize len,requested_len;
+	gssize len, requested_len;
 	char temp_buf[MSN_SOAP_READ_BUFF_SIZE];
+	
+	if ( soapconn->need_to_read == 0 || soapconn->need_to_read > MSN_SOAP_READ_BUFF_SIZE) {
+		requested_len = MSN_SOAP_READ_BUFF_SIZE;
+	}
+	else {
+		requested_len = soapconn->need_to_read;
+	}
+
+	if ( soapconn->ssl_conn ) {
+		len = purple_ssl_read(soapconn->gsc, temp_buf, requested_len);
+	} else {
+		len = read(soapconn->fd, temp_buf, requested_len);
+	}
+
+	if ( len <= 0 ) {
+		switch (errno) {
 
-//	requested_len = (soapconn->need_to_read > 0) ? soapconn->need_to_read : MSN_SOAP_READ_BUFF_SIZE;
-	requested_len = MSN_SOAP_READ_BUFF_SIZE;
-	if(soapconn->ssl_conn){
-		len = purple_ssl_read(soapconn->gsc, temp_buf,requested_len);
-	}else{
-		len = read(soapconn->fd, temp_buf,requested_len);
+			case 0:
+			case EBADF: /* we are sometimes getting this in Windows */
+			case EAGAIN:
+#ifdef MSN_SOAP_DEBUG
+				purple_debug_info("MSN SOAP",
+					"msn_soap_read(): %s, returning len = %d.\n",
+					strerror(errno), len);
+#endif
+				     return len;
+			default : purple_debug_error("MSN SOAP", "Read error!"
+						"read len: %d, error = %s\n",
+						len, strerror(errno));
+				  purple_input_remove(soapconn->input_handler);
+				  soapconn->input_handler = -1;
+				  g_free(soapconn->read_buf);
+				  soapconn->read_buf = NULL;
+				  soapconn->read_len = 0;
+				  /* TODO: error handling */
+				  return len;
+		}
 	}
-	if(len >0){
+	else {
+#ifdef MSN_SOAP_DEBUG
+		purple_debug_info("MSN SOAP", "Allocating space for more %d bytes from incoming data. Total space now (according to soapconn->read_len = %d\n", len, soapconn->read_len);
+#endif
 		soapconn->read_buf = g_realloc(soapconn->read_buf,
 						soapconn->read_len + len + 1);
-		memcpy(soapconn->read_buf + soapconn->read_len, temp_buf, len);
-		soapconn->read_len += len;
-		soapconn->read_buf[soapconn->read_len] = '\0';
+		if ( soapconn->read_buf != NULL ) {
+			memcpy(soapconn->read_buf + soapconn->read_len, temp_buf, len);
+			soapconn->read_len += len;
+			soapconn->read_buf[soapconn->read_len] = '\0';
+		}
+		else {
+			purple_debug_error("MSN SOAP", "Failure re-allocating %d bytes of memory!\n", soapconn->read_len + len + 1);
+			exit(EXIT_FAILURE);
+		}
+			
 	}
+
 #ifdef MSN_SOAP_DEBUG
-	purple_debug_info("MSNP14","++soap ssl read:{%d}\n",len);
-	purple_debug_info("MSNP14","nexus ssl read:{%s}\n",soapconn->read_buf);
+	purple_debug_info("MSN SOAP","Read SOAP bytes: %d\n", len);
+
+	if (len > -1) {
+		gchar * soapbody = NULL;
+		xmlnode * node = NULL;
+		soapbody = g_strstr_len(soapconn->read_buf, soapconn->read_len, "\r\n\r\n");
+		if (soapbody != NULL)
+			node = xmlnode_from_str(soapbody+4, -1);
+	
+	        if (node != NULL) {
+        	        gchar *pretty = xmlnode_to_formatted_str(node, NULL);
+			gchar *http_headers, *delimiter;
+
+			delimiter = g_strstr_len(soapconn->read_buf, soapconn->read_len,"\r\n\r\n");
+			if (delimiter  != NULL) {
+
+				http_headers = g_strndup(soapconn->read_buf, delimiter + 4 - soapconn->read_buf);
+                		purple_debug_info("MSN SOAP","Nexus server read data:\n%s%s\n", http_headers, pretty);
+				g_free(http_headers);
+			}
+			else
+				purple_debug_info("MSN SOAP","Nexus server read data:\n%s\n", soapconn->read_buf);
+		
+        	        g_free(pretty);
+                	xmlnode_free(node);
+        	}
+        	else
+                	purple_debug_info("MSN SOAP","Received data from Nexus server:\n%s\n", soapconn->read_buf);
+		
+	}
 #endif
 	return len;
 }
@@ -237,40 +305,31 @@
 	char * body_start,*body_len;
 	char *length_start,*length_end;
 
-//	purple_debug_misc("MSNP14", "soap read cb\n");
+#ifdef MSN_SOAP_DEBUG
+	purple_debug_misc("MSN SOAP", "msn_soap_read_cb()\n");
+#endif
 	session = soapconn->session;
 	g_return_if_fail(session != NULL);
 
-	if (soapconn->input_handler == -1){
-		soapconn->input_handler = purple_input_add(soapconn->gsc->fd,
-			PURPLE_INPUT_READ, msn_soap_read_cb, soapconn);
-	}
+	
 
 	/*read the request header*/
 	len = msn_soap_read(soapconn);
-	if (len < 0 && errno == EAGAIN){
+	
+	if ( len < 0 )
 		return;
-	}else if (len < 0) {
-		purple_debug_error("msn", "read Error!len:%d\n",len);
-		purple_input_remove(soapconn->input_handler);
-		soapconn->input_handler = -1;
-		g_free(soapconn->read_buf);
-		soapconn->read_buf = NULL;
-		soapconn->read_len = 0;
-		/* TODO: error handling */
+
+	if (soapconn->read_buf == NULL) {
 		return;
 	}
 
-	if(soapconn->read_buf == NULL){
-		return;
-	}
-
-	if (strstr(soapconn->read_buf, "HTTP/1.1 302") != NULL)
+	if ( (strstr(soapconn->read_buf, "HTTP/1.1 302") != NULL) 
+		|| ( strstr(soapconn->read_buf, "HTTP/1.1 301") != NULL ) )
 	{
 		/* Redirect. */
 		char *location, *c;
 
-		purple_debug_error("MSNP14", "soap redirect\n");
+		purple_debug_info("MSN SOAP", "HTTP Redirect\n");
 		location = strstr(soapconn->read_buf, "Location: ");
 		if (location == NULL)
 		{
@@ -343,7 +402,7 @@
 	{
 		const char *error;
 
-		purple_debug_error("MSNP14", "soap 401\n");
+		purple_debug_error("MSN SOAP", "Received HTTP error 401 Unauthorized\n");
 		if ((error = strstr(soapconn->read_buf, "WWW-Authenticate")) != NULL)
 		{
 			if ((error = strstr(error, "cbtxt=")) != NULL)
@@ -391,8 +450,8 @@
 	{
 			/*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;
+			if (!body_start) {
+				return;
 			}
 			body_start += 4;
 
@@ -402,19 +461,20 @@
 			length_start = strstr(soapconn->read_buf, "Content-Length: ");
 			length_start += strlen("Content-Length: ");
 			length_end = strstr(length_start, "\r\n");
-			body_len = g_strndup(length_start,length_end - length_start);
+			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);
 #ifdef MSN_SOAP_DEBUG
-			purple_debug_misc("MSNP14","SOAP Read length :%d,body len:%d\n",soapconn->read_len,soapconn->body_len);
+			purple_debug_misc("MSN SOAP","SOAP Read length: %d, Body len: %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){
+			soapconn->need_to_read = (body_start - soapconn->read_buf + soapconn->body_len) - soapconn->read_len;
+			if ( soapconn->need_to_read > 0 ) {
 				return;
 			}
-			g_free(body_len);
+			//g_free(body_len);
 
 			/*remove the read handler*/
 			purple_input_remove(soapconn->input_handler);
@@ -431,9 +491,10 @@
 			msn_soap_close(soapconn);
 
 			/*call the read callback*/
-			if(soapconn->read_cb != NULL){
-				soapconn->read_cb(soapconn,source,0);
+			if ( soapconn->read_cb != NULL ) {
+				soapconn->read_cb(soapconn, source, 0);
 			}
+			msn_soap_free_read_buf(soapconn);
 	}
 	return;
 }
@@ -467,8 +528,8 @@
 	int len, total_len;
 
 	g_return_if_fail(soapconn != NULL);
-	if(soapconn->write_buf == NULL){
-		purple_debug_error("MSNP14","soap buffer is NULL\n");
+	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;
 		return;
@@ -489,6 +550,7 @@
 		purple_input_remove(soapconn->output_handler);
 		soapconn->output_handler = -1;
 		/* TODO: notify of the error */
+		purple_debug_error("MSN SOAP","Error writing to SSL connection!\n");
 		return;
 	}
 	soapconn->written_len += len;
@@ -509,7 +571,11 @@
 		soapconn->written_cb(soapconn, source, 0);
 	}
 	/*maybe we need to read the input?*/
-	msn_soap_read_cb(soapconn,source,0);
+	if ( soapconn->input_handler == -1 ) {
+		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*/
@@ -519,6 +585,8 @@
 	soapconn->write_buf = write_buf;
 	soapconn->written_len = 0;
 	soapconn->written_cb = written_cb;
+	
+	msn_soap_free_read_buf(soapconn);
 
 	/*clear the read buffer first*/
 	/*start the write*/
@@ -586,18 +654,18 @@
 msn_soap_post(MsnSoapConn *soapconn,MsnSoapReq *request,
 				MsnSoapConnectInitFunction msn_soap_init_func)
 {
-	if(request != NULL){
+	if (request != NULL) {
 		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))){
+	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_info("MSNP14","soap is not connected!\n");
+		purple_debug_info("MSN SOAP","No connection to SOAP server. Connecting...\n");
 		msn_soap_init_func(soapconn);
 		msn_soap_connect(soapconn);
 		return;
 	}
-	purple_debug_info("MSNP14","soap  connected!\n");
+	purple_debug_info("MSN SOAP","Connected to SOAP server!\n");
 
 	/*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.
@@ -618,7 +686,11 @@
 	char * soap_head = NULL;
 	char * request_str = NULL;
 
-	purple_debug_info("MSNP14","msn_soap_post_request()...\n");
+#ifdef MSN_SOAP_DEBUG
+	xmlnode * node;
+
+	purple_debug_info("MSN SOAP","msn_soap_post_request()...\n");
+#endif
 	msn_soap_set_process_step(soapconn,MSN_SOAP_PROCESSING);
 	soap_head = g_strdup_printf(
 					"POST %s HTTP/1.1\r\n"
@@ -637,13 +709,21 @@
 					request->login_host,
 					strlen(request->body)
 					);
-	request_str = g_strdup_printf("%s%s", soap_head,request->body);
-	g_free(soap_head);
+	request_str = g_strdup_printf("%s%s", soap_head, request->body);
 
 #ifdef MSN_SOAP_DEBUG
-	purple_debug_info("MSNP14","send to  server{%s}\n",request_str);
+	node = xmlnode_from_str(request->body, -1);
+	if (node != NULL) {
+		char *pretty = xmlnode_to_formatted_str(node, NULL);
+		purple_debug_info("MSN SOAP","Posting request to SOAP server:\n%s%s\n",soap_head, pretty);
+		g_free(pretty);
+		xmlnode_free(node);
+	}
+	else
+		purple_debug_info("MSN SOAP","Failed to parse SOAP request:\n%s\n", request_str);
 #endif
-
+	
+	g_free(soap_head);
 	/*free read buffer*/
 	msn_soap_free_read_buf(soapconn);
 	/*post it to server*/
--- a/libpurple/protocols/msn/soap.h	Mon Jul 23 18:16:58 2007 +0000
+++ b/libpurple/protocols/msn/soap.h	Tue Aug 07 02:37:58 2007 +0000
@@ -28,6 +28,10 @@
 
 #define MSN_SOAP_READ_BUFF_SIZE		8192
 
+/* define this to debug the communications with the SOAP server */
+#undef MSN_SOAP_DEBUG
+
+
 typedef enum
 {
 	MSN_SOAP_UNCONNECTED,
--- a/libpurple/protocols/msn/userlist.c	Mon Jul 23 18:16:58 2007 +0000
+++ b/libpurple/protocols/msn/userlist.c	Tue Aug 07 02:37:58 2007 +0000
@@ -706,6 +706,8 @@
 
 	store_name = (user != NULL) ? get_store_name(user) : who;
 
+	purple_debug_info("MSNCL", "store_name = %s\n",store_name);
+
 	/* XXX: see XXX above, this should really be done when we get the response from
 	   the server */
 	msn_user_set_op(user, list_id);
@@ -713,7 +715,7 @@
 	/* Then request the add to the server. */
 	list = lists[list_id];
 
-	purple_debug_info("MSNP14", "add user:{%s} to group id {%s}\n",store_name ,group_id);
+	purple_debug_info("MSNP14", "Add user: %s to group id: %s\n",store_name ,group_id);
 	msn_add_contact(userlist->session->contact,who,group_id);
 	msn_notification_add_buddy(userlist->session->notification, list, who,
 							   store_name, group_id);