changeset 20484:98613886411a

Handle special cases in buddy/group management (wrt MSN_INDIVIDUALS_GROUP and MSN_NON_IM_GROUP). Deprecate now unused MSNP protocol commands.
author Carlos Silva <typ0@pidgin.im>
date Fri, 31 Aug 2007 18:12:35 +0000
parents 115290ce3b92
children 87eea1c5be97
files libpurple/protocols/msn/contact.c libpurple/protocols/msn/contact.h libpurple/protocols/msn/msn.c libpurple/protocols/msn/notification.c libpurple/protocols/msn/soap.h libpurple/protocols/msn/userlist.c
diffstat 6 files changed, 189 insertions(+), 114 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/msn/contact.c	Tue Aug 28 05:21:17 2007 +0000
+++ b/libpurple/protocols/msn/contact.c	Fri Aug 31 18:12:35 2007 +0000
@@ -31,10 +31,11 @@
 #include "group.h"
 
 
-const char *MsnAddressBookActionText[] =
+const char *MsnSoapPartnerScenarioText[] =
 {
         "Initial",
-        "ContactSave"
+        "ContactSave",
+	"MessengerPendingList"
 };
 
 
@@ -175,7 +176,7 @@
 	g_return_if_fail(session != NULL);
 
 	/*login ok!We can retrieve the contact list*/
-//	msn_get_contact_list(contact,NULL);
+//	msn_get_contact_list(contact, MSN_PS_INITIAL, NULL);
 }
 
 /*get MSN member role utility*/
@@ -223,7 +224,7 @@
 	g_return_if_fail(contact != NULL);
 
 	purple_debug_info("MSN AddressBook", "Address Book successfully created!\n");
-	msn_get_address_book(contact, MSN_AB_INITIAL, NULL, NULL);
+	msn_get_address_book(contact, MSN_PS_INITIAL, NULL, NULL);
 
 //	msn_soap_free_read_buf(soapconn);
 	return;
@@ -332,7 +333,7 @@
 			}
 		}
 		xmlnode_free(node);
-		msn_get_contact_list(contact, NULL);
+		msn_get_contact_list(contact, MSN_PS_INITIAL, NULL);
 		return;
 	}
 
@@ -345,7 +346,7 @@
 		 * has too old a copy for us to do a delta sync</faultstring>
 		 */
 		xmlnode_free(node);
-		msn_get_contact_list(contact, NULL);
+		msn_get_contact_list(contact, MSN_PS_INITIAL, NULL);
 		return;
 	}
 	purple_debug_info("MSNCL","FindMembershipResponse @ %p: Name: '%s'\n",response,response->name);
@@ -496,9 +497,9 @@
 	/* XXX: this should be enabled when we can correctly do partial
 	   syncs with the server. Currently we need to retrieve the whole
 	   list to detect sync issues */
-	msn_get_address_book(contact, MSN_AB_INITIAL, abLastChange, dynamicItemLastChange);
+	msn_get_address_book(contact, MSN_PS_INITIAL, abLastChange, dynamicItemLastChange);
 #else
-	msn_get_address_book(contact, MSN_AB_INITIAL, NULL, NULL);
+	msn_get_address_book(contact, MSN_PS_INITIAL, NULL, NULL);
 #endif
 	msn_soap_free_read_buf(soapconn);
 }
@@ -515,7 +516,7 @@
 
 /*SOAP  get contact list*/
 void
-msn_get_contact_list(MsnContact * contact, const char *update_time)
+msn_get_contact_list(MsnContact * contact, const MsnSoapPartnerScenario partner_scenario, const char *update_time)
 {
 	MsnSoapReq *soap_request;
 	char *body = NULL;
@@ -528,7 +529,7 @@
 	} else {
 		update_str = g_strdup("");
 	}
