Index: protocols/jabber/iq.c
===================================================================
--- protocols/jabber/iq.c	(revision 33dc2618520409c0d52efff335fe299c26f6dd42)
+++ protocols/jabber/iq.c	(revision f0cb961652cbd639e89dcd88a86f20a2414146c4)
@@ -360,26 +360,18 @@
 	while( ( c = xt_find_node( c, "item" ) ) )
 	{
+		struct xt_node *group = xt_find_node( node->children, "group" );
 		char *jid = xt_find_attr( c, "jid" );
 		char *name = xt_find_attr( c, "name" );
 		char *sub = xt_find_attr( c, "subscription" );
 		
-		if( !jid || !sub )
-		{
-			/* Maybe warn. But how likely is this to happen in the first place? */
-		}
-		else if( initial )
-		{
-			if( ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) )
-				add_buddy( ic, NULL, jid, name );
-		}
-		else
-		{
-			/* This is a roster push item. Find out what changed exactly. */
+		if( jid && sub )
+		{
 			if( ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) )
 			{
-				if( find_buddy( ic, jid ) == NULL )
-					add_buddy( ic, NULL, jid, name );
-				else if( name )
-					serv_buddy_rename( ic, jid, name );
+				if( initial || imcb_find_buddy( ic, jid ) == NULL )
+					imcb_add_buddy( ic, jid, ( group && group->text_len ) ?
+					                           group->text : NULL );
+				
+				imcb_rename_buddy( ic, jid, name );
 			}
 			else if( strcmp( sub, "remove" ) == 0 )
Index: protocols/jabber/jabber_util.c
===================================================================
--- protocols/jabber/jabber_util.c	(revision 33dc2618520409c0d52efff335fe299c26f6dd42)
+++ protocols/jabber/jabber_util.c	(revision f0cb961652cbd639e89dcd88a86f20a2414146c4)
@@ -223,5 +223,5 @@
 	presence_send_request( bla->ic, bla->handle, "subscribed" );
 	
-	if( find_buddy( bla->ic, bla->handle ) == NULL )
+	if( imcb_find_buddy( bla->ic, bla->handle ) == NULL )
 		imcb_ask_add( bla->ic, bla->handle, NULL );
 	
@@ -371,5 +371,5 @@
 		}
 		
-		if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && find_buddy( ic, jid ) )
+		if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && imcb_find_buddy( ic, jid ) )
 		{
 			*s = '/';
@@ -391,5 +391,5 @@
 		if( bud == NULL )
 			/* No match. Create it now? */
-			return ( ( flags & GET_BUDDY_CREAT ) && find_buddy( ic, jid_ ) ) ?
+			return ( ( flags & GET_BUDDY_CREAT ) && imcb_find_buddy( ic, jid_ ) ) ?
 			           jabber_buddy_add( ic, jid_ ) : NULL;
 		else if( bud->resource && ( flags & GET_BUDDY_EXACT ) )
Index: protocols/msn/msn_util.c
===================================================================
--- protocols/msn/msn_util.c	(revision 33dc2618520409c0d52efff335fe299c26f6dd42)
+++ protocols/msn/msn_util.c	(revision f0cb961652cbd639e89dcd88a86f20a2414146c4)
@@ -94,5 +94,5 @@
 	msn_buddy_list_add( bla->ic, "AL", bla->handle, bla->realname );
 	
-	if( find_buddy( bla->ic, bla->handle ) == NULL )
+	if( imcb_find_buddy( bla->ic, bla->handle ) == NULL )
 		imcb_ask_add( bla->ic, bla->handle, NULL );
 	
Index: protocols/msn/ns.c
===================================================================
--- protocols/msn/ns.c	(revision 33dc2618520409c0d52efff335fe299c26f6dd42)
+++ protocols/msn/ns.c	(revision f0cb961652cbd639e89dcd88a86f20a2414146c4)
@@ -305,8 +305,9 @@
 			int num;
 			
-			if( cmd[4] != NULL && sscanf( cmd[4], "%d", &num ) == 1 )
+			if( cmd[4] != NULL && sscanf( cmd[4], "%d", &num ) == 1 && num < md->groupcount )
 				group = md->grouplist[num];
 			
-			add_buddy( ic, group, cmd[1], cmd[2] );
+			imcb_add_buddy( ic, cmd[1], group );
+			imcb_rename_buddy( ic, cmd[1], cmd[2] );
 		}
 		if( list & 2 ) /* AL */
