Index: protocols/jabber/jabber.c
===================================================================
--- protocols/jabber/jabber.c	(revision 4ac647dbcef152bebde7209f7c9cbbf8a5e0fc37)
+++ protocols/jabber/jabber.c	(revision 8661caad555f4306cf36ee37979a7637b05d5cd4)
@@ -33,13 +33,31 @@
 #include "jabber.h"
 #include "md5.h"
-#include "base64.h"
 
 GSList *jabber_connections;
 
+/* First enty is the default */
+static const int jabber_port_list[] = {
+	5222,
+	5223,
+	5220,
+	5221,
+	5224,
+	5225,
+	5226,
+	5227,
+	5228,
+	5229,
+	80,
+	443,
+	0
+};
+
 static void jabber_init( account_t *acc )
 {
 	set_t *s;
-	
-	s = set_add( &acc->set, "port", JABBER_PORT_DEFAULT, set_eval_int, acc );
+	char str[16];
+	
+	g_snprintf( str, sizeof( str ), "%d", jabber_port_list[0] );
+	s = set_add( &acc->set, "port", str, set_eval_int, acc );
 	s->flags |= ACC_SET_OFFLINE_ONLY;
 	
@@ -74,4 +92,5 @@
 	struct ns_srv_reply *srv = NULL;
 	char *connect_to, *s;
+	int i;
 	
 	/* For now this is needed in the _connected() handlers if using
@@ -179,9 +198,11 @@
 	imcb_log( ic, "Connecting" );
 	
-	if( set_getint( &acc->set, "port" ) < JABBER_PORT_MIN ||
-	    set_getint( &acc->set, "port" ) > JABBER_PORT_MAX )
-	{
-		imcb_log( ic, "Incorrect port number, must be in the %d-%d range",
-		               JABBER_PORT_MIN, JABBER_PORT_MAX );
+	for( i = 0; jabber_port_list[i] > 0; i ++ )
+		if( set_getint( &acc->set, "port" ) == jabber_port_list[i] )
+			break;
+
+	if( jabber_port_list[i] == 0 )
+	{
+		imcb_log( ic, "Illegal port number" );
 		imc_logout( ic, FALSE );
 		return;
@@ -221,22 +242,18 @@
 }
 
+/* This generates an unfinished md5_state_t variable. Every time we generate
+   an ID, we finish the state by adding a sequence number and take the hash. */
 static void jabber_generate_id_hash( struct jabber_data *jd )
 {
-	md5_state_t id_hash;
-	md5_byte_t binbuf[16];
+	md5_byte_t binbuf[4];
 	char *s;
 	
-	md5_init( &id_hash );
-	md5_append( &id_hash, (unsigned char *) jd->username, strlen( jd->username ) );
-	md5_append( &id_hash, (unsigned char *) jd->server, strlen( jd->server ) );
+	md5_init( &jd->cached_id_prefix );
+	md5_append( &jd->cached_id_prefix, (unsigned char *) jd->username, strlen( jd->username ) );
+	md5_append( &jd->cached_id_prefix, (unsigned char *) jd->server, strlen( jd->server ) );
 	s = set_getstr( &jd->ic->acc->set, "resource" );
-	md5_append( &id_hash, (unsigned char *) s, strlen( s ) );
-	random_bytes( binbuf, 16 );
-	md5_append( &id_hash, binbuf, 16 );
-	md5_finish( &id_hash, binbuf );
-	
-	s = base64_encode( binbuf, 9 );
-	jd->cached_id_prefix = g_strdup_printf( "%s%s", JABBER_CACHED_ID, s );
-	g_free( s );
+	md5_append( &jd->cached_id_prefix, (unsigned char *) s, strlen( s ) );
+	random_bytes( binbuf, 4 );
+	md5_append( &jd->cached_id_prefix, binbuf, 4 );
 }
 
@@ -281,5 +298,4 @@
 	xt_free( jd->xt );
 	
-	g_free( jd->cached_id_prefix );
 	g_free( jd->away_message );
 	g_free( jd->username );
Index: protocols/jabber/jabber.h
===================================================================
--- protocols/jabber/jabber.h	(revision 4ac647dbcef152bebde7209f7c9cbbf8a5e0fc37)
+++ protocols/jabber/jabber.h	(revision 8661caad555f4306cf36ee37979a7637b05d5cd4)
@@ -94,5 +94,5 @@
 	char *away_message;
 	
-	char *cached_id_prefix;
+	md5_state_t cached_id_prefix;
 	GHashTable *node_cache;
 	GHashTable *buddies;
@@ -177,8 +177,4 @@
 
 #define JABBER_XMLCONSOLE_HANDLE "xmlconsole"
-
-#define JABBER_PORT_DEFAULT "5222"
-#define JABBER_PORT_MIN 5220
-#define JABBER_PORT_MAX 5229
 
 /* Prefixes to use for packet IDs (mainly for IQ packets ATM). Usually the
Index: protocols/jabber/jabber_util.c
===================================================================
--- protocols/jabber/jabber_util.c	(revision 4ac647dbcef152bebde7209f7c9cbbf8a5e0fc37)
+++ protocols/jabber/jabber_util.c	(revision 8661caad555f4306cf36ee37979a7637b05d5cd4)
@@ -23,4 +23,6 @@
 
 #include "jabber.h"
+#include "md5.h"
+#include "base64.h"
 
 static unsigned int next_id = 1;
@@ -138,9 +140,19 @@
 	struct jabber_data *jd = ic->proto_data;
 	struct jabber_cache_entry *entry = g_new0( struct jabber_cache_entry, 1 );
-	char *id;
-	
-	id = g_strdup_printf( "%s%05x", jd->cached_id_prefix, ( next_id++ ) & 0xfffff );
+	md5_state_t id_hash;
+	md5_byte_t id_sum[16];
+	char *id, *asc_hash;
+	
+	next_id ++;
+	
+	id_hash = jd->cached_id_prefix;
+	md5_append( &id_hash, (md5_byte_t*) &next_id, sizeof( next_id ) );
+	md5_finish( &id_hash, id_sum );
+	asc_hash = base64_encode( id_sum, 12 );
+	
+	id = g_strdup_printf( "%s%s", JABBER_CACHED_ID, asc_hash );
 	xt_add_attr( node, "id", id );
 	g_free( id );
+	g_free( asc_hash );
 	
 	entry->node = node;
@@ -188,5 +200,5 @@
 	
 	if( ( s = xt_find_attr( node, "id" ) ) == NULL ||
-	    strncmp( s, jd->cached_id_prefix, strlen( jd->cached_id_prefix ) ) != 0 )
+	    strncmp( s, JABBER_CACHED_ID, strlen( JABBER_CACHED_ID ) ) != 0 )
 	{
 		/* Silently ignore it, without an ID (or a non-cache
@@ -200,6 +212,12 @@
 	if( entry == NULL )
 	{
+		/*
+		There's no longer an easy way to see if we generated this
+		one or someone else, and there's a ten-minute timeout anyway,
+		so meh.
+		
 		imcb_log( ic, "Warning: Received %s-%s packet with unknown/expired ID %s!",
 		              node->name, xt_find_attr( node, "type" ) ? : "(no type)", s );
+		*/
 	}
 	else if( entry->func )