-	body = g_strdup_printf(MSN_GET_CONTACT_TEMPLATE, update_str);
+	body = g_strdup_printf(MSN_GET_CONTACT_TEMPLATE, MsnSoapPartnerScenarioText[partner_scenario], update_str);
 	g_free(update_str);
 
 	soap_request = msn_soap_request_new(MSN_CONTACT_SERVER,
@@ -836,7 +837,7 @@
 	purple_debug_misc("MSN AddressBook", "Got the Address Book!\n");
 
 	if ( msn_parse_addressbook(contact) ) {
-		msn_soap_free_read_buf(soapconn);
+		//msn_soap_free_read_buf(soapconn);
 
 		if (!session->logged_in) {
 			msn_send_privacy(session->account->gc);
@@ -869,11 +870,11 @@
 
 /*get the address book*/
 void
-msn_get_address_book(MsnContact *contact, const MsnAddressBookAction abaction, const char *LastChanged, const char *dynamicItemLastChange)
+msn_get_address_book(MsnContact *contact, const MsnSoapPartnerScenario partner_scenario, const char *LastChanged, const char *dynamicItemLastChange)
 {
 	MsnSoapReq *soap_request;
 	char *body = NULL;
-	char *ab_update_str,*update_str, *partner_scenario;
+	char *ab_update_str,*update_str;
 
 	purple_debug_misc("MSN AddressBook","Getting Address Book\n");
 
@@ -891,13 +892,9 @@
 	}
 	g_free(ab_update_str);
 	
-	partner_scenario = g_strdup(MsnAddressBookActionText[abaction]);
 
-	purple_debug_misc("MSN CL", "Get Address Book PartnerScenario parameter: %s\n", partner_scenario);
-
-	body = g_strdup_printf(MSN_GET_ADDRESS_TEMPLATE, partner_scenario, update_str);
+	body = g_strdup_printf(MSN_GET_ADDRESS_TEMPLATE, MsnSoapPartnerScenarioText[partner_scenario], update_str);
 	g_free(update_str);
-	g_free(partner_scenario);
 
 	soap_request = msn_soap_request_new(MSN_CONTACT_SERVER,
 					MSN_ADDRESS_BOOK_POST_URL,MSN_GET_ADDRESS_SOAP_ACTION,
@@ -909,15 +906,13 @@
 	g_free(body);
 }
 
-/* We don't need this as libpurple doesn't support ungroupped buddies, so we
- * can add buddies directly to a group with msn_add_contact_to_group() */
-#if 0	
 static void
 msn_add_contact_read_cb(gpointer data, gint source, PurpleInputCondition cond)
 {
 	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);
@@ -939,17 +934,11 @@
 	}
 	msn_notification_send_fqy(soapconn->session, state->who);
 	
+	user = msn_userlist_find_add_user(userlist, state->who, state->who);
+	msn_user_add_group_id(user, state->guid);
 
-	if (state->action & MSN_ADD_BUDDY_TO_GROUP) {
-		msn_add_contact_to_group(soapconn->session->contact,
-					 state,
-			       		 state->who,
-					 state->guid);
-	} else {
-		msn_callback_state_free(state);
-		msn_soap_free_read_buf(soapconn);
-	}
-	
+	msn_callback_state_free(state);
+	msn_soap_free_read_buf(soapconn);
 }
 
 static void
@@ -961,26 +950,29 @@
 	soapconn->read_cb = msn_add_contact_read_cb;
 }
 
-/* add a Contact */
+/* add a Contact in MSN_INDIVIDUALS_GROUP */
 void
