Index: protocols/jabber/io.c
===================================================================
--- protocols/jabber/io.c	(revision 842cd8dbfb98b61af33b5fe481364c3cfbeaca04)
+++ protocols/jabber/io.c	(revision 638feab58aebc97d646820dd1bc9b8d9fbeec29d)
@@ -375,37 +375,11 @@
 	
 	if( ( c = xt_find_node( node->children, "bind" ) ) )
-	{
-		reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &ic->acc->set, "resource" ), NULL ) );
-		xt_add_attr( reply, "xmlns", XMLNS_BIND );
-		reply = jabber_make_packet( "iq", "set", NULL, reply );
-		jabber_cache_add( ic, reply, jabber_pkt_bind_sess );
-		
-		if( !jabber_write_packet( ic, reply ) )
-			return XT_ABORT;
-		
-		jd->flags |= JFLAG_WAIT_BIND;
-	}
+		jd->flags |= JFLAG_WANT_BIND;
 	
 	if( ( c = xt_find_node( node->children, "session" ) ) )
-	{
-		reply = xt_new_node( "session", NULL, NULL );
-		xt_add_attr( reply, "xmlns", XMLNS_SESSION );
-		reply = jabber_make_packet( "iq", "set", NULL, reply );
-		jabber_cache_add( ic, reply, jabber_pkt_bind_sess );
-		
-		if( !jabber_write_packet( ic, reply ) )
-			return XT_ABORT;
-		
-		jd->flags |= JFLAG_WAIT_SESSION;
-	}
-	
-	/* This flag is already set if we authenticated via SASL, so now
-	   we can resume the session in the new stream, if we don't have
-	   to bind/initialize the session. */
-	if( jd->flags & JFLAG_AUTHENTICATED && ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )
-	{
-		if( !jabber_get_roster( ic ) )
-			return XT_ABORT;
-	}
+		jd->flags |= JFLAG_WANT_SESSION;
+	
+	if( jd->flags & JFLAG_AUTHENTICATED )
+		return jabber_pkt_bind_sess( ic, NULL, NULL );
 	
 	return XT_HANDLED;
@@ -441,4 +415,5 @@
 	imcb_log( ic, "Converting stream to TLS" );
 	
+	jd->flags |= JFLAG_STARTTLS_DONE;
 	jd->ssl = ssl_starttls( jd->fd, jabber_connected_ssl, ic );
 	
@@ -531,7 +506,8 @@
 		jd->r_inpa = b_input_add( jd->fd, GAIM_INPUT_READ, jabber_read_callback, ic );
 	
