Index: protocols/jabber/io.c
===================================================================
--- protocols/jabber/io.c	(revision 59974884ba72d6e8fa008d07ee93bd228d30a99c)
+++ protocols/jabber/io.c	(revision 8d7429102adf8dce6844f2f3da2723d1f87c6442)
@@ -73,4 +73,7 @@
 	int st;
 	
+	if( jd->fd == -1 )
+		return FALSE;
+	
 	st = write( jd->fd, jd->txq, jd->tx_len );
 	
@@ -86,4 +89,8 @@
 	else if( st == 0 || ( st < 0 && !sockerr_again() ) )
 	{
+		/* Set fd to -1 to make sure we won't write to it anymore. */
+		closesocket( jd->fd );	/* Shouldn't be necessary after errors? */
+		jd->fd = -1;
+		
 		hide_login_progress_error( gc, "Short write() to server" );
 		signoff( gc );
@@ -99,5 +106,5 @@
 		jd->txq = s;
 		
-		return FALSE;
+		return TRUE;
 	}
 	else
@@ -115,4 +122,7 @@
 	char buf[512];
 	int st;
+	
+	if( jd->fd == -1 )
+		return FALSE;
 	
 	st = read( fd, buf, sizeof( buf ) );
@@ -139,5 +149,4 @@
 		{
 			jd->flags &= ~JFLAG_STREAM_RESTART;
-			xt_reset( jd->xt );
 			jabber_start_stream( gc );
 		}
@@ -156,5 +165,10 @@
 			{
 				jd->flags |= JFLAG_STREAM_STARTED;
-				return jabber_start_auth( gc );
+				
+				/* If there's no version attribute, assume
+				   this is an old server that can't do SASL
+				   authentication. */
+				if( !sasl_supported( gc ) )
+					return jabber_start_iq_auth( gc );
 			}
 			else
@@ -168,4 +182,7 @@
 	else if( st == 0 || ( st < 0 && !sockerr_again() ) )
 	{
+		closesocket( jd->fd );
+		jd->fd = -1;
+		
 		hide_login_progress_error( gc, "Error while reading from server" );
 		signoff( gc );
@@ -198,4 +215,31 @@
 }
 