-msn_add_contact(MsnContact *contact, MsnCallbackState *state, const char *passport, const char *displayname)
+msn_add_contact(MsnContact *contact, MsnCallbackState *state, const char *passport)
 {
 	MsnSoapReq *soap_request;
 	gchar *body = NULL;
 	gchar *contact_xml = NULL;
 	gchar *soap_action;
-//	gchar *escaped_displayname;
+/*	gchar *escaped_displayname;
+
 
+	 if (displayname != NULL) {
+		escaped_displayname = g_markup_decode_text(displayname, -1);
+	 } else {
+		escaped_displayname = passport;
+	 }
+	contact_xml = g_strdup_printf(MSN_XML_ADD_CONTACT, escaped_displayname, passport);
+*/
 	purple_debug_info("MSNCL","Adding contact %s to contact list\n", passport);
 
-	// if (displayname != NULL) {
-	//	escaped_displayname = g_markup_decode_text(displayname, -1);
-	// } else {
-	//	escaped_displayname = passport;
-	// }
-	// contact_xml = g_strdup_printf(MSN_XML_ADD_CONTACT, escaped_displayname, passport);
-	
-	contact_xml = g_strdup_printf(MSN_CONTACT_XML, passport);
+//	if ( !strcmp(state->guid, MSN_INDIVIDUALS_GROUP_ID) ) {
+		contact_xml = g_strdup_printf(MSN_CONTACT_XML, passport);
+//	}
 	body = g_strdup_printf(MSN_ADD_CONTACT_TEMPLATE, contact_xml);
 
 	g_free(contact_xml);
@@ -1000,7 +992,6 @@
 	g_free(soap_action);
 	g_free(body);
 }
-#endif
 
 static void
 msn_add_contact_to_group_read_cb(gpointer data, gint source, PurpleInputCondition cond)
@@ -1066,7 +1057,27 @@
 	g_return_if_fail(contact->session->userlist != NULL);
 	
 	userlist = contact->session->userlist;
-	
+
+	if (!strcmp(groupId, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(groupId, MSN_NON_IM_GROUP_ID)) {
+		
+		user = msn_userlist_find_add_user(userlist, passport, passport);
+
+		if (state->action & MSN_ADD_BUDDY) {
+			msn_add_contact(contact, state, passport);
+			return;
+		}
+
+		if (state->action & MSN_MOVE_BUDDY) {
+			msn_user_add_group_id(user, groupId);
+			msn_del_contact_from_group(contact, passport, state->old_group_name);
+		} else {
+			msn_callback_state_free(state);
+		}
+
+		return;
+	}
+
+
 	purple_debug_info("MSNCL", "Adding user %s to group %s\n", passport, 
 			  msn_userlist_find_group_name(userlist, groupId));
 
@@ -1209,7 +1220,12 @@
 		purple_debug_warning("MSN CL", "Unable to retrieve user from passport %s!\n", passport);
 		return;
 	}