@@ -294,12 +312,10 @@
 	len = strlen( orig );
 	new = g_new( char, len + 1 );
-	for( i = 0; i < len; i ++ )
-	{
-		/* don't normalize the resource */
-		if( orig[i] == '/' )
-			break;
+	
+	/* So it turns out the /resource part is case sensitive. Yeah, and
+	   it's Unicode but feck Unicode. :-P So stop once we see a slash. */
+	for( i = 0; i < len && orig[i] != '/' ; i ++ )
 		new[i] = tolower( orig[i] );
-	}
-	for( ; i < len; i ++ )
+	for( ; orig[i]; i ++ )
 		new[i] = orig[i];
 	
@@ -345,5 +361,5 @@
 		{
 			/* Check for dupes. */
-			if( g_strcasecmp( bi->resource, s + 1 ) == 0 )
+			if( strcmp( bi->resource, s + 1 ) == 0 )
 			{
 				*s = '/';
@@ -398,5 +414,5 @@
 	if( ( s = strchr( jid, '/' ) ) )
 	{
-		int none_found = 0;
+		int bare_exists = 0;
 		
 		*s = 0;
@@ -421,19 +437,17 @@
 			/* See if there's an exact match. */
 			for( ; bud; bud = bud->next )
-				if( g_strcasecmp( bud->resource, s + 1 ) == 0 )
+				if( strcmp( bud->resource, s + 1 ) == 0 )
 					break;
 		}
 		else
 		{
-			/* This hack is there to make sure that O_CREAT will
-			   work if there's already another resouce present
-			   for this JID, even if it's an unknown buddy. This
-			   is done to handle conferences properly. */
-			none_found = 1;
-			/* TODO(wilmer): Find out what I was thinking when I
-			   wrote this??? And then fix it. This makes me sad... */
-		}
-		
-		if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && ( imcb_find_buddy( ic, jid ) || !none_found ) )
+			/* This variable tells the if down here that the bare
+			   JID already exists and we should feel free to add
+			   more resources, if the caller asked for that. */
+			bare_exists = 1;
+		}
+		
+		if( bud == NULL && ( flags & GET_BUDDY_CREAT ) &&
+		    ( !bare_exists || imcb_find_buddy( ic, jid ) ) )
 		{
 			*s = '/';
@@ -460,5 +474,5 @@
 			/* We want an exact match, so in thise case there shouldn't be a /resource. */
 			return NULL;
-		else if( ( bud->resource == NULL || bud->next == NULL ) )
+		else if( bud->resource == NULL || bud->next == NULL )
 			/* No need for selection if there's only one option. */
 			return bud;
@@ -536,5 +550,7 @@
 		   matches), removing it is simple. (And the hash reference
 		   should be removed too!) */