+static xt_status jabber_pkt_features( struct xt_node *node, gpointer data )
+{
+	struct gaim_connection *gc = data;
+	struct jabber_data *jd = gc->proto_data;
+	struct xt_node *c;
+	
+	c = xt_find_node( node->children, "starttls" );
+	if( c )
+	{
+		/*
+		jd->flags |= JFLAG_SUPPORTS_TLS;
+		if( xt_find_node( c->children, "required" ) )
+			jd->flags |= JFLAG_REQUIRES_TLS;
+		*/
+	}
+	
+	/* This flag is already set if we authenticated via SASL, so now
+	   we can resume the session in the new stream. */
+	if( jd->flags & JFLAG_AUTHENTICATED )
+	{
+		if( !jabber_get_roster( gc ) )
+			return XT_ABORT;
+	}
+	
+	return XT_HANDLED;
+}
+
 static xt_status jabber_pkt_misc( struct xt_node *node, gpointer data )
 {
@@ -208,7 +252,8 @@
 static const struct xt_handler_entry jabber_handlers[] = {
 	{ "stream:stream",      "<root>",               jabber_end_of_stream },
-	{ "iq",                 "stream:stream",        jabber_pkt_iq },
 	{ "message",            "stream:stream",        jabber_pkt_message },
 	{ "presence",           "stream:stream",        jabber_pkt_presence },
+	{ "iq",                 "stream:stream",        jabber_pkt_iq },
+	{ "stream:features",    "stream:stream",        jabber_pkt_features },
 	{ "mechanisms",         "stream:features",      sasl_pkt_mechanisms },
 	{ "challenge",          "stream:stream",        sasl_pkt_challenge },
@@ -231,5 +276,6 @@
 	jd->xt->handlers = (struct xt_handler_entry*) jabber_handlers;
 	
-	jd->r_inpa = b_input_add( jd->fd, GAIM_INPUT_READ, jabber_read_callback, gc );
+	if( jd->r_inpa <= 0 )
+		jd->r_inpa = b_input_add( jd->fd, GAIM_INPUT_READ, jabber_read_callback, gc );
 	
 	greet = g_strdup_printf( "<?xml version='1.0' ?>"
@@ -254,9 +300,12 @@
 		char eos[] = "</stream:stream>";
 		struct xt_node *node;
-		int st;
-		
-		node = jabber_make_packet( "presence", "unavailable", NULL, NULL );
-		st = jabber_write_packet( gc, node );
-		xt_free_node( node );
+		int st = 1;
+		
+		if( gc->flags & OPT_LOGGED_IN )
+		{
+			node = jabber_make_packet( "presence", "unavailable", NULL, NULL );
+			st = jabber_write_packet( gc, node );
+			xt_free_node( node );
+		}
 		
 		if( st )
Index: protocols/jabber/iq.c
===================================================================
--- protocols/jabber/iq.c	(revision 59974884ba72d6e8fa008d07ee93bd228d30a99c)
+++ protocols/jabber/iq.c	(revision 8d7429102adf8dce6844f2f3da2723d1f87c6442)
@@ -130,5 +130,5 @@
 }
 
-int jabber_start_auth( struct gaim_connection *gc )
+int jabber_start_iq_auth( struct gaim_connection *gc )
 {
 	struct jabber_data *jd = gc->proto_data;
Index: protocols/jabber/jabber.h
===================================================================
--- protocols/jabber/jabber.h	(revision 59974884ba72d6e8fa008d07ee93bd228d30a99c)
+++ protocols/jabber/jabber.h	(revision 8d7429102adf8dce6844f2f3da2723d1f87c6442)
@@ -35,10 +35,9 @@
 	JFLAG_AUTHENTICATED = 2,	/* Set when we're successfully authenticatd. */
 	JFLAG_STREAM_RESTART = 4,	/* Set when we want to restart the stream (after SASL or TLS). */
-	JFLAG_SUPPORTS_TLS = 8,		/* Set when there's <starttls/> in <stream:features>. */
 } jabber_flags_t;
 
 /* iq.c */
 xt_status jabber_pkt_iq( struct xt_node *node, gpointer data );
-int jabber_start_auth( struct gaim_connection *gc );
+int jabber_start_iq_auth( struct gaim_connection *gc );
 int jabber_get_roster( struct gaim_connection *gc );
 
@@ -66,4 +65,5 @@
 xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data );
 xt_status sasl_pkt_result( struct xt_node *node, gpointer data );
+gboolean sasl_supported( struct gaim_connection *gc );
 
 struct jabber_data
Index: protocols/jabber/sasl.c
===================================================================
--- protocols/jabber/sasl.c	(revision 59974884ba72d6e8fa008d07ee93bd228d30a99c)
+++ protocols/jabber/sasl.c	(revision 8d7429102adf8dce6844f2f3da2723d1f87c6442)
@@ -34,4 +34,13 @@
 	char *s;
 	int sup_plain = 0, sup_digest = 0;
+	
+	if( !sasl_supported( gc ) )
+	{
+		/* Should abort this now, since we should already be doing
+		   IQ authentication. Strange things happen when you try
+		   to do both... */
+		serv_got_crap( gc, "XMPP 1.0 non-compliant server seems to support SASL, please report this as a BitlBee bug!" );
+		return XT_HANDLED;
+	}
 	
 	s = xt_find_attr( node, "xmlns" );
@@ -94,4 +103,5 @@
 xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data )
 {
+	return XT_HANDLED;
 }
 
@@ -123,2 +133,12 @@
 	return XT_HANDLED;
 }
+
+/* This one is needed to judge if we'll do authentication using IQ or SASL.
+   It's done by checking if the <stream:stream> from the server has a
+   version attribute. I don't know if this is the right way though... */
+gboolean sasl_supported( struct gaim_connection *gc )
+{
+	struct jabber_data *jd = gc->proto_data;
+	
+	return ( jd->xt && jd->xt->root && xt_find_attr( jd->xt->root, "version" ) ) != NULL;
+}
Index: protocols/nogaim.c
===================================================================
--- protocols/nogaim.c	(revision 59974884ba72d6e8fa008d07ee93bd228d30a99c)
+++ protocols/nogaim.c	(revision 8d7429102adf8dce6844f2f3da2723d1f87c6442)
@@ -279,4 +279,9 @@
 	user_t *t, *u = irc->users;
 	account_t *a;
+	
+	/* Nested calls might happen sometimes, this is probably the best
+	   place to catch them. */
+	if( gc->flags & OPT_LOGGING_OUT )
+		return;
 	
 	serv_got_crap( gc, "Signing off.." );
