Index: protocols/msn/msn.c
===================================================================
--- protocols/msn/msn.c	(revision e5854a80111e337be01cf1e506073a231fac1c3d)
+++ protocols/msn/msn.c	(revision 193dc742d357bb604fff8921417c74ddf9e8729c)
@@ -217,12 +217,12 @@
 	struct bee_user *bu = bee_user_by_handle( ic->bee, ic, who );
 	
-	msn_buddy_list_add( ic, "FL", who, who, group );
+	msn_buddy_list_add( ic, MSN_BUDDY_FL, who, who, group );
 	if( bu && bu->group )
-		msn_buddy_list_remove( ic, "FL", who, bu->group->name );
+		msn_buddy_list_remove( ic, MSN_BUDDY_FL, who, bu->group->name );
 }
 
 static void msn_remove_buddy( struct im_connection *ic, char *who, char *group )
 {
-	msn_buddy_list_remove( ic, "FL", who, NULL );
+	msn_buddy_list_remove( ic, MSN_BUDDY_FL, who, NULL );
 }
 
@@ -289,10 +289,10 @@
 static void msn_add_permit( struct im_connection *ic, char *who )
 {
-	msn_buddy_list_add( ic, "AL", who, who, NULL );
+	msn_buddy_list_add( ic, MSN_BUDDY_AL, who, who, NULL );
 }
 
 static void msn_rem_permit( struct im_connection *ic, char *who )
 {
-	msn_buddy_list_remove( ic, "AL", who, NULL );
+	msn_buddy_list_remove( ic, MSN_BUDDY_AL, who, NULL );
 }
 
@@ -301,5 +301,5 @@
 	struct msn_switchboard *sb;
 	
-	msn_buddy_list_add( ic, "BL", who, who, NULL );
+	msn_buddy_list_add( ic, MSN_BUDDY_BL, who, who, NULL );
 	
 	/* If there's still a conversation with this person, close it. */
@@ -312,5 +312,5 @@
 static void msn_rem_deny( struct im_connection *ic, char *who )
 {
-	msn_buddy_list_remove( ic, "BL", who, NULL );
+	msn_buddy_list_remove( ic, MSN_BUDDY_BL, who, NULL );
 }
 
Index: protocols/msn/msn.h
===================================================================
--- protocols/msn/msn.h	(revision e5854a80111e337be01cf1e506073a231fac1c3d)
+++ protocols/msn/msn.h	(revision 193dc742d357bb604fff8921417c74ddf9e8729c)
@@ -201,6 +201,6 @@
 int msn_write( struct im_connection *ic, char *s, int len );
 int msn_logged_in( struct im_connection *ic );
-int msn_buddy_list_add( struct im_connection *ic, const char *list, const char *who, const char *realname_, const char *group );
-int msn_buddy_list_remove( struct im_connection *ic, char *list, const char *who, const char *group );
+int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname_, const char *group );
+int msn_buddy_list_remove( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *group );
 void msn_buddy_ask( bee_user_t *bu );
 char *msn_findheader( char *text, char *header, int len );
Index: protocols/msn/msn_util.c
===================================================================
--- protocols/msn/msn_util.c	(revision e5854a80111e337be01cf1e506073a231fac1c3d)
+++ protocols/msn/msn_util.c	(revision 193dc742d357bb604fff8921417c74ddf9e8729c)
@@ -27,4 +27,5 @@
 #include "msn.h"
 #include "md5.h"
+#include "soap.h"
 #include <ctype.h>
 
@@ -58,10 +59,29 @@
 }
 
-int msn_buddy_list_add( struct im_connection *ic, const char *list, const char *who, const char *realname_, const char *group )
+static char *adlrml_entry( const char *handle_, msn_buddy_flags_t list )
+{
+	char *domain, handle[strlen(handle_)+1];
+	
+	strcpy( handle, handle_ );
+	if( ( domain = strchr( handle, '@' ) ) )
+		*(domain
+		++) = '\0';
+	else
+		return NULL;
+	
+	return g_markup_printf_escaped( "<ml><d n=\"%s\"><c n=\"%s\" l=\"%d\" t=\"1\"/></d></ml>",
+		domain, handle, list );
+}
+
+int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname_, const char *group )
 {
 	struct msn_data *md = ic->proto_data;
-	char buf[1024], realname[strlen(realname_)*3+1], groupid[8];
+	char buf[1024], groupid[8];
+	bee_user_t *bu;
+	struct msn_buddy_data *bd;
+	char *adl;
 	
 	*groupid = '\0';
+#if 0
 	if( group )
 	{
@@ -109,18 +129,34 @@
 		}
 	}