-	
+
+	if ( !strcmp(groupId, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(groupId, MSN_NON_IM_GROUP_ID)) {
+		msn_user_remove_group_id(user, groupId);
+		return;
+	}
+
 	state = msn_callback_state_new();
 	msn_callback_state_set_who(state, passport);
 	msn_callback_state_set_guid(state, groupId);
@@ -1296,13 +1312,13 @@
 
 /*block a Contact*/
 void
-msn_block_contact(MsnContact *contact,const char* membership_id)
+msn_block_contact(MsnContact *contact, const char* membership_id)
 {
 	MsnSoapReq *soap_request;
 	char *body = NULL;
 
 	purple_debug_info("MSNP14","msn block a contact...\n");
-	body = g_strdup_printf(MSN_CONTACT_DELECT_FROM_ALLOW_TEMPLATE,membership_id);
+	body = g_strdup_printf(MSN_CONTACT_DELECT_FROM_ALLOW_TEMPLATE, membership_id);
 	/*build SOAP and POST it*/
 	soap_request = msn_soap_request_new(MSN_CONTACT_SERVER,
 					MSN_SHARE_POST_URL,
@@ -1534,6 +1550,12 @@
 		purple_debug_info("MSN CL", "Group %s guid not found, returning.\n", group_name);
 		return;
 	}
+
+	if ( !strcmp(guid, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(guid, MSN_NON_IM_GROUP_ID) ) {
+		// add back PurpleGroup since it isn't really removed in the server?
+		return;
+	}
+
 	state = msn_callback_state_new();
 	msn_callback_state_set_action(state, MSN_DEL_GROUP);
 	msn_callback_state_set_guid(state, guid);
@@ -1573,10 +1595,16 @@
 	guid = msn_userlist_find_group_id(session->userlist, old_group_name);
 	if (guid == NULL)
 		return;
-	
-	msn_callback_state_set_action(state, MSN_RENAME_GROUP);
+
 	msn_callback_state_set_guid(state, guid);
 	msn_callback_state_set_new_group_name(state, new_group_name);
+
+	if ( !strcmp(guid, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(guid, MSN_NON_IM_GROUP_ID) ) {
+		msn_add_group(session, state, new_group_name);
+		// XXX move every buddy there (we probably need to fix concurrent SOAP reqs first)
+	}
+
+	msn_callback_state_set_action(state, MSN_RENAME_GROUP);
 	
 	/* escape group name's html special chars so it can safely be sent
 	 * in a XML SOAP request
--- a/libpurple/protocols/msn/contact.h	Tue Aug 28 05:21:17 2007 +0000
+++ b/libpurple/protocols/msn/contact.h	Fri Aug 31 18:12:35 2007 +0000
@@ -40,22 +40,22 @@
 		"<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
 			"<ApplicationId xmlns=\"http://www.msn.com/webservices/AddressBook\">09607671-1C32-421F-A6A6-CBFAA51AB5F4</ApplicationId>"\
 			"<IsMigration xmlns=\"http://www.msn.com/webservices/AddressBook\">false</IsMigration>"\
-			"<PartnerScenario xmlns=\"http://www.msn.com/webservices/AddressBook\">Initial</PartnerScenario>"\
+			"<PartnerScenario xmlns=\"http://www.msn.com/webservices/AddressBook\">%s</PartnerScenario>"\
 		 "</ABApplicationHeader>"\
 		"<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-		"<ManagedGroupRequest xmlns=\"http://www.msn.com/webservices/AddressBook\">false</ManagedGroupRequest>"\
+			"<ManagedGroupRequest xmlns=\"http://www.msn.com/webservices/AddressBook\">false</ManagedGroupRequest>"\
 		"</ABAuthHeader>"\
 	"</soap:Header>"\
 	"<soap:Body xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
 		"<FindMembership xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
 			"<serviceFilter xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-			"<Types xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-				"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Messenger</ServiceType>"\
-				"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Invitation</ServiceType>"\
-				"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">SocialNetwork</ServiceType>"\
-				"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Space</ServiceType>"\
-				"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Profile</ServiceType>"\
-			"</Types>"\
+				"<Types xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+					"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Messenger</ServiceType>"\
+					"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Invitation</ServiceType>"\
+					"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">SocialNetwork</ServiceType>"\
+					"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Space</ServiceType>"\
+					"<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Profile</ServiceType>"\
+				"</Types>"\
 			"</serviceFilter>"\
 			"%s"\
 		"</FindMembership>"\
@@ -128,32 +128,6 @@
 "</soap:Envelope>"
 
 
-/*	Send this shit after adding a contact (with ABGroupContactAdd or something) damnit!	
-<?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>ContactSave</PartnerScenario>
-		</ABApplicationHeader>
-		<ABAuthHeader xmlns="http://www.msn.com/webservices/AddressBook">
-			<ManagedGroupRequest>false</ManagedGroupRequest>
-		</ABAuthHeader>
-	</soap:Header>
-	<soap:Body>
-		<ABFindAll xmlns="http://www.msn.com/webservices/AddressBook">
-			<abId>00000000-0000-0000-0000-000000000000</abId>
-			<abView>Full</abView>
-			<deltasOnly>true</deltasOnly>
-			<lastChange>2007-08-22T06:19:36.84-07:00</lastChange>
-			<dynamicItemView>Gleam</dynamicItemView>
-			<dynamicItemLastChange>0001-01-01T00:00:00</dynamicItemLastChange>
-		</ABFindAll>
-	</soap:Body>
-</soap:Envelope>
-*/
-
 /*Gleams SOAP request template*/
 #define MSN_GET_GLEAMS_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABFindAll"
 #define MSN_GLEAMS_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
@@ -342,9 +316,10 @@
 
 typedef enum 
 {
-	MSN_AB_INITIAL,
-	MSN_AB_SAVE_CONTACT
-} MsnAddressBookAction;
+	MSN_PS_INITIAL,
+	MSN_PS_SAVE_CONTACT,
+	MSN_PS_PENDING_LIST
+} MsnSoapPartnerScenario;
 
 
 /************************************************
@@ -366,15 +341,18 @@
 				   MsnCallbackAction action);
 
 void msn_contact_connect(MsnContact *contact);
-void msn_get_contact_list(MsnContact * contact, const char *update);
-void msn_get_address_book(MsnContact *contact, MsnAddressBookAction abaction,
+void msn_get_contact_list(MsnContact * contact, 
+			  const MsnSoapPartnerScenario partner_scenario,
+			  const char *update);
+void msn_get_address_book(MsnContact *contact, 
+			  const MsnSoapPartnerScenario partner_scenario,
 			  const char * update, const char * gupdate);
 
 /*contact SOAP Operation*/
 void msn_update_contact(MsnContact *contact, const char* nickname);
 
 void msn_add_contact(MsnContact *contact, MsnCallbackState *state, 
-		     const char *passport, const char *displayname);
+		     const char *passport);
 void msn_delete_contact(MsnContact *contact, const char *contactId);
 
 void msn_add_contact_to_group(MsnContact *contact, MsnCallbackState *state, 
--- a/libpurple/protocols/msn/msn.c	Tue Aug 28 05:21:17 2007 +0000
+++ b/libpurple/protocols/msn/msn.c	Fri Aug 31 18:12:35 2007 +0000
@@ -1450,10 +1450,12 @@
 	session = gc->proto_data;
 	cmdproc = session->notification->cmdproc;
 
+	purple_debug_info("MSN", "Remove group %s\n", group->name);
 	/*we can't delete the default group*/
 	if(!strcmp(group->name, MSN_INDIVIDUALS_GROUP_NAME)||
 		!strcmp(group->name, MSN_NON_IM_GROUP_NAME))
 	{
+		purple_debug_info("MSN", "This group can't be removed, returning.\n");
 		return ;
 	}
 	
--- a/libpurple/protocols/msn/notification.c	Tue Aug 28 05:21:17 2007 +0000
+++ b/libpurple/protocols/msn/notification.c	Fri Aug 31 18:12:35 2007 +0000
@@ -593,7 +593,6 @@
 	char *email,*domain;
 	char *list_op_str,*type_str;
 
-	purple_debug_info("::","msn_add_contact_xml()\n");
 	purple_debug_info("MSNP14","Passport: %s, type: %d\n", passport, type);
 	tokens = g_strsplit(passport, "@", 2);
 	email = tokens[0];
@@ -652,8 +651,7 @@
 msn_notification_post_adl(MsnCmdProc *cmdproc, const char *payload, int payload_len)
 {
 	MsnTransaction *trans;
-	purple_debug_info("::","msn_notification_post_adl()\n");
-	purple_debug_info("MSNP14","Sending ADL with payload: %s\n", payload);
+	purple_debug_info("MSN Notification","Sending ADL with payload: %s\n", payload);
 	trans = msn_transaction_new(cmdproc, "ADL","%d", strlen(payload));
 	msn_transaction_set_payload(trans, payload, strlen(payload));
 	msn_cmdproc_send_trans(cmdproc, trans);
@@ -676,17 +674,6 @@
 	adl_node->child = NULL;
 	xmlnode_set_attrib(adl_node, "l", "1");
 
-
-/*	if ( session->userlist->users == NULL ) {
-		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;
@@ -764,9 +751,79 @@
 }
 
 static void
+adl_cmd_parse(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
+		                         size_t len)
+{
+	xmlnode *root, *domain_node;
+
+	purple_debug_misc("MSN Notification", "Parsing received ADL XML data\n");
+
+	g_return_if_fail(payload != NULL);
+	
+	root = xmlnode_from_str(payload, (gssize) len);
+	
+	if (root == NULL) {
+		purple_debug_info("MSN Notification", "Invalid XML!\n");
+		return;
+	}
+	for (domain_node = xmlnode_get_child(root, "d"); domain_node; domain_node = xmlnode_get_next_twin(domain_node)) {
+		const gchar * domain = NULL; 
+		xmlnode *contact_node = NULL;
+
+		domain = xmlnode_get_attrib(domain_node, "n");
+
+		for (contact_node = xmlnode_get_child(domain_node, "c"); contact_node; contact_node = xmlnode_get_next_twin(contact_node)) {
+//			gchar *name = NULL, *friendlyname = NULL, *passport= NULL;
+			const gchar *list;
+			gint list_op = 0;
+
+//			name = xmlnode_get_attrib(contact_node, "n");
+			list = xmlnode_get_attrib(contact_node, "l");
+			if (list != NULL) {
+				list_op = atoi(list);
+			}
+//			friendlyname = xmlnode_get_attrib(contact_node, "f");
+
+//			passport = g_strdup_printf("%s@%s", name, domain);
+
+//			if (friendlyname != NULL) {
+//				decoded_friendlyname = g_strdup(purple_url_decode(friendlyname));
+//			} else {
+//				decoded_friendlyname = g_strdup(passport);
+//			}
+
+			if (list_op & MSN_LIST_RL_OP) {
+				/* someone is adding us */
+//				got_new_entry(cmdproc->session->account->gc, passport, decoded_friendly_name);
+				msn_get_contact_list(cmdproc->session->contact, MSN_PS_PENDING_LIST, NULL);
+			}
+
+//			g_free(decoded_friendly_name);
+//			g_free(passport);
+		}
+	}
+
+	xmlnode_free(root);
+}
+
+static void
 adl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
