aboutsummaryrefslogtreecommitdiffstats
path: root/protocols/jabber
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/jabber')
-rw-r--r--protocols/jabber/Makefile2
-rw-r--r--protocols/jabber/io.c12
-rw-r--r--protocols/jabber/jabber.c55
-rw-r--r--protocols/jabber/jabber.h6
-rw-r--r--protocols/jabber/jabber_util.c67
-rw-r--r--protocols/jabber/message.c17
-rw-r--r--protocols/jabber/xmltree.c589
-rw-r--r--protocols/jabber/xmltree.h97
8 files changed, 110 insertions, 735 deletions
diff --git a/protocols/jabber/Makefile b/protocols/jabber/Makefile
index 3ce78127..e7a505ba 100644
--- a/protocols/jabber/Makefile
+++ b/protocols/jabber/Makefile
@@ -9,7 +9,7 @@
-include ../../Makefile.settings
# [SH] Program variables
-objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o xmltree.o
+objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o
CFLAGS += -Wall
LFLAGS += -r
diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c
index 86c216ef..10efad37 100644
--- a/protocols/jabber/io.c
+++ b/protocols/jabber/io.c
@@ -240,8 +240,13 @@ static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition
return FALSE;
}
- /* EAGAIN/etc or a successful read. */
- return TRUE;
+ if( ssl_pending( jd->ssl ) )
+ /* OpenSSL empties the TCP buffers completely but may keep some
+ data in its internap buffers. select() won't see that, but
+ ssl_pending() does. */
+ return jabber_read_callback( data, fd, cond );
+ else
+ return TRUE;
}
gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond )
@@ -520,8 +525,7 @@ gboolean jabber_start_stream( struct im_connection *ic )
/* We'll start our stream now, so prepare everything to receive one
from the server too. */
xt_free( jd->xt ); /* In case we're RE-starting. */
- jd->xt = xt_new( ic );
- jd->xt->handlers = (struct xt_handler_entry*) jabber_handlers;
+ jd->xt = xt_new( jabber_handlers, ic );
if( jd->r_inpa <= 0 )
jd->r_inpa = b_input_add( jd->fd, GAIM_INPUT_READ, jabber_read_callback, ic );
diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c
index dac18bae..5fb2c4fc 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 );
@@ -71,6 +89,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
@@ -176,11 +195,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;
}
@@ -218,24 +239,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 )
diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h
index 1ff0e8dd..904bf0c4 100644
--- a/protocols/jabber/jabber.h
+++ b/protocols/jabber/jabber.h
@@ -85,7 +85,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;
};
@@ -134,10 +134,6 @@ struct jabber_chat
#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 6e872040..1bee5009 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;
@@ -133,11 +135,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;
@@ -183,7 +195,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
@@ -195,8 +207,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 )
{
@@ -245,8 +263,10 @@ struct jabber_buddy_ask_data
char *realname;
};
-static void jabber_buddy_ask_yes( gpointer w, struct jabber_buddy_ask_data *bla )
+static void jabber_buddy_ask_yes( void *data )
{
+ struct jabber_buddy_ask_data *bla = data;
+
presence_send_request( bla->ic, bla->handle, "subscribed" );
if( imcb_find_buddy( bla->ic, bla->handle ) == NULL )
@@ -256,8 +276,10 @@ static void jabber_buddy_ask_yes( gpointer w, struct jabber_buddy_ask_data *bla
g_free( bla );
}
-static void jabber_buddy_ask_no( gpointer w, struct jabber_buddy_ask_data *bla )
+static void jabber_buddy_ask_no( void *data )
{
+ struct jabber_buddy_ask_data *bla = data;
+
presence_send_request( bla->ic, bla->handle, "subscribed" );
g_free( bla->handle );
@@ -285,8 +307,13 @@ char *jabber_normalize( const char *orig )
len = strlen( orig );
new = g_new( char, len + 1 );
- for( i = 0; i < len; i ++ )
+
+ /* 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( ; orig[i]; i ++ )
+ new[i] = orig[i];
new[i] = 0;
return new;
@@ -329,7 +356,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 );
@@ -382,7 +409,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 ) ) )
@@ -405,21 +432,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 );
@@ -444,7 +469,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 )
@@ -520,7 +545,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 );
@@ -543,7 +570,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, '/' ) ) )
{
diff --git a/protocols/jabber/xmltree.c b/protocols/jabber/xmltree.c
deleted file mode 100644
index 62549eb5..00000000
--- a/protocols/jabber/xmltree.c
+++ /dev/null
@@ -1,589 +0,0 @@
-/***************************************************************************\
-* *
-* BitlBee - An IRC to IM gateway *
-* Simple XML (stream) parse tree handling code (Jabber/XMPP, mainly) *
-* *
-* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> *
-* *
-* This library is free software; you can redistribute it and/or *
-* modify it under the terms of the GNU Lesser General Public *
-* License as published by the Free Software Foundation, version *
-* 2.1. *
-* *
-* This library is distributed in the hope that it will be useful, *
-* but WITHOUT ANY WARRANTY; without even the implied warranty of *
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
-* Lesser General Public License for more details. *
-* *
-* You should have received a copy of the GNU Lesser General Public License *
-* along with this library; if not, write to the Free Software Foundation, *
-* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
-* *
-****************************************************************************/
-
-#include <glib.h>
-#include <string.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <stdio.h>
-
-#include "xmltree.h"
-
-static void xt_start_element( GMarkupParseContext *ctx, const gchar *element_name, const gchar **attr_names, const gchar **attr_values, gpointer data, GError **error )
-{
- struct xt_parser *xt = data;
- struct xt_node *node = g_new0( struct xt_node, 1 ), *nt;
- int i;
-
- node->parent = xt->cur;
- node->name = g_strdup( element_name );
-
- /* First count the number of attributes */
- for( i = 0; attr_names[i]; i ++ );
-
- /* Then allocate a NULL-terminated array. */
- node->attr = g_new0( struct xt_attr, i + 1 );
-
- /* And fill it, saving one variable by starting at the end. */
- for( i --; i >= 0; i -- )
- {
- node->attr[i].key = g_strdup( attr_names[i] );
- node->attr[i].value = g_strdup( attr_values[i] );
- }
-
- /* Add it to the linked list of children nodes, if we have a current
- node yet. */
- if( xt->cur )
- {
- if( xt->cur->children )
- {
- for( nt = xt->cur->children; nt->next; nt = nt->next );
- nt->next = node;
- }
- else
- {
- xt->cur->children = node;
- }
- }
- else if( xt->root )
- {
- /* ERROR situation: A second root-element??? */
- }
-
- /* Now this node will be the new current node. */
- xt->cur = node;
- /* And maybe this is the root? */
- if( xt->root == NULL )
- xt->root = node;
-}
-
-static void xt_text( GMarkupParseContext *ctx, const gchar *text, gsize text_len, gpointer data, GError **error )
-{
- struct xt_parser *xt = data;
- struct xt_node *node = xt->cur;
-
- if( node == NULL )
- return;
-
- /* FIXME: Does g_renew also OFFICIALLY accept NULL arguments? */
- node->text = g_renew( char, node->text, node->text_len + text_len + 1 );
- memcpy( node->text + node->text_len, text, text_len );
- node->text_len += text_len;
- /* Zero termination is always nice to have. */
- node->text[node->text_len] = 0;
-}
-
-static void xt_end_element( GMarkupParseContext *ctx, const gchar *element_name, gpointer data, GError **error )
-{
- struct xt_parser *xt = data;
-
- xt->cur->flags |= XT_COMPLETE;
- xt->cur = xt->cur->parent;
-}
-
-GMarkupParser xt_parser_funcs =
-{
- xt_start_element,
- xt_end_element,
- xt_text,
- NULL,
- NULL
-};
-
-struct xt_parser *xt_new( gpointer data )
-{
- struct xt_parser *xt = g_new0( struct xt_parser, 1 );
-
- xt->data = data;
- xt_reset( xt );
-
- return xt;
-}
-
-/* Reset the parser, flush everything we have so far. For example, we need
- this for XMPP when doing TLS/SASL to restart the stream. */
-void xt_reset( struct xt_parser *xt )
-{
- if( xt->parser )
- g_markup_parse_context_free( xt->parser );
-
- xt->parser = g_markup_parse_context_new( &xt_parser_funcs, 0, xt, NULL );
-
- if( xt->root )
- {
- xt_free_node( xt->root );
- xt->root = NULL;
- xt->cur = NULL;
- }
-}
-
-/* Feed the parser, don't execute any handler. Returns -1 on errors, 0 on
- end-of-stream and 1 otherwise. */
-int xt_feed( struct xt_parser *xt, char *text, int text_len )
-{
- if( !g_markup_parse_context_parse( xt->parser, text, text_len, &xt->gerr ) )
- {
- return -1;
- }
-
- return !( xt->root && xt->root->flags & XT_COMPLETE );
-}
-
-/* Find completed nodes and see if a handler has to be called. Passing
- a node isn't necessary if you want to start at the root, just pass
- NULL. This second argument is needed for recursive calls. */
-int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth )
-{
- struct xt_node *c;
- xt_status st;
- int i;
-
- /* Just in case someone likes infinite loops... */
- if( xt->root == NULL )
- return 0;
-
- if( node == NULL )
- return xt_handle( xt, xt->root, depth );
-
- if( depth != 0 )
- for( c = node->children; c; c = c->next )
- if( !xt_handle( xt, c, depth > 0 ? depth - 1 : depth ) )
- return 0;
-
- if( node->flags & XT_COMPLETE && !( node->flags & XT_SEEN ) )
- {
- for( i = 0; xt->handlers[i].func; i ++ )
- {
- /* This one is fun! \o/ */
-
- /* If handler.name == NULL it means it should always match. */
- if( ( xt->handlers[i].name == NULL ||
- /* If it's not, compare. There should always be a name. */
- g_strcasecmp( xt->handlers[i].name, node->name ) == 0 ) &&
- /* If handler.parent == NULL, it's a match. */
- ( xt->handlers[i].parent == NULL ||
- /* If there's a parent node, see if the name matches. */
- ( node->parent ? g_strcasecmp( xt->handlers[i].parent, node->parent->name ) == 0 :
- /* If there's no parent, the handler should mention <root> as a parent. */
- g_strcasecmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) )
- {
- st = xt->handlers[i].func( node, xt->data );
-
- if( st == XT_ABORT )
- return 0;
- else if( st != XT_NEXT )
- break;
- }
- }
-
- node->flags |= XT_SEEN;
- }
-
- return 1;
-}
-
-/* Garbage collection: Cleans up all nodes that are handled. Useful for
- streams because there's no reason to keep a complete packet history
- in memory. */
-void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth )
-{
- struct xt_node *c, *prev;
-
- if( !xt || !xt->root )
- return;
-
- if( node == NULL )
- return xt_cleanup( xt, xt->root, depth );
-
- if( node->flags & XT_SEEN && node == xt->root )
- {
- xt_free_node( xt->root );
- xt->root = xt->cur = NULL;
- /* xt->cur should be NULL already, BTW... */
-
- return;
- }
-
- /* c contains the current node, prev the previous node (or NULL).
- I admit, this one's pretty horrible. */
- for( c = node->children, prev = NULL; c; prev = c, c = c ? c->next : node->children )
- {
- if( c->flags & XT_SEEN )
- {
- /* Remove the node from the linked list. */
- if( prev )
- prev->next = c->next;
- else
- node->children = c->next;
-
- xt_free_node( c );
-
- /* Since the for loop wants to get c->next, make sure
- c points at something that exists (and that c->next
- will actually be the next item we should check). c
- can be NULL now, if we just removed the first item.
- That explains the ? thing in for(). */
- c = prev;
- }
- else
- {
- /* This node can't be cleaned up yet, but maybe a
- subnode can. */
- if( depth != 0 )
- xt_cleanup( xt, c, depth > 0 ? depth - 1 : depth );
- }
- }
-}
-
-static void xt_to_string_real( struct xt_node *node, GString *str )
-{
- char *buf;
- struct xt_node *c;
- int i;
-
- g_string_append_printf( str, "<%s", node->name );
-
- for( i = 0; node->attr[i].key; i ++ )
- {
- buf = g_markup_printf_escaped( " %s=\"%s\"", node->attr[i].key, node->attr[i].value );
- g_string_append( str, buf );
- g_free( buf );
- }
-
- if( node->text == NULL && node->children == NULL )
- {
- g_string_append( str, "/>" );
- return;
- }
-
- g_string_append( str, ">" );
- if( node->text_len > 0 )
- {
- buf = g_markup_escape_text( node->text, node->text_len );
- g_string_append( str, buf );
- g_free( buf );
- }
-
- for( c = node->children; c; c = c->next )
- xt_to_string_real( c, str );
-
- g_string_append_printf( str, "</%s>", node->name );
-}
-
-char *xt_to_string( struct xt_node *node )
-{
- GString *ret;
- char *real;
-
- ret = g_string_new( "" );
- xt_to_string_real( node, ret );
-
- real = ret->str;
- g_string_free( ret, FALSE );
-
- return real;
-}
-
-#ifdef DEBUG
-void xt_print( struct xt_node *node )
-{
- int i;
- struct xt_node *c;
-
- /* Indentation */
- for( c = node; c->parent; c = c->parent )
- printf( "\t" );
-
- /* Start the tag */
- printf( "<%s", node->name );
-
- /* Print the attributes */
- for( i = 0; node->attr[i].key; i ++ )
- printf( " %s=\"%s\"", node->attr[i].key, g_markup_escape_text( node->attr[i].value, -1 ) );
-
- /* /> in case there's really *nothing* inside this tag, otherwise
- just >. */
- /* If this tag doesn't have any content at all... */
- if( node->text == NULL && node->children == NULL )
- {
- printf( "/>\n" );
- return;
- /* Then we're finished! */
- }
-
- /* Otherwise... */
- printf( ">" );
-
- /* Only print the text if it contains more than whitespace (TEST). */
- if( node->text_len > 0 )
- {
- for( i = 0; node->text[i] && isspace( node->text[i] ); i ++ );
- if( node->text[i] )
- printf( "%s", g_markup_escape_text( node->text, -1 ) );
- }
-
- if( node->children )
- printf( "\n" );
-
- for( c = node->children; c; c = c->next )
- xt_print( c );
-
- if( node->children )
- for( c = node; c->parent; c = c->parent )
- printf( "\t" );
-
- /* Non-empty tag is now finished. */
- printf( "</%s>\n", node->name );
-}
-#endif
-
-struct xt_node *xt_dup( struct xt_node *node )
-{
- struct xt_node *dup = g_new0( struct xt_node, 1 );
- struct xt_node *c, *dc = NULL;
- int i;
-
- /* Let's NOT copy the parent element here BTW! Only do it for children. */
-
- dup->name = g_strdup( node->name );
- dup->flags = node->flags;
- if( node->text )
- {
- dup->text = g_memdup( node->text, node->text_len + 1 );
- dup->text_len = node->text_len;
- }
-
- /* Count the number of attributes and allocate the new array. */
- for( i = 0; node->attr[i].key; i ++ );
- dup->attr = g_new0( struct xt_attr, i + 1 );
-
- /* Copy them all! */
- for( i --; i >= 0; i -- )
- {
- dup->attr[i].key = g_strdup( node->attr[i].key );
- dup->attr[i].value = g_strdup( node->attr[i].value );
- }
-
- /* This nice mysterious loop takes care of the children. */
- for( c = node->children; c; c = c->next )
- {
- if( dc == NULL )
- dc = dup->children = xt_dup( c );
- else
- dc = ( dc->next = xt_dup( c ) );
-
- dc->parent = dup;
- }
-
- return dup;
-}
-
-/* Frees a node. This doesn't clean up references to itself from parents! */
-void xt_free_node( struct xt_node *node )
-{
- int i;
-
- if( !node )
- return;
-
- g_free( node->name );
- g_free( node->text );
-
- for( i = 0; node->attr[i].key; i ++ )
- {
- g_free( node->attr[i].key );
- g_free( node->attr[i].value );
- }
- g_free( node->attr );
-
- while( node->children )
- {
- struct xt_node *next = node->children->next;
-
- xt_free_node( node->children );
- node->children = next;
- }
-
- g_free( node );
-}
-
-void xt_free( struct xt_parser *xt )
-{
- if( !xt )
- return;
-
- if( xt->root )
- xt_free_node( xt->root );
-
- g_markup_parse_context_free( xt->parser );
-
- g_free( xt );
-}
-
-/* To find a node's child with a specific name, pass the node's children
- list, not the node itself! The reason you have to do this by hand: So
- that you can also use this function as a find-next. */
-struct xt_node *xt_find_node( struct xt_node *node, const char *name )
-{
- while( node )
- {
- if( g_strcasecmp( node->name, name ) == 0 )
- break;
-
- node = node->next;
- }
-
- return node;
-}
-
-char *xt_find_attr( struct xt_node *node, const char *key )
-{
- int i;
-
- if( !node )
- return NULL;
-
- for( i = 0; node->attr[i].key; i ++ )
- if( g_strcasecmp( node->attr[i].key, key ) == 0 )
- break;
-
- return node->attr[i].value;
-}
-
-struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children )
-{
- struct xt_node *node, *c;
-
- node = g_new0( struct xt_node, 1 );
- node->name = g_strdup( name );
- node->children = children;
- node->attr = g_new0( struct xt_attr, 1 );
-
- if( text )
- {
- node->text_len = strlen( text );
- node->text = g_memdup( text, node->text_len + 1 );
- }
-
- for( c = children; c; c = c->next )
- {
- if( c->parent != NULL )
- {
- /* ERROR CONDITION: They seem to have a parent already??? */
- }
-
- c->parent = node;
- }
-
- return node;
-}
-
-void xt_add_child( struct xt_node *parent, struct xt_node *child )
-{
- struct xt_node *node;
-
- /* This function can actually be used to add more than one child, so
- do handle this properly. */
- for( node = child; node; node = node->next )
- {
- if( node->parent != NULL )
- {
- /* ERROR CONDITION: They seem to have a parent already??? */
- }
-
- node->parent = parent;
- }
-
- if( parent->children == NULL )
- {
- parent->children = child;
- }
- else
- {
- for( node = parent->children; node->next; node = node->next );
- node->next = child;
- }
-}
-
-void xt_add_attr( struct xt_node *node, const char *key, const char *value )
-{
- int i;
-
- /* Now actually it'd be nice if we can also change existing attributes
- (which actually means this function doesn't have the right name).
- So let's find out if we have this attribute already... */
- for( i = 0; node->attr[i].key; i ++ )
- if( strcmp( node->attr[i].key, key ) == 0 )
- break;
-
- if( node->attr[i].key == NULL )
- {
- /* If not, allocate space for a new attribute. */
- node->attr = g_renew( struct xt_attr, node->attr, i + 2 );
- node->attr[i].key = g_strdup( key );
- node->attr[i+1].key = NULL;
- }
- else
- {
- /* Otherwise, free the old value before setting the new one. */
- g_free( node->attr[i].value );
- }
-
- node->attr[i].value = g_strdup( value );
-}
-
-int xt_remove_attr( struct xt_node *node, const char *key )
-{
- int i, last;
-
- for( i = 0; node->attr[i].key; i ++ )
- if( strcmp( node->attr[i].key, key ) == 0 )
- break;
-
- /* If we didn't find the attribute... */
- if( node->attr[i].key == NULL )
- return 0;
-
- g_free( node->attr[i].key );
- g_free( node->attr[i].value );
-
- /* If it's the last, this is easy: */
- if( node->attr[i+1].key == NULL )
- {
- node->attr[i].key = node->attr[i].value = NULL;
- }
- else /* It's also pretty easy, actually. */
- {
- /* Find the last item. */
- for( last = i + 1; node->attr[last+1].key; last ++ );
-
- node->attr[i] = node->attr[last];
- node->attr[last].key = NULL;
- node->attr[last].value = NULL;
- }
-
- /* Let's not bother with reallocating memory here. It takes time and
- most packets don't stay in memory for long anyway. */
-
- return 1;
-}
diff --git a/protocols/jabber/xmltree.h b/protocols/jabber/xmltree.h
deleted file mode 100644
index b8b61641..00000000
--- a/protocols/jabber/xmltree.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/***************************************************************************\
-* *
-* BitlBee - An IRC to IM gateway *
-* Simple XML (stream) parse tree handling code (Jabber/XMPP, mainly) *
-* *
-* Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net> *
-* *
-* This library is free software; you can redistribute it and/or *
-* modify it under the terms of the GNU Lesser General Public *
-* License as published by the Free Software Foundation, version *
-* 2.1. *
-* *
-* This library is distributed in the hope that it will be useful, *
-* but WITHOUT ANY WARRANTY; without even the implied warranty of *
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
-* Lesser General Public License for more details. *
-* *
-* You should have received a copy of the GNU Lesser General Public License *
-* along with this library; if not, write to the Free Software Foundation, *
-* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
-* *
-****************************************************************************/
-
-#ifndef _XMLTREE_H
-#define _XMLTREE_H
-
-typedef enum
-{
- XT_COMPLETE = 1, /* </tag> reached */
- XT_SEEN = 2, /* Handler called (or not defined) */
-} xt_flags;
-
-typedef enum
-{
- XT_ABORT, /* Abort, don't handle the rest anymore */
- XT_HANDLED, /* Handled this tag properly, go to the next one */
- XT_NEXT /* Try if there's another matching handler */
-} xt_status;
-
-struct xt_attr
-{
- char *key, *value;
-};
-
-struct xt_node
-{
- struct xt_node *parent;
- struct xt_node *children;
-
- char *name;
- struct xt_attr *attr;
- char *text;
- int text_len;
-
- struct xt_node *next;
- xt_flags flags;
-};
-
-typedef xt_status (*xt_handler_func) ( struct xt_node *node, gpointer data );
-
-struct xt_handler_entry
-{
- char *name, *parent;
- xt_handler_func func;
-};
-
-struct xt_parser
-{
- GMarkupParseContext *parser;
- struct xt_node *root;
- struct xt_node *cur;
-
- struct xt_handler_entry *handlers;
- gpointer data;
-
- GError *gerr;
-};
-
-struct xt_parser *xt_new( gpointer data );
-void xt_reset( struct xt_parser *xt );
-int xt_feed( struct xt_parser *xt, char *text, int text_len );
-int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth );
-void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth );
-char *xt_to_string( struct xt_node *node );
-void xt_print( struct xt_node *node );
-struct xt_node *xt_dup( struct xt_node *node );
-void xt_free_node( struct xt_node *node );
-void xt_free( struct xt_parser *xt );
-struct xt_node *xt_find_node( struct xt_node *node, const char *name );
-char *xt_find_attr( struct xt_node *node, const char *key );
-
-struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children );
-void xt_add_child( struct xt_node *parent, struct xt_node *child );
-void xt_add_attr( struct xt_node *node, const char *key, const char *value );
-int xt_remove_attr( struct xt_node *node, const char *key );
-
-#endif