-		if( bud->next == NULL && ( ( s == NULL || bud->resource == NULL ) || g_strcasecmp( bud->resource, s + 1 ) == 0 ) )
+		if( bud->next == NULL &&
+		    ( ( s == NULL && bud->resource == NULL ) ||
+		      ( bud->resource && s && strcmp( bud->resource, s + 1 ) == 0 ) ) )
 		{
 			g_hash_table_remove( jd->buddies, bud->bare_jid );
@@ -559,5 +575,5 @@
 		{
 			for( bi = bud, prev = NULL; bi; bi = (prev=bi)->next )
-				if( g_strcasecmp( bi->resource, s + 1 ) == 0 )
+				if( strcmp( bi->resource, s + 1 ) == 0 )
 					break;
 			
Index: protocols/jabber/message.c
===================================================================
--- protocols/jabber/message.c	(revision 4ac647dbcef152bebde7209f7c9cbbf8a5e0fc37)
+++ protocols/jabber/message.c	(revision 8661caad555f4306cf36ee37979a7637b05d5cd4)
@@ -49,4 +49,21 @@
 	{
 		GString *fullmsg = g_string_new( "" );
+
+		for( c = node->children; ( c = xt_find_node( c, "x" ) ); c = c->next )
+		{
+			char *ns = xt_find_attr( c, "xmlns" ), *room;
+			struct xt_node *inv, *reason;
+			
+			if( strcmp( ns, XMLNS_MUC_USER ) == 0 &&
+			    ( inv = xt_find_node( c->children, "invite" ) ) )
+			{
+				room = from;
+				from = xt_find_attr( inv, "from" ) ? : from;
+
+				g_string_append_printf( fullmsg, "<< \002BitlBee\002 - Invitation to chatroom %s >>\n", room );
+				if( ( reason = xt_find_node( inv->children, "reason" ) ) && reason->text_len > 0 )
+					g_string_append( fullmsg, reason->text );
+			}
+		}
 		
 		if( ( s = strchr( from, '/' ) ) )