-	
-	strcpy( realname, realname_ );
-	http_encode( realname );
-	g_snprintf( buf, sizeof( buf ), "ADD %d %s %s %s%s\r\n", ++md->trId, list, who, realname, groupid );
-	
-	return msn_write( ic, buf, strlen( buf ) );
-}
-
-int msn_buddy_list_remove( struct im_connection *ic, char *list, const char *who, const char *group )
+#endif
+	
+	if( !( bu = bee_user_by_handle( ic->bee, ic, who ) ) ||
+	    !( bd = bu->data ) || bd->flags & list )
+		return 1;
+	
+	bd->flags |= list;
+	
+	msn_soap_memlist_edit( ic, who, TRUE, list );
+	
+	if( ( adl = adlrml_entry( who, list ) ) )
+	{
+		g_snprintf( buf, sizeof( buf ), "ADL %d %zd\r\n%s",
+		            ++md->trId, strlen( adl ), adl );
+		g_free( adl );
+		
+		return msn_write( ic, buf, strlen( buf ) );
+	}
+}
+
+int msn_buddy_list_remove( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *group )
 {
 	struct msn_data *md = ic->proto_data;
 	char buf[1024], groupid[8];
+	bee_user_t *bu;
+	struct msn_buddy_data *bd;
+	char *adl;
 	
 	*groupid = '\0';
+#if 0
 	if( group )
 	{
@@ -133,8 +169,22 @@
 			}
 	}
-	
-	g_snprintf( buf, sizeof( buf ), "REM %d %s %s%s\r\n", ++md->trId, list, who, groupid );
-	if( msn_write( ic, buf, strlen( buf ) ) )
-		return( 1 );
+#endif
+	
+	if( !( bu = bee_user_by_handle( ic->bee, ic, who ) ) ||
+	    !( bd = bu->data ) || !( bd->flags & list ) )
+		return 1;
+	
+	bd->flags &= ~list;
+	
+	msn_soap_memlist_edit( ic, who, FALSE, list );
+	
+	if( ( adl = adlrml_entry( who, list ) ) )
+	{
+		g_snprintf( buf, sizeof( buf ), "RML %d %zd\r\n%s",
+		            ++md->trId, strlen( adl ), adl );
+		g_free( adl );
+		
+		return msn_write( ic, buf, strlen( buf ) );
+	}
 	
 	return( 0 );
@@ -152,5 +202,5 @@
 	struct msn_buddy_ask_data *bla = data;
 	
-	msn_buddy_list_add( bla->ic, "AL", bla->handle, bla->realname, NULL );
+	msn_buddy_list_add( bla->ic, MSN_BUDDY_AL, bla->handle, bla->realname, NULL );
 	
 	imcb_ask_add( bla->ic, bla->handle, NULL );
@@ -165,5 +215,5 @@
 	struct msn_buddy_ask_data *bla = data;
 	
-	msn_buddy_list_add( bla->ic, "BL", bla->handle, bla->realname, NULL );
+	msn_buddy_list_add( bla->ic, MSN_BUDDY_BL, bla->handle, bla->realname, NULL );
 	
 	g_free( bla->handle );
Index: protocols/msn/ns.c
===================================================================
--- protocols/msn/ns.c	(revision e5854a80111e337be01cf1e506073a231fac1c3d)
+++ protocols/msn/ns.c	(revision 193dc742d357bb604fff8921417c74ddf9e8729c)
@@ -264,8 +264,11 @@
 		{
 			char buf[1024];
-			char *fn_raw = set_getstr( &ic->acc->set, "display_name" );
+			char *fn_raw;
 			char *fn;
 			
-			if( fn_raw == NULL )
+			if( ic->flags & OPT_LOGGED_IN )
+				return 1;
+			
+			if( ( fn_raw = set_getstr( &ic->acc->set, "display_name" ) ) == NULL )
 				fn_raw = ic->acc->user;
 			fn = g_malloc( strlen( fn_raw ) * 3 + 1 );
Index: protocols/msn/soap.c
===================================================================
--- protocols/msn/soap.c	(revision e5854a80111e337be01cf1e506073a231fac1c3d)
+++ protocols/msn/soap.c	(revision 193dc742d357bb604fff8921417c74ddf9e8729c)
@@ -517,4 +517,85 @@
 }
 
