Index: protocols/msn/msn.h
===================================================================
--- protocols/msn/msn.h	(revision 07874bef9e9c4e6ace44e4d0605ce1aec89cad74)
+++ protocols/msn/msn.h	(revision e5854a80111e337be01cf1e506073a231fac1c3d)
@@ -203,5 +203,5 @@
 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 );
-void msn_buddy_ask( struct im_connection *ic, char *handle, char *realname );
+void msn_buddy_ask( bee_user_t *bu );
 char *msn_findheader( char *text, char *header, int len );
 char **msn_linesplit( char *line );
Index: protocols/msn/msn_util.c
===================================================================
--- protocols/msn/msn_util.c	(revision 07874bef9e9c4e6ace44e4d0605ce1aec89cad74)
+++ protocols/msn/msn_util.c	(revision e5854a80111e337be01cf1e506073a231fac1c3d)
@@ -172,17 +172,22 @@
 }
 
-void msn_buddy_ask( struct im_connection *ic, char *handle, char *realname )
-{
-	struct msn_buddy_ask_data *bla = g_new0( struct msn_buddy_ask_data, 1 );
+void msn_buddy_ask( bee_user_t *bu )
+{
+	struct msn_buddy_ask_data *bla;
+	struct msn_buddy_data *bd = bu->data;
 	char buf[1024];
 	
-	bla->ic = ic;
-	bla->handle = g_strdup( handle );
-	bla->realname = g_strdup( realname );
+	if( ( bd->flags & 30 ) != 8 && ( bd->flags & 30 ) != 16 )
+		return;
+	
+	bla = g_new0( struct msn_buddy_ask_data, 1 );
+	bla->ic = bu->ic;
+	bla->handle = g_strdup( bu->handle );
+	bla->realname = g_strdup( bu->fullname );
 	
 	g_snprintf( buf, sizeof( buf ),
 	            "The user %s (%s) wants to add you to his/her buddy list.",
-	            handle, realname );
-	imcb_ask( ic, buf, bla, msn_buddy_ask_yes, msn_buddy_ask_no );
+	            bu->handle, bu->fullname );
+	imcb_ask( bu->ic, buf, bla, msn_buddy_ask_yes, msn_buddy_ask_no );
 }
 
Index: protocols/msn/ns.c
===================================================================
--- protocols/msn/ns.c	(revision 07874bef9e9c4e6ace44e4d0605ce1aec89cad74)
+++ protocols/msn/ns.c	(revision e5854a80111e337be01cf1e506073a231fac1c3d)
@@ -279,4 +279,8 @@
 			msn_write( ic, buf, strlen( buf ) );
 		}
+		else if( num_parts >= 3 )
+		{
+			md->handler->msglen = atoi( cmd[2] );
+		}
 	}
 	else if( strcmp( cmd[0], "PRP" ) == 0 )
@@ -412,44 +416,4 @@
 		}
 	}
-	else if( strcmp( cmd[0], "ADD" ) == 0 )
-	{
-		if( num_parts >= 6 && strcmp( cmd[2], "RL" ) == 0 )
-		{
-			GSList *l;
-			
-			http_decode( cmd[5] );
-			
-			if( strchr( cmd[4], '@' ) == NULL )
-			{
-				imcb_error( ic, "Syntax error" );
-				imc_logout( ic, TRUE );
-				return 0;
-			}
-			
-			/* We got added by someone. If we don't have this
-			   person in permit/deny yet, inform the user. */
-			for( l = ic->permit; l; l = l->next )
-				if( g_strcasecmp( l->data, cmd[4] ) == 0 )
-					return 1;
-			
-			for( l = ic->deny; l; l = l->next )
-				if( g_strcasecmp( l->data, cmd[4] ) == 0 )
-					return 1;
-			
-			msn_buddy_ask( ic, cmd[4], cmd[5] );
-		}
-		else if( num_parts >= 6 && strcmp( cmd[2], "FL" ) == 0 )
-		{
-			const char *group = NULL;
-			int num;
-			
-			if( cmd[6] != NULL && sscanf( cmd[6], "%d", &num ) == 1 && num < md->groupcount )
-				group = md->grouplist[num];
-			
-			http_decode( cmd[5] );
-			imcb_add_buddy( ic, cmd[4], group );
-			imcb_rename_buddy( ic, cmd[4], cmd[5] );
-		}
-	}
 	else if( strcmp( cmd[0], "OUT" ) == 0 )
 	{
@@ -486,4 +450,5 @@
 		}
 	}
