Index: protocols/jabber/io.c
===================================================================
--- protocols/jabber/io.c	(revision 8d7429102adf8dce6844f2f3da2723d1f87c6442)
+++ protocols/jabber/io.c	(revision fe7a55434385fd858453dffdbb425a21f41e3859)
@@ -219,5 +219,5 @@
 	struct gaim_connection *gc = data;
 	struct jabber_data *jd = gc->proto_data;
-	struct xt_node *c;
+	struct xt_node *c, *reply;
 	
 	c = xt_find_node( node->children, "starttls" );
@@ -231,7 +231,34 @@
 	}
 	
+	if( ( c = xt_find_node( node->children, "bind" ) ) )
+	{
+		reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &gc->acc->set, "resource" ), NULL ) );
+		xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-bind" );
+		reply = jabber_make_packet( "iq", "set", NULL, reply );
+		jabber_cache_packet( gc, reply );
+		
+		if( !jabber_write_packet( gc, reply ) )
+			return XT_ABORT;
+		
+		jd->flags |= JFLAG_WAIT_BIND;
+	}
+	
+	if( ( c = xt_find_node( node->children, "session" ) ) )
+	{
+		reply = xt_new_node( "session", NULL, NULL );
+		xt_add_attr( reply, "xmlns", "urn:ietf:params:xml:ns:xmpp-session" );
+		reply = jabber_make_packet( "iq", "set", NULL, reply );
+		jabber_cache_packet( gc, reply );
+		
+		if( !jabber_write_packet( gc, 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( jd->flags & JFLAG_AUTHENTICATED )
+	   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( gc ) )
Index: protocols/jabber/iq.c
===================================================================
--- protocols/jabber/iq.c	(revision 8d7429102adf8dce6844f2f3da2723d1f87c6442)
+++ protocols/jabber/iq.c	(revision fe7a55434385fd858453dffdbb425a21f41e3859)
@@ -28,5 +28,5 @@
 	struct gaim_connection *gc = data;
 	struct jabber_data *jd = gc->proto_data;
-	struct xt_node *query, *reply = NULL;
+	struct xt_node *query, *reply = NULL, *orig = NULL;
 	char *s, *type, *xmlns;
 	int st;
@@ -39,4 +39,7 @@
 	
 	xmlns = xt_find_attr( query, "xmlns" );
+	
+	if( ( s = xt_find_attr( node, "id" ) ) )
+		orig = jabber_packet_from_cache( gc, s );
 	
 	if( strcmp( type, "result" ) == 0 && xmlns && strcmp( xmlns, "jabber:iq:auth" ) == 0 )
@@ -82,6 +85,6 @@
 		
 		reply = jabber_make_packet( "iq", "set", NULL, reply );
+		jabber_cache_packet( gc, reply );
 		st = jabber_write_packet( gc, reply );
-		xt_free_node( reply );
 		
 		return st ? XT_HANDLED : XT_ABORT;
@@ -106,13 +109,32 @@
 		presence_announce( gc );
 	}
-	else if( strcmp( type, "result" ) == 0 )
+	else if( strcmp( type, "result" ) == 0 && orig )
 	{
-		/* If we weren't authenticated yet, let's assume we are now.
-		   There are cleaner ways to do this, probably, but well.. */
-		if( !( jd->flags & JFLAG_AUTHENTICATED ) )
+		struct xt_node *node;
+		
+		if( !( jd->flags & JFLAG_AUTHENTICATED ) &&
+		    ( node = xt_find_node( orig->children, "query" ) ) &&
+		    ( node = xt_find_node( node->children, "username" ) ) &&
+		    node->text_len )
 		{
+			/* This happens when we just successfully authenticated
+			   the old (non-SASL) way. */
 			jd->flags |= JFLAG_AUTHENTICATED;
 			if( !jabber_get_roster( gc ) )
 				return XT_ABORT;
+		}
+		else if( ( node = xt_find_node( orig->children, "bind" ) ) ||
+		         ( node = xt_find_node( orig->children, "session" ) ) )
+		{
+			if( strcmp( node->name, "bind" ) == 0 )
+				jd->flags &= ~JFLAG_WAIT_BIND;
+			else if( strcmp( node->name, "session" ) == 0 )
+				jd->flags &= ~JFLAG_WAIT_SESSION;
+			
+			if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )
+			{
+				if( !jabber_get_roster( gc ) )
+					return XT_ABORT;
+			}
 		}
 	}
Index: protocols/jabber/jabber.c
===================================================================
--- protocols/jabber/jabber.c	(revision 8d7429102adf8dce6844f2f3da2723d1f87c6442)
+++ protocols/jabber/jabber.c	(revision fe7a55434385fd858453dffdbb425a21f41e3859)
@@ -76,4 +76,6 @@
 	jd->server ++;
 	
