aboutsummaryrefslogtreecommitdiffstats
path: root/protocols/jabber
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/jabber')
-rw-r--r--protocols/jabber/jabber.c56
-rw-r--r--protocols/jabber/jabber.h6
-rw-r--r--protocols/jabber/jabber_util.c64
-rw-r--r--protocols/jabber/message.c17
4 files changed, 94 insertions, 49 deletions
diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c
index 987ef96e..48f71ff1 100644
--- a/protocols/jabber/jabber.c
+++ b/protocols/jabber/jabber.c
@@ -32,15 +32,33 @@
#include "bitlbee.h"
#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;
+ char str[16];
- s = set_add( &acc->set, "port", JABBER_PORT_DEFAULT, set_eval_int, acc );
+ 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;
s = set_add( &acc->set, "priority", "0", set_eval_priority, acc );
@@ -73,6 +91,7 @@ static void jabber_login( account_t *acc )
struct jabber_data *jd = g_new0( struct jabber_data, 1 );
struct ns_srv_reply *srv = NULL;
char *connect_to, *s;
+ int i;
/* For now this is needed in the _connected() handlers if using
GLib event handling, to make sure we're not handling events
@@ -178,11 +197,13 @@ static void jabber_login( account_t *acc )
imcb_log( ic, "Connecting" );
- if( set_getint( &acc->set, "port" ) < JABBER_PORT_MIN ||
- set_getint( &acc->set, "port" ) > 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, "Incorrect port number, must be in the %d-%d range",
- JABBER_PORT_MIN, JABBER_PORT_MAX );
+ imcb_log( ic, "Illegal port number" );
imc_logout( ic, FALSE );
return;
}
@@ -220,24 +241,20 @@ static void jabber_login( account_t *acc )
jabber_generate_id_hash( jd );
}
+/* 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 );
}
static void jabber_logout( struct im_connection *ic )
@@ -280,7 +297,6 @@ static void jabber_logout( struct im_connection *ic )
xt_free( jd->xt );
- g_free( jd->cached_id_prefix );
g_free( jd->away_message );
g_free( jd->username );
g_free( jd );
diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h
index bc848170..cc12bdbb 100644
--- a/protocols/jabber/jabber.h
+++ b/protocols/jabber/jabber.h
@@ -93,7 +93,7 @@ struct jabber_data
struct jabber_away_state *away_state;
char *away_message;
- char *cached_id_prefix;
+ md5_state_t cached_id_prefix;
GHashTable *node_cache;
GHashTable *buddies;
@@ -177,10 +177,6 @@ struct jabber_transfer
#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
first one should be used, but when storing a packet in the cache, a
"special" kind of ID is assigned to make it easier later to figure out
diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c
index 23a3010f..9579a848 100644
--- a/protocols/jabber/jabber_util.c
+++ b/protocols/jabber/jabber_util.c
@@ -22,6 +22,8 @@
\***************************************************************************/
#include "jabber.h"
+#include "md5.h"
+#include "base64.h"
static unsigned int next_id = 1;
@@ -137,11 +139,21 @@ void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_ca
{
struct jabber_data *jd = ic->proto_data;
struct jabber_cache_entry *entry = g_new0( struct jabber_cache_entry, 1 );
- char *id;
+ md5_state_t id_hash;
+ md5_byte_t id_sum[16];
+ char *id, *asc_hash;
- id = g_strdup_printf( "%s%05x", jd->cached_id_prefix, ( next_id++ ) & 0xfffff );
+ 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;
entry->func = func;
@@ -187,7 +199,7 @@ xt_status jabber_cache_handle_packet( struct im_connection *ic, struct xt_node *
char *s;
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
ID) we don't know how to handle the packet and we
@@ -199,8 +211,14 @@ xt_status jabber_cache_handle_packet( struct im_connection *ic, struct xt_node *
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 )
{
@@ -293,14 +311,12 @@ char *jabber_normalize( const char *orig )
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];
new[i] = 0;
@@ -344,7 +360,7 @@ struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid_
for( bi = bud; bi; bi = bi->next )
{
/* Check for dupes. */
- if( g_strcasecmp( bi->resource, s + 1 ) == 0 )
+ if( strcmp( bi->resource, s + 1 ) == 0 )
{
*s = '/';
g_free( new );
@@ -397,7 +413,7 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_,
if( ( s = strchr( jid, '/' ) ) )
{
- int none_found = 0;
+ int bare_exists = 0;
*s = 0;
if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) )
@@ -420,21 +436,19 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_,
/* 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... */
+ /* 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 ) && ( imcb_find_buddy( ic, jid ) || !none_found ) )
+ if( bud == NULL && ( flags & GET_BUDDY_CREAT ) &&
+ ( !bare_exists || imcb_find_buddy( ic, jid ) ) )
{
*s = '/';
bud = jabber_buddy_add( ic, jid );
@@ -459,7 +473,7 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_,
else if( bud->resource && ( flags & GET_BUDDY_EXACT ) )
/* 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;
else if( flags & GET_BUDDY_FIRST )
@@ -535,7 +549,9 @@ int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ )
/* If there's only one item in the list (and if the resource
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 );
g_free( bud->bare_jid );
@@ -558,7 +574,7 @@ int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ )
else
{
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;
g_free( full_jid );
diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c
index fab62a91..6cb67d42 100644
--- a/protocols/jabber/message.c
+++ b/protocols/jabber/message.c
@@ -48,6 +48,23 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data )
else /* "chat", "normal", "headline", no-type or whatever. Should all be pretty similar. */
{
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, '/' ) ) )
{