@@ -391,5 +392,5 @@
 		
 		http_decode( cmd[4] );
-		serv_buddy_rename( ic, cmd[3], cmd[4] );
+		imcb_rename_buddy( ic, cmd[3], cmd[4] );
 		
 		st = msn_away_state_by_code( cmd[2] );
@@ -420,5 +421,5 @@
 		
 		http_decode( cmd[3] );
-		serv_buddy_rename( ic, cmd[2], cmd[3] );
+		imcb_rename_buddy( ic, cmd[2], cmd[3] );
 		
 		st = msn_away_state_by_code( cmd[1] );
@@ -482,17 +483,24 @@
 				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. */
+				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 );
+					return 1;
 			
 			for( l = ic->deny; l; l = l->next )
 				if( g_strcasecmp( l->data, cmd[4] ) == 0 )
-					return( 1 );
+					return 1;
 			
 			msn_buddy_ask( ic, cmd[4], cmd[5] );
+		}
+		else if( num_parts >= 6 && strcmp( cmd[2], "FL" ) == 0 )
+		{
+			http_decode( cmd[5] );
+			imcb_add_buddy( ic, cmd[4], NULL );
+			imcb_rename_buddy( ic, cmd[4], cmd[5] );
 		}
 	}
@@ -545,5 +553,5 @@
 			/* This is not supposed to happen, but let's handle it anyway... */
 			http_decode( cmd[4] );
-			serv_buddy_rename( ic, cmd[3], cmd[4] );
+			imcb_rename_buddy( ic, cmd[3], cmd[4] );
 		}
 	}
Index: protocols/nogaim.c
===================================================================
--- protocols/nogaim.c	(revision 33dc2618520409c0d52efff335fe299c26f6dd42)
+++ protocols/nogaim.c	(revision f0cb961652cbd639e89dcd88a86f20a2414146c4)
@@ -352,13 +352,9 @@
 /* list.c */
 
-void add_buddy( struct im_connection *ic, char *group, char *handle, char *realname )
+void imcb_add_buddy( struct im_connection *ic, char *handle, char *group )
 {
 	user_t *u;
-	char nick[MAX_NICK_LENGTH+1];
-	char *s;
+	char nick[MAX_NICK_LENGTH+1], *s;
 	irc_t *irc = ic->irc;
-	
-	if( set_getbool( &irc->set, "debug" ) && 0 ) /* This message is too useless */
-		imcb_log( ic, "Receiving user add from handle: %s", handle );
 	
 	if( user_findhandle( ic, handle ) )
@@ -369,14 +365,17 @@
 		return;
 		
-		/* Buddy seems to exist already. Let's ignore this request then... */
+		/* Buddy seems to exist already. Let's ignore this request then...
+		   Eventually subsequent calls to this function *should* be possible
+		   when a buddy is in multiple groups. But for now BitlBee doesn't
+		   even support groups so let's silently ignore this for now. */
 	}
 	
 	memset( nick, 0, MAX_NICK_LENGTH + 1 );
-	strcpy( nick, nick_get( ic->acc, handle, realname ) );
+	strcpy( nick, nick_get( ic->acc, handle, NULL ) );
 	
 	u = user_add( ic->irc, nick );
 	
-	if( !realname || !*realname ) realname = nick;
-	u->realname = g_strdup( realname );
+//	if( !realname || !*realname ) realname = nick;
+//	u->realname = g_strdup( realname );
 	
 	if( ( s = strchr( handle, '@' ) ) )
@@ -387,12 +386,5 @@
 	else if( ic->acc->server )
 	{
-		char *colon;
-		
-		if( ( colon = strchr( ic->acc->server, ':' ) ) )
-			u->host = g_strndup( ic->acc->server,
-			                     colon - ic->acc->server );
-		else
-			u->host = g_strdup( ic->acc->server );
-		
+		u->host = g_strdup( ic->acc->server );
 		u->user = g_strdup( handle );
 		
@@ -415,5 +407,5 @@
 }
 