-	greet = g_strdup_printf( "<?xml version='1.0' ?>"
-	                         "<stream:stream to=\"%s\" xmlns=\"jabber:client\" "
-	                          "xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">", jd->server );
+	greet = g_strdup_printf( "%s<stream:stream to=\"%s\" xmlns=\"jabber:client\" "
+	                          "xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">", 
+	                          ( jd->flags & JFLAG_STARTTLS_DONE ) ? "" : "<?xml version='1.0' ?>",
+	                          jd->server );
 	
 	st = jabber_write( ic, greet, strlen( greet ) );
Index: protocols/jabber/iq.c
===================================================================
--- protocols/jabber/iq.c	(revision 842cd8dbfb98b61af33b5fe481364c3cfbeaca04)
+++ protocols/jabber/iq.c	(revision 638feab58aebc97d646820dd1bc9b8d9fbeec29d)
@@ -298,8 +298,8 @@
 {
 	struct jabber_data *jd = ic->proto_data;
-	struct xt_node *c;
+	struct xt_node *c, *reply = NULL;
 	char *s;
 	
-	if( ( c = xt_find_node( node->children, "bind" ) ) )
+	if( node && ( c = xt_find_node( node->children, "bind" ) ) )
 	{
 		c = xt_find_node( c->children, "jid" );
@@ -307,13 +307,28 @@
 		    strcmp( s + 1, set_getstr( &ic->acc->set, "resource" ) ) != 0 )
 			imcb_log( ic, "Server changed session resource string to `%s'", s + 1 );
-		
-		jd->flags &= ~JFLAG_WAIT_BIND;
-	}
-	else
-	{
-		jd->flags &= ~JFLAG_WAIT_SESSION;
-	}
-	
-	if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )
+	}
+	
+	if( jd->flags & JFLAG_WANT_BIND )
+	{
+		reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &ic->acc->set, "resource" ), NULL ) );
+		xt_add_attr( reply, "xmlns", XMLNS_BIND );
+		jd->flags &= ~JFLAG_WANT_BIND;
+	}
+	else if( jd->flags & JFLAG_WANT_SESSION )
+	{
+		reply = xt_new_node( "session", NULL, NULL );
+		xt_add_attr( reply, "xmlns", XMLNS_SESSION );
+		jd->flags &= ~JFLAG_WANT_SESSION;
+	}
+	
+	if( reply != NULL )
+	{
+		reply = jabber_make_packet( "iq", "set", NULL, reply );
+		jabber_cache_add( ic, reply, jabber_pkt_bind_sess );
+		
+		if( !jabber_write_packet( ic, reply ) )
+			return XT_ABORT;
+	}
+	else if( ( jd->flags & ( JFLAG_WANT_BIND | JFLAG_WANT_SESSION ) ) == 0 )
 	{
 		if( !jabber_get_roster( ic ) )
Index: protocols/jabber/jabber.h
===================================================================
--- protocols/jabber/jabber.h	(revision 842cd8dbfb98b61af33b5fe481364c3cfbeaca04)
+++ protocols/jabber/jabber.h	(revision 638feab58aebc97d646820dd1bc9b8d9fbeec29d)
@@ -40,10 +40,11 @@
 	JFLAG_STREAM_RESTART = 4,       /* Set when we want to restart the stream (after
 	                                   SASL or TLS). */
-	JFLAG_WAIT_SESSION = 8,	        /* Set if we sent a <session> tag and need a reply
+	JFLAG_WANT_SESSION = 8,	        /* Set if the server wants a <session/> tag
 	                                   before we continue. */
-	JFLAG_WAIT_BIND = 16,           /* ... for <bind> tag. */
+	JFLAG_WANT_BIND = 16,           /* ... for <bind> tag. */
 	JFLAG_WANT_TYPING = 32,         /* Set if we ever sent a typing notification, this
 	                                   activates all XEP-85 related code. */
 	JFLAG_XMLCONSOLE = 64,          /* If the user added an xmlconsole buddy. */
+	JFLAG_STARTTLS_DONE = 128,      /* If a plaintext session was converted to TLS. */
 } jabber_flags_t;
 
Index: protocols/msn/msn.c
===================================================================
--- protocols/msn/msn.c	(revision 842cd8dbfb98b61af33b5fe481364c3cfbeaca04)
+++ protocols/msn/msn.c	(revision 638feab58aebc97d646820dd1bc9b8d9fbeec29d)
@@ -26,4 +26,8 @@
 #include "nogaim.h"
 #include "msn.h"
+
+int msn_chat_id;
+GSList *msn_connections;
+GSList *msn_switchboards;
 
 static char *msn_set_display_name( set_t *set, char *value );
Index: protocols/msn/msn.h
===================================================================
--- protocols/msn/msn.h	(revision 842cd8dbfb98b61af33b5fe481364c3cfbeaca04)
+++ protocols/msn/msn.h	(revision 638feab58aebc97d646820dd1bc9b8d9fbeec29d)
@@ -135,5 +135,5 @@
 #define STATUS_SB_CHAT_SPARE	8	/* Same, but also for groupchats (not used yet). */
 
-int msn_chat_id;
+extern int msn_chat_id;
 extern const struct msn_away_state msn_away_state_list[];
 extern const struct msn_status_code msn_status_code_list[];
@@ -144,6 +144,6 @@
    connection), the callback should check whether it's still listed here
    before doing *anything* else. */
-GSList *msn_connections;
-GSList *msn_switchboards;
+extern GSList *msn_connections;
+extern GSList *msn_switchboards;
 
 /* ns.c */
Index: protocols/msn/ns.c
===================================================================
--- protocols/msn/ns.c	(revision 842cd8dbfb98b61af33b5fe481364c3cfbeaca04)
+++ protocols/msn/ns.c	(revision 638feab58aebc97d646820dd1bc9b8d9fbeec29d)
@@ -229,17 +229,24 @@
 			}
 		}