+	jd->node_cache = xt_new_node( "cache", NULL, NULL );
+	
 	if( set_getbool( &acc->set, "ssl" ) )
 	{
@@ -103,4 +105,8 @@
 		closesocket( jd->fd );
 	
+	if( jd->tx_len )
+		g_free( jd->txq );
+	
+	xt_free_node( jd->node_cache );
 	xt_free( jd->xt );
 	
Index: protocols/jabber/jabber.h
===================================================================
--- protocols/jabber/jabber.h	(revision 8d7429102adf8dce6844f2f3da2723d1f87c6442)
+++ protocols/jabber/jabber.h	(revision fe7a55434385fd858453dffdbb425a21f41e3859)
@@ -35,4 +35,6 @@
 	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_WAIT_SESSION = 8,		/* Set if we sent a <session> tag and need a reply before we continue. */
+	JFLAG_WAIT_BIND = 16,		/* ... for <bind> tag. */
 } jabber_flags_t;
 
@@ -53,4 +55,6 @@
 char *set_eval_tls( set_t *set, char *value );
 struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children );
+void jabber_cache_packet( struct gaim_connection *gc, struct xt_node *node );
+struct xt_node *jabber_packet_from_cache( struct gaim_connection *gc, char *id );
 
 /* io.c */
@@ -82,4 +86,6 @@
 	char *username;		/* USERNAME@server */
 	char *server;		/* username@SERVER -=> server/domain, not hostname */
+	
+	struct xt_node *node_cache;
 };
 
Index: protocols/jabber/jabber_util.c
===================================================================
--- protocols/jabber/jabber_util.c	(revision 8d7429102adf8dce6844f2f3da2723d1f87c6442)
+++ protocols/jabber/jabber_util.c	(revision fe7a55434385fd858453dffdbb425a21f41e3859)
@@ -52,10 +52,8 @@
 struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children )
 {
-	char *id = g_strdup_printf( "BeeX%04x", next_id++ );
 	struct xt_node *node;
 	
 	node = xt_new_node( name, NULL, children );
 	
-	xt_add_attr( node, "id", id );
 	if( type )
 		xt_add_attr( node, "type", type );
@@ -63,5 +61,32 @@
 		xt_add_attr( node, "to", to );
 	
+	return node;
+}
+
+/* Cache a node/packet for later use. Mainly useful for IQ packets if you need
+   them when you receive the response. Use this BEFORE sending the packet so
+   it'll get an id= tag, and do NOT free() the packet after writing it! */
+void jabber_cache_packet( struct gaim_connection *gc, struct xt_node *node )
+{
+	struct jabber_data *jd = gc->proto_data;
+	char *id = g_strdup_printf( "BeeX%04x", next_id++ );
+	
+	/* FIXME: Maybe start using g_error() here if nodes still have a parent, for example? */
+	
+	xt_add_attr( node, "id", id );
+	xt_add_child( jd->node_cache, node );
 	g_free( id );
+}
+
+/* Emptying this cache is a BIG TODO! */
+struct xt_node *jabber_packet_from_cache( struct gaim_connection *gc, char *id )
+{
+	struct jabber_data *jd = gc->proto_data;
+	struct xt_node *node;
+	char *s;
+	
+	for( node = jd->node_cache->children; node; node = node->next )
+		if( ( s = xt_find_attr( node, "id" ) ) && strcmp( id, s ) == 0 )
+			break;
 	
 	return node;
Index: protocols/jabber/sasl.c
===================================================================
--- protocols/jabber/sasl.c	(revision 8d7429102adf8dce6844f2f3da2723d1f87c6442)
+++ protocols/jabber/sasl.c	(revision fe7a55434385fd858453dffdbb425a21f41e3859)
@@ -71,5 +71,11 @@
 	xt_add_attr( reply, "xmlns", SASL_NS );
 	
-	if( sup_plain )
+	if( sup_digest && 0 )
+	{
+		xt_add_attr( reply, "mechanism", "DIGEST-MD5" );
+		
+		/* The rest will be done later, when we receive a <challenge/>. */
+	}
+	else if( sup_plain )
 	{
 		int len;
@@ -141,4 +147,4 @@
 	struct jabber_data *jd = gc->proto_data;
 	
-	return ( jd->xt && jd->xt->root && xt_find_attr( jd->xt->root, "version" ) ) != NULL;
+	return ( (void*) ( jd->xt && jd->xt->root && xt_find_attr( jd->xt->root, "version" ) ) ) != NULL;
 }