+#if 0
 	else if( strcmp( cmd[0], "ADG" ) == 0 )
 	{
@@ -530,4 +495,5 @@
 		}
 	}
+#endif
 	else if( strcmp( cmd[0], "GCF" ) == 0 )
 	{
@@ -538,5 +504,5 @@
 	else if( strcmp( cmd[0], "UBX" ) == 0 )
 	{
-		/* Status message. Parser coming soon. */
+		/* Status message. */
 		if( num_parts >= 4 )
 			md->handler->msglen = atoi( cmd[3] );
@@ -544,8 +510,8 @@
 	else if( strcmp( cmd[0], "NOT" ) == 0 )
 	{
-		/* Some kind of notification, not sure if it still exists
-		   but we have to skip the payload or stuff breaks. */
-		if( num_parts >= 3 )
-			md->handler->msglen = atoi( cmd[2] );
+		/* Some kind of notification, poorly documented but
+		   apparently used to announce address book changes. */
+		if( num_parts >= 2 )
+			md->handler->msglen = atoi( cmd[1] );
 	}
 	else if( isdigit( cmd[0][0] ) )
@@ -670,4 +636,54 @@
 		imcb_buddy_status_msg( ic, cmd[1], psm_text );
 		xt_free_node( psm );
+	}
+	else if( strcmp( cmd[0], "ADL" ) == 0 )
+	{
+		struct xt_node *adl, *d, *c;
+		
+		if( !( adl = xt_from_string( msg ) ) )
+			return 1;
+		
+		for( d = adl->children; d; d = d->next )
+		{
+			char *dn;
+			if( strcmp( d->name, "d" ) != 0 ||
+			    ( dn = xt_find_attr( d, "n" ) ) == NULL )
+				continue;
+			for( c = d->children; c; c = c->next )
+			{
+				bee_user_t *bu;
+				struct msn_buddy_data *bd;
+				char *cn, *handle, *f, *l;
+				int flags;
+				
+				if( strcmp( c->name, "c" ) != 0 ||
+				    ( l = xt_find_attr( c, "l" ) ) == NULL ||
+				    ( cn = xt_find_attr( c, "n" ) ) == NULL )
+					continue;
+				
+				handle = g_strdup_printf( "%s@%s", cn, dn );
+				if( !( ( bu = bee_user_by_handle( ic->bee, ic, handle ) ) ||
+				       ( bu = bee_user_new( ic->bee, ic, handle, 0 ) ) ) )
+				{
+					g_free( handle );
+					continue;
+				}
+				g_free( handle );
+				bd = bu->data;
+				
+				if( ( f = xt_find_attr( c, "f" ) ) )
+				{
+					http_decode( f );
+					imcb_rename_buddy( ic, bu->handle, f );
+				}
+				
+				flags = atoi( l ) & 15;
+				if( bd->flags != flags )
+				{
+					bd->flags = flags;
+					msn_buddy_ask( bu );
+				}
+			}
+		}
 	}
 	
@@ -718,4 +734,7 @@
 	char l[4];
 	
+	if( ( bd->flags & 7 ) == 0 )
+		return FALSE;
+	
 	strcpy( handle, bu->handle );
 	if( ( domain = strchr( handle, '@' ) ) == NULL ) /* WTF */
Index: protocols/msn/soap.c
===================================================================
--- protocols/msn/soap.c	(revision 07874bef9e9c4e6ace44e4d0605ce1aec89cad74)
+++ protocols/msn/soap.c	(revision e5854a80111e337be01cf1e506073a231fac1c3d)
@@ -477,7 +477,15 @@
 		bd->flags |= MSN_BUDDY_BL;
 	else if( strcmp( role, "Reverse" ) == 0 )
+	{
 		bd->flags |= MSN_BUDDY_RL;
+		msn_buddy_ask( bu );
+	}
 	else if( strcmp( role, "Pending" ) == 0 )
+	{
 		bd->flags |= MSN_BUDDY_PL;
+		msn_buddy_ask( bu );
+	}
+	
+	printf( "%s %d\n", handle, bd->flags );
 	
 	return XT_HANDLED;