-		else if( num_parts == 7 && strcmp( cmd[2], "OK" ) == 0 )
+		else if( num_parts >= 7 && strcmp( cmd[2], "OK" ) == 0 )
 		{
 			set_t *s;
 			
-			http_decode( cmd[4] );
-			
-			strncpy( ic->displayname, cmd[4], sizeof( ic->displayname ) );
-			ic->displayname[sizeof(ic->displayname)-1] = 0;
-			
-			if( ( s = set_find( &ic->acc->set, "display_name" ) ) )
-			{
-				g_free( s->value );
-				s->value = g_strdup( cmd[4] );
+			if( num_parts == 7 )
+			{
+				http_decode( cmd[4] );
+				
+				strncpy( ic->displayname, cmd[4], sizeof( ic->displayname ) );
+				ic->displayname[sizeof(ic->displayname)-1] = 0;
+				
+				if( ( s = set_find( &ic->acc->set, "display_name" ) ) )
+				{
+					g_free( s->value );
+					s->value = g_strdup( cmd[4] );
+				}
+			}
+			else
+			{
+				imcb_log( ic, "Warning: Friendly name in server response was corrupted" );
 			}
 			
Index: protocols/nogaim.c
===================================================================
--- protocols/nogaim.c	(revision 842cd8dbfb98b61af33b5fe481364c3cfbeaca04)
+++ protocols/nogaim.c	(revision 638feab58aebc97d646820dd1bc9b8d9fbeec29d)
@@ -98,5 +98,17 @@
 void register_protocol (struct prpl *p)
 {
-	protocols = g_list_append(protocols, p);
+	int i;
+	gboolean refused = global.conf->protocols != NULL;
+ 
+	for (i = 0; global.conf->protocols && global.conf->protocols[i]; i++)
+ 	{
+ 		if (g_strcasecmp(p->name, global.conf->protocols[i]) == 0)
+			refused = FALSE;
+ 	}
+
+	if (refused)
+		log_message(LOGLVL_WARNING, "Protocol %s disabled\n", p->name);
+	else
+		protocols = g_list_append(protocols, p);
 }
 
@@ -371,5 +383,5 @@
 /* list.c */
 
-void imcb_add_buddy( struct im_connection *ic, char *handle, char *group )
+void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group )
 {
 	user_t *u;
@@ -445,7 +457,8 @@
 }
 
-void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname )
+void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *realname )
 {
 	user_t *u = user_findhandle( ic, handle );
+	char *set;
 	
 	if( !u || !realname ) return;
@@ -460,7 +473,24 @@
 			imcb_log( ic, "User `%s' changed name to `%s'", u->nick, u->realname );
 	}
-}
-
-void imcb_remove_buddy( struct im_connection *ic, char *handle, char *group )
+	
+	set = set_getstr( &ic->acc->set, "nick_source" );
+	if( strcmp( set, "handle" ) != 0 )
+	{
+		char *name = g_strdup( realname );
+		
+		if( strcmp( set, "first_name" ) == 0 )
+		{
+			int i;
+			for( i = 0; name[i] && !isspace( name[i] ); i ++ ) {}
+			name[i] = '\0';
+		}
+		
+		imcb_buddy_nick_hint( ic, handle, name );
+		
+		g_free( name );
+	}
+}
+
+void imcb_remove_buddy( struct im_connection *ic, const char *handle, char *group )
 {
 	user_t *u;
@@ -472,5 +502,5 @@
 /* Mainly meant for ICQ (and now also for Jabber conferences) to allow IM
    modules to suggest a nickname for a handle. */
-void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick )
+void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick )
 {
 	user_t *u = user_findhandle( ic, handle );
@@ -617,9 +647,7 @@
 	oo = u->online;
 	
-	if( u->away )
-	{
-		g_free( u->away );
-		u->away = NULL;
-	}
+	g_free( u->away );
+	g_free( u->status_msg );
+	u->away = u->status_msg = NULL;
 	
 	if( ( flags & OPT_LOGGED_IN ) && !u->online )
@@ -659,5 +687,8 @@
 		}
 	}
-	/* else waste_any_state_information_for_now(); */
+	else
+	{
+		u->status_msg = g_strdup( message );
+	}
 	
 	/* LISPy... */
@@ -684,5 +715,5 @@
 }
 
-void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, uint32_t flags, time_t sent_at )
+void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at )
 {
 	irc_t *irc = ic->irc;
@@ -817,5 +848,5 @@
 }
 