-struct buddy *find_buddy( struct im_connection *ic, char *handle )
+struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle )
 {
 	static struct buddy b[1];
@@ -435,9 +427,9 @@
 
 
-void serv_buddy_rename( struct im_connection *ic, char *handle, char *realname )
+void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname )
 {
 	user_t *u = user_findhandle( ic, handle );
 	
-	if( !u ) return;
+	if( !u || !realname ) return;
 	
 	if( g_strcasecmp( u->realname, realname ) != 0 )
@@ -470,5 +462,5 @@
 {
 	data->ic->acc->prpl->add_buddy( data->ic, data->handle, NULL );
-	add_buddy( data->ic, NULL, data->handle, data->handle );
+	/* imcb_add_buddy( data->ic, NULL, data->handle, data->handle ); */
 	
 	return show_got_added_no( w, data );
@@ -505,5 +497,5 @@
 		if( g_strcasecmp( set_getstr( &ic->irc->set, "handle_unknown" ), "add" ) == 0 )
 		{
-			add_buddy( ic, NULL, (char*) handle, NULL );
+			imcb_add_buddy( ic, (char*) handle, NULL );
 			u = user_findhandle( ic, (char*) handle );
 		}
@@ -609,5 +601,5 @@
 			}
 			
-			add_buddy( ic, NULL, handle, NULL );
+			imcb_add_buddy( ic, handle, NULL );
 			u = user_findhandle( ic, handle );
 			u->is_private = private;
@@ -779,5 +771,5 @@
 	if( !u )
 	{
-		add_buddy( b->ic, NULL, handle, NULL );
+		imcb_add_buddy( b->ic, handle, NULL );
 		u = user_findhandle( b->ic, handle );
 	}
Index: protocols/nogaim.h
===================================================================
--- protocols/nogaim.h	(revision 33dc2618520409c0d52efff335fe299c26f6dd42)
+++ protocols/nogaim.h	(revision f0cb961652cbd639e89dcd88a86f20a2414146c4)
@@ -201,7 +201,8 @@
 
 /* Buddy management */
-G_MODULE_EXPORT void add_buddy( struct im_connection *ic, char *group, char *handle, char *realname );
-G_MODULE_EXPORT struct buddy *find_buddy( struct im_connection *ic, char *handle );
-G_MODULE_EXPORT void serv_buddy_rename( struct im_connection *ic, char *handle, char *realname );
+G_MODULE_EXPORT void imcb_add_buddy( struct im_connection *ic, char *handle, char *group );
+G_MODULE_EXPORT void imcb_remove_buddy( struct im_connection *ic, char *handle, char *group );
+G_MODULE_EXPORT struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle );
+G_MODULE_EXPORT void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname );
 
 /* Buddy activity */
Index: protocols/oscar/oscar.c
===================================================================
--- protocols/oscar/oscar.c	(revision 33dc2618520409c0d52efff335fe299c26f6dd42)
+++ protocols/oscar/oscar.c	(revision f0cb961652cbd639e89dcd88a86f20a2414146c4)
@@ -1119,5 +1119,5 @@
 	aim_ssi_auth_reply(od->sess, od->conn, uin, 1, "");
 	// aim_send_im_ch4(od->sess, uin, AIM_ICQMSG_AUTHGRANTED, &message);
-	if(find_buddy(data->ic, uin) == NULL)
+	if(imcb_find_buddy(data->ic, uin) == NULL)
 		imcb_ask_add(data->ic, uin, NULL);
 	