-	msn_session_finish_login(cmdproc->session);
+	MsnSession *session;
+
+	g_return_if_fail(cmdproc != NULL);
+	g_return_if_fail(cmdproc->session != NULL);
+	g_return_if_fail(cmdproc->last_cmd != NULL);
+	g_return_if_fail(cmd != NULL);
+
+	session = cmdproc->session;
+
+	if ( !strcmp(cmd->params[1], "OK")) {
+		/* ADL ack */
+		msn_session_finish_login(session);
+	} else {
+		cmdproc->last_cmd->payload_cb = adl_cmd_parse;
+	}
 
 	return;
 }
@@ -797,7 +854,7 @@
 	g_return_if_fail(cmdproc->session != NULL);
 	g_return_if_fail(cmdproc->session->contact != NULL);
 //	msn_notification_post_adl(cmdproc, payload, len);
-	msn_get_address_book(cmdproc->session->contact, MSN_AB_SAVE_CONTACT, NULL, NULL);
+//	msn_get_address_book(cmdproc->session->contact, MSN_AB_SAVE_CONTACT, NULL, NULL);
 }
 
 static void
@@ -1663,10 +1720,10 @@
 #ifdef MSN_PARTIAL_LISTS
 	/* msn_userlist_load defeats all attempts at trying to detect blist sync issues */
 	msn_userlist_load(session);