-void imcb_chat_msg( struct groupchat *c, char *who, char *msg, uint32_t flags, time_t sent_at )
+void imcb_chat_msg( struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at )
 {
 	struct im_connection *ic = c->ic;
@@ -889,5 +920,5 @@
 /* buddy_chat.c */
 
-void imcb_chat_add_buddy( struct groupchat *b, char *handle )
+void imcb_chat_add_buddy( struct groupchat *b, const char *handle )
 {
 	user_t *u = user_findhandle( b->ic, handle );
@@ -924,5 +955,5 @@
 
 /* This function is one BIG hack... :-( EREWRITE */
-void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason )
+void imcb_chat_remove_buddy( struct groupchat *b, const char *handle, const char *reason )
 {
 	user_t *u;
Index: protocols/nogaim.h
===================================================================
--- protocols/nogaim.h	(revision 842cd8dbfb98b61af33b5fe481364c3cfbeaca04)
+++ protocols/nogaim.h	(revision 638feab58aebc97d646820dd1bc9b8d9fbeec29d)
@@ -275,9 +275,9 @@
  * user, usually after a login, or if the user added a buddy and the IM
  * server confirms that the add was successful. Don't forget to do this! */
-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 void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group );
+G_MODULE_EXPORT void imcb_remove_buddy( struct im_connection *ic, const 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 );
-G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick );
+G_MODULE_EXPORT void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *realname );
+G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick );
 
 /* Buddy activity */
@@ -289,5 +289,5 @@
 /* Not implemented yet! */ G_MODULE_EXPORT void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle );
 /* Call when a handle says something. 'flags' and 'sent_at may be just 0. */
-G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, uint32_t flags, time_t sent_at );
+G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at );
 G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, char *handle, uint32_t flags );
 G_MODULE_EXPORT void imcb_clean_handle( struct im_connection *ic, char *handle );
@@ -302,9 +302,9 @@
  *   user, too. */
 G_MODULE_EXPORT struct groupchat *imcb_chat_new( struct im_connection *ic, const char *handle );
-G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, char *handle );
+G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, const char *handle );
 /* To remove a handle from a group chat. Reason can be NULL. */
-G_MODULE_EXPORT void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason );
+G_MODULE_EXPORT void imcb_chat_remove_buddy( struct groupchat *b, const char *handle, const char *reason );
 /* To tell BitlBee 'who' said 'msg' in 'c'. 'flags' and 'sent_at' can be 0. */
-G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, char *who, char *msg, uint32_t flags, time_t sent_at );
+G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at );
 /* System messages specific to a groupchat, so they can be displayed in the right context. */
 G_MODULE_EXPORT void imcb_chat_log( struct groupchat *c, char *format, ... ) G_GNUC_PRINTF( 2, 3 );
Index: protocols/yahoo/libyahoo2.c
===================================================================
--- protocols/yahoo/libyahoo2.c	(revision 842cd8dbfb98b61af33b5fe481364c3cfbeaca04)
+++ protocols/yahoo/libyahoo2.c	(revision 638feab58aebc97d646820dd1bc9b8d9fbeec29d)
@@ -855,53 +855,4 @@
 }
 
-static YList * bud_str2list(char *rawlist)
-{
-	YList * l = NULL;
-
-	char **lines;
-	char **split;
-	char **buddies;
-	char **tmp, **bud;
-
-	lines = y_strsplit(rawlist, "\n", -1);
-	for (tmp = lines; *tmp; tmp++) {
-		struct yahoo_buddy *newbud;
-
-		split = y_strsplit(*tmp, ":", 2);
-		if (!split)
-			continue;
-		if (!split[0] || !split[1]) {
-			y_strfreev(split);
-			continue;
-		}
-		buddies = y_strsplit(split[1], ",", -1);
-
-		for (bud = buddies; bud && *bud; bud++) {
-			newbud = y_new0(struct yahoo_buddy, 1);
-			newbud->id = strdup(*bud);
-			newbud->group = strdup(split[0]);
-
-			if(y_list_find_custom(l, newbud, is_same_bud)) {
-				FREE(newbud->id);
-				FREE(newbud->group);
-				FREE(newbud);
-				continue;
-			}
-
-			newbud->real_name = NULL;
-
-			l = y_list_append(l, newbud);
-
-			NOTICE(("Added buddy %s to group %s", newbud->id, newbud->group));
-		}
-
-		y_strfreev(buddies);
-		y_strfreev(split);
-	}
-	y_strfreev(lines);
-
-	return l;
-}
-
 static char * getcookie(char *rawcookie)
 {
@@ -1360,38 +1311,25 @@
 }
 