@@ -1875,5 +1875,5 @@
 	struct oscar_data *odata = (struct oscar_data *)g->proto_data;
 	if (odata->icq) {
-		struct buddy *budlight = find_buddy(g, who);
+		struct buddy *budlight = imcb_find_buddy(g, who);
 		if (budlight)
 			if ((budlight->uc & 0xff80) >> 7)
@@ -2013,5 +2013,5 @@
 		switch (curitem->type) {
 			case 0x0000: /* Buddy */
-				if ((curitem->name) && (!find_buddy(ic, curitem->name))) {
+				if ((curitem->name) && (!imcb_find_buddy(ic, curitem->name))) {
 					char *realname = NULL;
 
@@ -2019,8 +2019,10 @@
 						    realname = aim_gettlv_str(curitem->data, 0x0131, 1);
 						
-					add_buddy(ic, NULL, curitem->name, realname);
+					imcb_add_buddy(ic, curitem->name, NULL);
 					
-					if (realname)
-					    g_free(realname);
+					if (realname) {
+						imcb_rename_buddy(ic, curitem->name, realname);
+						g_free(realname);
+					}
 				}
 				break;
@@ -2105,5 +2107,9 @@
 		{
 			st = aimbs_get16( &fr->data );
-			if( st == 0x0E )
+			if( st == 0x00 )
+			{
+				imcb_add_buddy( sess->aux_data, list, NULL );
+			}
+			else if( st == 0x0E )
 			{
 				imcb_log( sess->aux_data, "Buddy %s can't be added without authorization, requesting authorization", list );
@@ -2111,4 +2117,8 @@
 				aim_ssi_auth_request( sess, fr->conn, list, "" );
 				aim_ssi_addbuddies( sess, fr->conn, OSCAR_GROUP, &list, 1, 1 );
+			}
+			else
+			{
+				imcb_error( sess->aux_data, "Error while adding buddy: 0x%04x", st );
 			}
 			list += strlen( list ) + 1;
Index: protocols/yahoo/libyahoo2.c
===================================================================
--- protocols/yahoo/libyahoo2.c	(revision 33dc2618520409c0d52efff335fe299c26f6dd42)
+++ protocols/yahoo/libyahoo2.c	(revision f0cb961652cbd639e89dcd88a86f20a2414146c4)
@@ -2403,10 +2403,17 @@
 		where = "Unknown";
 
-	bud = y_new0(struct yahoo_buddy, 1);
-	bud->id = strdup(who);
-	bud->group = strdup(where);
-	bud->real_name = NULL;
-
-	yd->buddies = y_list_append(yd->buddies, bud);
+	/* status: 0 == Successful, 1 == Error (does not exist), 2 == Already in list */
+	if( status == 0 ) {
+		bud = y_new0(struct yahoo_buddy, 1);
+		bud->id = strdup(who);
+		bud->group = strdup(where);
+		bud->real_name = NULL;
+		
+		yd->buddies = y_list_append(yd->buddies, bud);
+		
+		/* Possibly called already, but at least the call above doesn't
+		   seem to happen every time (not anytime I tried). */
+		YAHOO_CALLBACK(ext_yahoo_contact_added)(yd->client_id, me, who, NULL);
+	}
 
 /*	YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, who, status, NULL, (status==YAHOO_STATUS_AVAILABLE?0:1)); */
Index: protocols/yahoo/yahoo.c
===================================================================
--- protocols/yahoo/yahoo.c	(revision 33dc2618520409c0d52efff335fe299c26f6dd42)
+++ protocols/yahoo/yahoo.c	(revision f0cb961652cbd639e89dcd88a86f20a2414146c4)
@@ -532,5 +532,7 @@
 		}
 		
-		add_buddy( ic, b->group, b->id, b->real_name );
+		imcb_add_buddy( ic, b->id, b->group );
+		imcb_rename_buddy( ic, b->id, b->real_name );
+		
 		bl = bl->next;
 	}
@@ -904,4 +906,7 @@
 void ext_yahoo_contact_added( int id, const char *myid, const char *who, const char *msg )
 {
+	/* Groups schmoups. If I want to handle groups properly I can get the
+	   buddy data from some internal libyahoo2 structure. */
+	imcb_add_buddy( byahoo_get_ic_by_id( id ), (char*) who, NULL );
 }
 
Index: root_commands.c
===================================================================
--- root_commands.c	(revision 33dc2618520409c0d52efff335fe299c26f6dd42)
+++ root_commands.c	(revision f0cb961652cbd639e89dcd88a86f20a2414146c4)
@@ -437,9 +437,9 @@
 {
 	account_t *a;
-	int add_for_real = 1;
+	int add_on_server = 1;
 	
 	if( g_strcasecmp( cmd[1], "-tmp" ) == 0 )
 	{
-		add_for_real = 0;
+		add_on_server = 0;
 		cmd ++;		/* So evil... :-D */
 	}
@@ -476,10 +476,10 @@
 	/* By making this optional, you can talk to people without having to
 	   add them to your *real* (server-side) contact list. */
-	if( add_for_real )
+	if( add_on_server )
 		a->ic->acc->prpl->add_buddy( a->ic, cmd[2], NULL );
-		
-	add_buddy( a->ic, NULL, cmd[2], cmd[2] );
-	
-	irc_usermsg( irc, "User `%s' added to your contact list as `%s'", cmd[2], user_findhandle( a->ic, cmd[2] )->nick );
+	
+	/* add_buddy( a->ic, NULL, cmd[2], cmd[2] ); */
+	
+	irc_usermsg( irc, "Adding `%s' to your contact list", cmd[2]  );
 }
 