-	msn_get_contact_list(session->contact, clLastChange);
+	msn_get_contact_list(session->contact, MSN_PS_INITIAL, clLastChange);
 #else
 	/* always get the full list? */
-	msn_get_contact_list(session->contact, NULL);
+	msn_get_contact_list(session->contact, MSN_PS_INITIAL, NULL);
 #endif
 #if 0
 	msn_contact_connect(session->contact);
@@ -1972,11 +2029,11 @@
 	msn_table_add_cmd(cbs_table, "CHG", "CHG", NULL);
 	msn_table_add_cmd(cbs_table, "CHG", "ILN", iln_cmd);
 	msn_table_add_cmd(cbs_table, "ADL", "ILN", iln_cmd);
-	msn_table_add_cmd(cbs_table, "REM", "REM", rem_cmd);
+//	msn_table_add_cmd(cbs_table, "REM", "REM", rem_cmd);	/* Removed as of MSNP13 */
 	msn_table_add_cmd(cbs_table, "USR", "USR", usr_cmd);
 	msn_table_add_cmd(cbs_table, "USR", "XFR", xfr_cmd);
 	msn_table_add_cmd(cbs_table, "USR", "GCF", gcf_cmd);
-	msn_table_add_cmd(cbs_table, "SYN", "SYN", syn_cmd);
+//	msn_table_add_cmd(cbs_table, "SYN", "SYN", syn_cmd);	/* Removed as of MSNP13 */
 	msn_table_add_cmd(cbs_table, "CVR", "CVR", cvr_cmd);
 	msn_table_add_cmd(cbs_table, "VER", "VER", ver_cmd);
 	msn_table_add_cmd(cbs_table, "REA", "REA", rea_cmd);