-
-static void yahoo_process_status(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
+static void yahoo_process_status(struct yahoo_input_data *yid,
+	struct yahoo_packet *pkt)
 {
 	YList *l;
 	struct yahoo_data *yd = yid->yd;
 
-	struct user
-	{
-		char *name;	/* 7	name */
-		int   state;	/* 10	state */
-		int   flags;	/* 13	flags, bit 0 = pager, bit 1 = chat, bit 2 = game */
-		int   mobile;	/* 60	mobile */
-		char *msg;	/* 19	custom status message */
-		int   away;	/* 47	away (or invisible)*/
-		int   buddy_session;	/* 11	state */
-		int   f17;	/* 17	in chat? then what about flags? */
-		int   idle;	/* 137	seconds idle */
-		int   f138;	/* 138	state */
-		char *f184;	/* 184	state */
-		int   f192;	/* 192	state */
-		int   f10001;	/* 10001	state */
-		int   f10002;	/* 10002	state */
-		int   f198;	/* 198	state */
-		char *f197;	/* 197	state */
-		char *f205;	/* 205	state */
-		int   f213;	/* 213	state */
-	} *u;
+	struct yahoo_process_status_entry *u;
 
 	YList *users = 0;
-	
+
 	if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) {
-		YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_DUPL, NULL);
-		return;
-	}
+		YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id,
+			YAHOO_LOGIN_DUPL, NULL);
+		return;
+	}
+
+	/* Status updates may be spread accross multiple packets and not
+	   even on buddy boundaries, so keeping some state is important.
+	   So, continue where we left off, and only add a user entry to
+	   the list once it's complete (301-315 End buddy). */
+	u = yd->half_user;
 
 	for (l = pkt->hash; l; l = l->next) {
@@ -1399,99 +1337,126 @@
 
 		switch (pair->key) {
-		case 0: /* we won't actually do anything with this */
+		case 300:	/* Begin buddy */
+			if (!strcmp(pair->value, "315") && !u) {
+				u = yd->half_user = y_new0(struct yahoo_process_status_entry, 1);
+			}
+			break;
+		case 301:	/* End buddy */
+			if (!strcmp(pair->value, "315") && u) {
+				/* Sometimes user info comes in an odd format with no
+				   "begin buddy" but *with* an "end buddy". Don't add
+				   it twice. */
+				if (!y_list_find(users, u))
+					users = y_list_prepend(users, u);
+				u = yd->half_user = NULL;
+			}
+			break;
+		case 0:	/* we won't actually do anything with this */
 			NOTICE(("key %d:%s", pair->key, pair->value));
 			break;
-		case 1: /* we don't get the full buddy list here. */
+		case 1:	/* we don't get the full buddy list here. */
 			if (!yd->logged_in) {
-				yd->logged_in = TRUE;
-				if(yd->current_status < 0)
+				yd->logged_in = 1;
+				if (yd->current_status < 0)
 					yd->current_status = yd->initial_status;
-				YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_OK, NULL);
+				YAHOO_CALLBACK(ext_yahoo_login_response) (yd->
+					client_id, YAHOO_LOGIN_OK, NULL);
 			}
 			break;
-		case 8: /* how many online buddies we have */
+		case 8:	/* how many online buddies we have */
 			NOTICE(("key %d:%s", pair->key, pair->value));
 			break;
-		case 7: /* the current buddy */
-			u = y_new0(struct user, 1);
+		case 7:	/* the current buddy */
+			if (!u) {
+				/* This will only happen in case of a single level message */
+				u = y_new0(struct yahoo_process_status_entry, 1);
+				users = y_list_prepend(users, u);
+			}
 			u->name = pair->value;
-			users = y_list_prepend(users, u);
-			break;
-		case 10: /* state */
-			((struct user*)users->data)->state = strtol(pair->value, NULL, 10);
-			break;
-		case 19: /* custom status message */
-			((struct user*)users->data)->msg = pair->value;
-			break;
-		case 47: /* is it an away message or not */
-			((struct user*)users->data)->away = atoi(pair->value);
-			break;
-		case 137: /* seconds idle */
-			((struct user*)users->data)->idle = atoi(pair->value);
-			break;
-		case 11: /* this is the buddy's session id */
-			((struct user*)users->data)->buddy_session = atoi(pair->value);
-			break;
-		case 17: /* in chat? */
-			((struct user*)users->data)->f17 = atoi(pair->value);
-			break;
-		case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */
-			((struct user*)users->data)->flags = atoi(pair->value);
-			break;
-		case 60: /* SMS -> 1 MOBILE USER */
+			break;
+		case 10:	/* state */
+			u->state = strtol(pair->value, NULL, 10);
+			break;
+		case 19:	/* custom status message */
+			u->msg = pair->value;
+			break;
+		case 47:	/* is it an away message or not. Not applicable for YMSG16 anymore */
+			u->away = atoi(pair->value);
+			break;
+		case 137:	/* seconds idle */
+			u->idle = atoi(pair->value);
+			break;
+		case 11:	/* this is the buddy's session id */
+			u->buddy_session = atoi(pair->value);
+			break;
+		case 17:	/* in chat? */
+			u->f17 = atoi(pair->value);
+			break;
+		case 13:	/* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */
+			u->flags = atoi(pair->value);
+			break;
+		case 60:	/* SMS -> 1 MOBILE USER */
 			/* sometimes going offline makes this 2, but invisible never sends it */
-			((struct user*)users->data)->mobile = atoi(pair->value);
+			u->mobile = atoi(pair->value);
 			break;
 		case 138:
-			((struct user*)users->data)->f138 = atoi(pair->value);
+			u->f138 = atoi(pair->value);
 			break;
 		case 184:
-			((struct user*)users->data)->f184 = pair->value;
+			u->f184 = pair->value;
 			break;
 		case 192:
-			((struct user*)users->data)->f192 = atoi(pair->value);
+			u->f192 = atoi(pair->value);
 			break;
 		case 10001:
-			((struct user*)users->data)->f10001 = atoi(pair->value);
+			u->f10001 = atoi(pair->value);
 			break;
 		case 10002:
-			((struct user*)users->data)->f10002 = atoi(pair->value);
+			u->f10002 = atoi(pair->value);
 			break;
 		case 198:
-			((struct user*)users->data)->f198 = atoi(pair->value);
+			u->f198 = atoi(pair->value);
 			break;
 		case 197:
-			((struct user*)users->data)->f197 = pair->value;
+			u->f197 = pair->value;
 			break;
 		case 205:
-			((struct user*)users->data)->f205 = pair->value;
+			u->f205 = pair->value;
 			break;
 		case 213:
-			((struct user*)users->data)->f213 = atoi(pair->value);
-			break;
-		case 16: /* Custom error message */
-			YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, pair->value, 0, E_CUSTOM);
+			u->f213 = atoi(pair->value);
+			break;
+		case 16:	/* Custom error message */
+			YAHOO_CALLBACK(ext_yahoo_error) (yd->client_id,
+				pair->value, 0, E_CUSTOM);
 			break;
 		default:
-			WARNING(("unknown status key %d:%s", pair->key, pair->value));
-			break;
-		}
-	}
-	
+			WARNING(("unknown status key %d:%s", pair->key,
+					pair->value));
+			break;
+		}
+	}
+
 	while (users) {
 		YList *t = users;
-		struct user *u = users->data;
+		struct yahoo_process_status_entry *u = users->data;
 
 		if (u->name != NULL) {
-			if (pkt->service == YAHOO_SERVICE_LOGOFF) { /* || u->flags == 0) { Not in YMSG16 */
-				YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, u->name, YAHOO_STATUS_OFFLINE, NULL, 1, 0, 0);
+			if (pkt->service ==
+				YAHOO_SERVICE_LOGOFF
+				/*|| u->flags == 0 No flags for YMSG16 */ ) {
+				YAHOO_CALLBACK(ext_yahoo_status_changed) (yd->
+					client_id, u->name,
+					YAHOO_STATUS_OFFLINE, NULL, 1, 0, 0);
 			} else {
 				/* Key 47 always seems to be 1 for YMSG16 */
-				if(!u->state)
+				if (!u->state)
 					u->away = 0;
 				else
 					u->away = 1;
 
-				YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, u->name, u->state, u->msg, u->away, u->idle, u->mobile);
+				YAHOO_CALLBACK(ext_yahoo_status_changed) (yd->
+					client_id, u->name, u->state, u->msg,
+					u->away, u->idle, u->mobile);
 			}
 		}
@@ -1503,5 +1468,6 @@
 }
 
