Index: protocols/jabber/io.c
===================================================================
--- protocols/jabber/io.c	(revision 3f81999c20852f14a5fb27a6ef6c5ea44db61a4d)
+++ protocols/jabber/io.c	(revision 5f8ab6a9adf09ea7c07f728227bdb6d3953588f1)
@@ -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 3f81999c20852f14a5fb27a6ef6c5ea44db61a4d)
+++ protocols/jabber/iq.c	(revision 5f8ab6a9adf09ea7c07f728227bdb6d3953588f1)
@@ -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.c
===================================================================
--- protocols/jabber/jabber.c	(revision 3f81999c20852f14a5fb27a6ef6c5ea44db61a4d)
+++ protocols/jabber/jabber.c	(revision 5f8ab6a9adf09ea7c07f728227bdb6d3953588f1)
@@ -67,5 +67,5 @@
 	s->flags |= ACC_SET_OFFLINE_ONLY;
 	
-	s = set_add( &acc->set, "resource_select", "priority", NULL, acc );
+	s = set_add( &acc->set, "resource_select", "activity", NULL, acc );
 	
 	s = set_add( &acc->set, "server", NULL, set_eval_account, acc );
@@ -80,4 +80,6 @@
 	s = set_add( &acc->set, "xmlconsole", "false", set_eval_bool, acc );
 	s->flags |= ACC_SET_OFFLINE_ONLY;
+	
+	acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE;
 }
 
@@ -364,8 +366,9 @@
 	while( bud )
 	{
-		imcb_log( ic, "Buddy %s (%d) information:\nAway state: %s\nAway message: %s",
-		                   bud->full_jid, bud->priority,
-		                   bud->away_state ? bud->away_state->full_name : "(none)",
-		                   bud->away_message ? : "(none)" );
+		imcb_log( ic, "Buddy %s (%d) information:", bud->full_jid, bud->priority );
+		if( bud->away_state )
+			imcb_log( ic, "Away state: %s", bud->away_state->full_name );
+		imcb_log( ic, "Status message: %s", bud->away_message ? : "(none)" );
+		
 		bud = bud->next;
 	}
@@ -377,9 +380,10 @@
 {
 	struct jabber_data *jd = ic->proto_data;
-	struct jabber_away_state *state;
-	
-	/* Save all this info. We need it, for example, when changing the priority setting. */
-	state = (void *) jabber_away_state_by_name( state_txt );
-	jd->away_state = state ? state : (void *) jabber_away_state_list; /* Fall back to "Away" if necessary. */
+	
+	/* state_txt == NULL -> Not away.
+	   Unknown state -> fall back to the first defined away state. */
+	jd->away_state = state_txt ? jabber_away_state_by_name( state_txt )
+	                 ? : jabber_away_state_list : NULL;
+	
 	g_free( jd->away_message );
 	jd->away_message = ( message && *message ) ? g_strdup( message ) : NULL;
Index: protocols/jabber/jabber.h
===================================================================
--- protocols/jabber/jabber.h	(revision 3f81999c20852f14a5fb27a6ef6c5ea44db61a4d)
+++ protocols/jabber/jabber.h	(revision 5f8ab6a9adf09ea7c07f728227bdb6d3953588f1)
@@ -27,6 +27,7 @@
 #include <glib.h>
 
+#include "bitlbee.h"
+#include "md5.h"
 #include "xmltree.h"
-#include "bitlbee.h"
 
 extern GSList *jabber_connections;
@@ -39,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;
 
@@ -83,5 +85,5 @@
 	/* After changing one of these two (or the priority setting), call
 	   presence_send_update() to inform the server about the changes. */
-	struct jabber_away_state *away_state;
+	const struct jabber_away_state *away_state;
 	char *away_message;
 	
Index: protocols/jabber/jabber_util.c
===================================================================
--- protocols/jabber/jabber_util.c	(revision 3f81999c20852f14a5fb27a6ef6c5ea44db61a4d)
+++ protocols/jabber/jabber_util.c	(revision 5f8ab6a9adf09ea7c07f728227bdb6d3953588f1)
@@ -228,8 +228,7 @@
 {
 	{ "away",  "Away" },
-	{ "chat",  "Free for Chat" },
+	{ "chat",  "Free for Chat" },   /* WTF actually uses this? */
 	{ "dnd",   "Do not Disturb" },
 	{ "xa",    "Extended Away" },
-	{ "",      "Online" },
 	{ "",      NULL }
 };
@@ -238,4 +237,7 @@
 {
 	int i;
+	
+	if( code == NULL )
+		return NULL;
 	
 	for( i = 0; jabber_away_state_list[i].full_name; i ++ )
@@ -249,4 +251,7 @@
 {
 	int i;
+	
+	if( name == NULL )
+		return NULL;
 	
 	for( i = 0; jabber_away_state_list[i].full_name; i ++ )
Index: protocols/jabber/presence.c
===================================================================
--- protocols/jabber/presence.c	(revision 3f81999c20852f14a5fb27a6ef6c5ea44db61a4d)
+++ protocols/jabber/presence.c	(revision 5f8ab6a9adf09ea7c07f728227bdb6d3953588f1)
@@ -190,11 +190,10 @@
 		int is_away = 0;
 
-		if( send_presence->away_state && !( *send_presence->away_state->code == 0 ||
-		    strcmp( send_presence->away_state->code, "chat" ) == 0 ) )
+		if( send_presence->away_state &&
+		    strcmp( send_presence->away_state->code, "chat" ) != 0 )
 			is_away = OPT_AWAY;
 
 		imcb_buddy_status( ic, send_presence->bare_jid, OPT_LOGGED_IN | is_away,
-		                   ( is_away && send_presence->away_state ) ?
-		                   send_presence->away_state->full_name : NULL,
+		                   is_away ? send_presence->away_state->full_name : NULL,
 		                   send_presence->away_message );
 	}
@@ -209,6 +208,4 @@
 	struct jabber_data *jd = ic->proto_data;
 	struct xt_node *node, *cap;
-	char *show = jd->away_state->code;
-	char *status = jd->away_message;
 	struct groupchat *c;
 	int st;
@@ -216,8 +213,8 @@
 	node = jabber_make_packet( "presence", NULL, NULL, NULL );
 	xt_add_child( node, xt_new_node( "priority", set_getstr( &ic->acc->set, "priority" ), NULL ) );
-	if( show && *show )
-		xt_add_child( node, xt_new_node( "show", show, NULL ) );
-	if( status )
-		xt_add_child( node, xt_new_node( "status", status, NULL ) );
+	if( jd->away_state )
+		xt_add_child( node, xt_new_node( "show", jd->away_state->code, NULL ) );
+	if( jd->away_message )
+		xt_add_child( node, xt_new_node( "status", jd->away_message, NULL ) );
 	
 	/* This makes the packet slightly bigger, but clients interested in