+/* Variant: Adding/Removing people */
+struct msn_soap_memlist_edit_data
+{
+	char *handle;
+	gboolean add;
+	msn_buddy_flags_t list;
+};
+
+static int msn_soap_memlist_edit_build_request( struct msn_soap_req_data *soap_req )
+{
+	struct msn_data *md = soap_req->ic->proto_data;
+	struct msn_soap_memlist_edit_data *med = soap_req->data;
+	char *add, *scenario, *list;
+	
+	soap_req->url = g_strdup( SOAP_MEMLIST_URL );
+	if( med->add )
+	{
+		soap_req->action = g_strdup( SOAP_MEMLIST_ADD_ACTION );
+		add = "Add";
+	}
+	else
+	{
+		soap_req->action = g_strdup( SOAP_MEMLIST_DEL_ACTION );
+		add = "Delete";
+	}
+	switch( med->list )
+	{
+	case MSN_BUDDY_AL:
+		scenario = "BlockUnblock";
+		list = "Allow";
+		break;
+	case MSN_BUDDY_BL:
+		scenario = "BlockUnblock";
+		list = "Block";
+		break;
+	case MSN_BUDDY_RL:
+		scenario = "Timer";
+		list = "Reverse";
+		break;
+	case MSN_BUDDY_PL:
+	default:
+		scenario = "Timer";
+		list = "Pending";
+		break;
+	}
+	soap_req->payload = g_markup_printf_escaped( SOAP_MEMLIST_EDIT_PAYLOAD,
+		scenario, md->tokens[1], add, list, med->handle, add );
+	
+	return 1;
+}
+
+static int msn_soap_memlist_edit_handle_response( struct msn_soap_req_data *soap_req )
+{
+	return MSN_SOAP_OK;
+}
+
+static int msn_soap_memlist_edit_free_data( struct msn_soap_req_data *soap_req )
+{
+	struct msn_soap_memlist_edit_data *med = soap_req->data;
+	
+	g_free( med->handle );
+	g_free( med );
+	
+	return 0;
+}
+
+int msn_soap_memlist_edit( struct im_connection *ic, const char *handle, gboolean add, int list )
+{
+	struct msn_soap_memlist_edit_data *med;
+	
+	med = g_new0( struct msn_soap_memlist_edit_data, 1 );
+	med->handle = g_strdup( handle );
+	med->add = add;
+	med->list = list;
+	
+	return msn_soap_start( ic, med, msn_soap_memlist_edit_build_request,
+	                                NULL,
+	                                msn_soap_memlist_edit_handle_response,
+	                                msn_soap_memlist_edit_free_data );
+}
+
 
 /* addressbook: Fetching the membership list (NOT address book) */
Index: protocols/msn/soap.h
===================================================================
--- protocols/msn/soap.h	(revision e5854a80111e337be01cf1e506073a231fac1c3d)
+++ protocols/msn/soap.h	(revision 193dc742d357bb604fff8921417c74ddf9e8729c)
@@ -190,5 +190,46 @@
 "</soap:Envelope>"
 
+#define SOAP_MEMLIST_ADD_ACTION "http://www.msn.com/webservices/AddressBook/AddMember"
+#define SOAP_MEMLIST_DEL_ACTION "http://www.msn.com/webservices/AddressBook/DeleteMember"
+
+#define SOAP_MEMLIST_EDIT_PAYLOAD \
+"<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \
+  "<soap:Header xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \
+    "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">" \
+      "<ApplicationId xmlns=\"http://www.msn.com/webservices/AddressBook\">CFE80F9D-180F-4399-82AB-413F33A1FA11</ApplicationId>" \
+      "<IsMigration xmlns=\"http://www.msn.com/webservices/AddressBook\">false</IsMigration>" \
+      "<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>" \
+      "<TicketToken>%s</TicketToken>" \
+    "</ABAuthHeader>" \
+  "</soap:Header>" \
+  "<soap:Body xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \
+  "<%sMember xmlns=\"http://www.msn.com/webservices/AddressBook\">" \
+   "<serviceHandle>" \
+    "<Id>0</Id>" \
+    "<Type>Messenger</Type>" \
+    "<ForeignId></ForeignId>" \
+   "</serviceHandle>" \
+   "<memberships>" \
+    "<Membership>" \
+     "<MemberRole>%s</MemberRole>" \
+     "<Members>" \
+      "<Member xsi:type=\"PassportMember\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" \
+       "<Type>Passport</Type>" \
+       "<State>Accepted</State>" \
+       "<PassportName>%s</PassportName>" \
+      "</Member>" \
+     "</Members>" \
+    "</Membership>" \
+   "</memberships>" \
+  "</%sMember>" \
+  "</soap:Body>" \
+"</soap:Envelope>"
+
 int msn_soap_memlist_request( struct im_connection *ic );
+int msn_soap_memlist_edit( struct im_connection *ic, const char *handle, gboolean add, int list );
 
 