-static void yahoo_process_buddy_list(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
+static void yahoo_process_buddy_list(struct yahoo_input_data *yid,
+	struct yahoo_packet *pkt)
 {
 	struct yahoo_data *yd = yid->yd;
@@ -1515,14 +1481,14 @@
 		struct yahoo_pair *pair = l->data;
 
-		switch(pair->key) {
+		switch (pair->key) {
 		case 300:
 		case 301:
 		case 302:
+			break;	/* Separators. Our logic does not need them */
 		case 303:
-			if ( 315 == atoi(pair->value) )
+			if (318 == atoi(pair->value))
 				last_packet = 1;
 			break;
 		case 65:
-			g_free(cur_group);
 			cur_group = strdup(pair->value);
 			break;
@@ -1530,18 +1496,14 @@
 			newbud = y_new0(struct yahoo_buddy, 1);
 			newbud->id = strdup(pair->value);
-			if (cur_group) {
+			if (cur_group)
 				newbud->group = strdup(cur_group);
-			} else {
-				YList *last;
-				struct yahoo_buddy *lastbud;
-				
-				for (last = yd->buddies; last && last->next; last = last->next);
-				if (last) {
-					lastbud = last->data;
-					newbud->group = strdup(lastbud->group);
-				} else {
-					newbud->group = strdup("Buddies");
-				}
-			}
+			else if (yd->buddies) {
+				struct yahoo_buddy *lastbud =
+					(struct yahoo_buddy *)y_list_nth(yd->
+					buddies,
+					y_list_length(yd->buddies) - 1)->data;
+				newbud->group = strdup(lastbud->group);
+			} else
+				newbud->group = strdup("Buddies");
 
 			yd->buddies = y_list_append(yd->buddies, newbud);
@@ -1550,76 +1512,56 @@
 		}
 	}
-	
-	g_free(cur_group);
 
 	/* we could be getting multiple packets here */
-	if (last_packet)
-		return;
-
-	YAHOO_CALLBACK(ext_yahoo_got_buddies)(yd->client_id, yd->buddies);
-
-	/*** We login at the very end of the packet communication */
+	if (pkt->hash && !last_packet)
+		return;
+
+	YAHOO_CALLBACK(ext_yahoo_got_buddies) (yd->client_id, yd->buddies);
+
+	/* Logged in */
 	if (!yd->logged_in) {
-		yd->logged_in = TRUE;
-		if(yd->current_status < 0)
+		yd->logged_in = 1;
+		if (yd->current_status < 0)
 			yd->current_status = yd->initial_status;
-		YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_OK, NULL);
-	}
-}
-
-static void yahoo_process_list(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
+		YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id,
+			YAHOO_LOGIN_OK, NULL);
+
+		/*
+		yahoo_set_away(yd->client_id, yd->initial_status, NULL,
+			(yd->initial_status == YAHOO_STATUS_AVAILABLE) ? 0 : 1);
+
+		yahoo_get_yab(yd->client_id);
+		*/
+	}
+
+}
+
+static void yahoo_process_list(struct yahoo_input_data *yid,
+	struct yahoo_packet *pkt)
 {
 	struct yahoo_data *yd = yid->yd;
 	YList *l;
 
-	if (!yd->logged_in) {
-		yd->logged_in = TRUE;
-		if(yd->current_status < 0)
-			yd->current_status = yd->initial_status;
-		YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_OK, NULL);
-	}
-
+	/* we could be getting multiple packets here */
 	for (l = pkt->hash; l; l = l->next) {
 		struct yahoo_pair *pair = l->data;
 
-		switch(pair->key) {
-		case 87: /* buddies */
-			if(!yd->rawbuddylist)
-				yd->rawbuddylist = strdup(pair->value);
-			else {
-				yd->rawbuddylist = y_string_append(yd->rawbuddylist, pair->value);
+		switch (pair->key) {
+		case 89:	/* identities */
+			{
+				char **identities =
+					y_strsplit(pair->value, ",", -1);
+				int i;
+				for (i = 0; identities[i]; i++)
+					yd->identities =
+						y_list_append(yd->identities,
+						strdup(identities[i]));
+				y_strfreev(identities);
 			}
-			break;
-
-		case 88: /* ignore list */
-			if(!yd->ignorelist)
-				yd->ignorelist = strdup("Ignore:");
-			yd->ignorelist = y_string_append(yd->ignorelist, pair->value);
-			break;
-
-		case 89: /* identities */
-			{
-			char **identities = y_strsplit(pair->value, ",", -1);
-			int i;
-			for(i=0; identities[i]; i++)
-				yd->identities = y_list_append(yd->identities, 
-						strdup(identities[i]));
-			y_strfreev(identities);
-			}
-			YAHOO_CALLBACK(ext_yahoo_got_identities)(yd->client_id, yd->identities);
-			break;
-		case 59: /* cookies */
-			if(yd->ignorelist) {
-				yd->ignore = bud_str2list(yd->ignorelist);
-				FREE(yd->ignorelist);
-				YAHOO_CALLBACK(ext_yahoo_got_ignore)(yd->client_id, yd->ignore);
-			}
-			if(yd->rawbuddylist) {
-				yd->buddies = bud_str2list(yd->rawbuddylist);
-				FREE(yd->rawbuddylist);
-				YAHOO_CALLBACK(ext_yahoo_got_buddies)(yd->client_id, yd->buddies);
-			}
-
-			if(pair->value[0]=='Y') {
+			YAHOO_CALLBACK(ext_yahoo_got_identities) (yd->client_id,
+				yd->identities);
+			break;
+		case 59:	/* cookies */
+			if (pair->value[0] == 'Y') {
 				FREE(yd->cookie_y);
 				FREE(yd->login_cookie);
@@ -1628,26 +1570,26 @@
 				yd->login_cookie = getlcookie(yd->cookie_y);
 
-			} else if(pair->value[0]=='T') {
+			} else if (pair->value[0] == 'T') {
 				FREE(yd->cookie_t);
 				yd->cookie_t = getcookie(pair->value);
 
-			} else if(pair->value[0]=='C') {
+			} else if (pair->value[0] == 'C') {
 				FREE(yd->cookie_c);
 				yd->cookie_c = getcookie(pair->value);
-			} 
-
-			if(yd->cookie_y && yd->cookie_t)
-				YAHOO_CALLBACK(ext_yahoo_got_cookies)(yd->client_id);
-
-			break;
-		case 3: /* my id */
-		case 90: /* 1 */
-		case 100: /* 0 */
-		case 101: /* NULL */
-		case 102: /* NULL */
-		case 93: /* 86400/1440 */
-			break;
-		}
-	}
+			}
+
+			break;
+		case 3:	/* my id */
+		case 90:	/* 1 */
+		case 100:	/* 0 */
+		case 101:	/* NULL */
+		case 102:	/* NULL */
+		case 93:	/* 86400/1440 */
+			break;
+		}
+	}
+
+	if (yd->cookie_y && yd->cookie_t)	/* We don't get cookie_c anymore */
+		YAHOO_CALLBACK(ext_yahoo_got_cookies) (yd->client_id);
 }
 