--- a/libpurple/protocols/msn/soap.h	Tue Aug 28 05:21:17 2007 +0000
+++ b/libpurple/protocols/msn/soap.h	Fri Aug 31 18:12:35 2007 +0000
@@ -29,7 +29,7 @@
 #define MSN_SOAP_READ_BUFF_SIZE		8192
 
 /* define this to debug the communications with the SOAP server */
-#undef MSN_SOAP_DEBUG
+/* #define MSN_SOAP_DEBUG */
 
 
 typedef enum
--- a/libpurple/protocols/msn/userlist.c	Tue Aug 28 05:21:17 2007 +0000
+++ b/libpurple/protocols/msn/userlist.c	Fri Aug 31 18:12:35 2007 +0000
@@ -106,7 +106,7 @@
 }
 
 static gboolean
-msn_userlist_user_is_in_list(MsnUser *user, int list_id)
+msn_userlist_user_is_in_list(MsnUser *user, MsnListId list_id)
 {
 	int list_op;
 
@@ -373,6 +373,11 @@
 		}
 	}
 
+	if (list_op & MSN_LIST_PL_OP)
+	{
+		got_new_entry(gc, passport, store);
+	}
+
 	user->list_op |= list_op;
 }
 
@@ -629,6 +634,7 @@
 	
 	new_group_name = group_name == NULL ? MSN_INDIVIDUALS_GROUP_NAME : group_name;
 
+	
 	g_return_if_fail(userlist != NULL);
 	g_return_if_fail(userlist->session != NULL);
 
@@ -669,6 +675,9 @@
 		msn_callback_state_set_guid(state, group_id);
 	}
 	
+	/* XXX: adding user here may not be correct (should add them in the
+ 	 * ACK to the ADL command), but for now we need to make sure they exist  
+	 * early enough that the ILN command doesn't screw us up */
 
 	user = msn_userlist_find_add_user(userlist, who, who);
 
@@ -787,12 +796,13 @@
 			const char *old_group_name, const char *new_group_name)
 {
 	const char *new_group_id;
-	MsnCallbackState *state = msn_callback_state_new();
+	MsnCallbackState *state;
 	
 	g_return_if_fail(userlist != NULL);
 	g_return_if_fail(userlist->session != NULL);
 	g_return_if_fail(userlist->session->contact != NULL);
-	
+
+	state = msn_callback_state_new();
 	msn_callback_state_set_who(state, who);
 	msn_callback_state_set_action(state, MSN_MOVE_BUDDY);
 	msn_callback_state_set_old_group_name(state, old_group_name);