Index: protocols/yahoo/yahoo.c
===================================================================
--- protocols/yahoo/yahoo.c	(revision 842cd8dbfb98b61af33b5fe481364c3cfbeaca04)
+++ protocols/yahoo/yahoo.c	(revision 638feab58aebc97d646820dd1bc9b8d9fbeec29d)
@@ -227,5 +227,5 @@
 			yd->current_status = YAHOO_STATUS_CUSTOM;
 	}
-	else if( state )
+	else if( msg )
 		yd->current_status = YAHOO_STATUS_CUSTOM;
 	else
Index: protocols/yahoo/yahoo2_types.h
===================================================================
--- protocols/yahoo/yahoo2_types.h	(revision 842cd8dbfb98b61af33b5fe481364c3cfbeaca04)
+++ protocols/yahoo/yahoo2_types.h	(revision 638feab58aebc97d646820dd1bc9b8d9fbeec29d)
@@ -196,4 +196,6 @@
 
 	void  *server_settings;
+	
+	struct yahoo_process_status_entry *half_user;
 };
 
@@ -261,4 +263,25 @@
 };
 
+struct yahoo_process_status_entry {
+	char *name;	/* 7      name */
+	int state;	/* 10     state */
+	int flags;	/* 13     flags, bit 0 = pager, bit 1 = chat, bit 2 = game */
+	int mobile;	/* 60     mobile */
+	char *msg;	/* 19     custom status message */
+	int away;	/* 47     away (or invisible) */
+	int buddy_session; /* 11  state */
+	int f17;	/* 17     in chat? then what about flags? */
+	int idle;	/* 137    seconds idle */
+	int f138;	/* 138    state */
+	char *f184;	/* 184    state */
+	int f192;	/* 192    state */
+	int f10001;	/* 10001  state */
+	int f10002;	/* 10002  state */
+	int f198;	/* 198    state */
+	char *f197;	/* 197    state */
+	char *f205;	/* 205    state */
+	int f213;	/* 213    state */
+};
+
 #ifdef __cplusplus
 }
