Index: lib/events_libevent.c
===================================================================
--- lib/events_libevent.c	(revision c6ca3ee33e27feefb8cae0dc1d55a7239baf43cb)
+++ lib/events_libevent.c	(revision 7815a2b57887751a7e026747b27abea04b13abae)
@@ -37,7 +37,9 @@
 
 static void b_main_restart();
-static guint id_next = 1;
+static guint id_next = 1; /* Next ID to be allocated to an event handler. */
+static guint id_cur = 0; /* Event ID that we're currently handling. */
+static guint id_dead; /* Set to 1 if b_event_remove removes id_cur. */
 static GHashTable *id_hash;
-static int quitting = 0;
+static int quitting = 0; /* Prepare to quit, stop handling events. */
 
 /* Since libevent doesn't handle two event handlers for one fd-condition
@@ -119,5 +121,5 @@
 	struct b_event_data *b_ev = data;
 	b_input_condition cond = 0;
-	int id;
+	gboolean st;
 	
 	if( fd >= 0 )
@@ -133,19 +135,28 @@
 	/* Since the called function might cancel this handler already
 	   (which free()s b_ev), we have to remember the ID here. */
-	id = b_ev->id;
+	id_cur = b_ev->id;
+	id_dead = 0;
 	
 	if( quitting )
 	{
-		b_event_remove( id );
+		b_event_remove( id_cur );
 		return;
 	}
 	
-	if( !b_ev->function( b_ev->data, fd, cond ) )
+	st = b_ev->function( b_ev->data, fd, cond );
+	if( id_dead )
+	{
+		/* This event was killed already, don't touch it! */
+		return;
+	}
+	else if( !st )
 	{
 		event_debug( "Handler returned FALSE: " );
-		b_event_remove( id );
+		b_event_remove( id_cur );
 	}
 	else if( fd == -1 )
 	{
+		/* fd == -1 means it was a timer. These can't be auto-repeated
+		   so it has to be recreated every time. */
 		struct timeval tv;
 		
@@ -236,4 +247,7 @@
 	if( b_ev )
 	{
+		if( id == id_cur )
+			id_dead = TRUE;
+		
 		g_hash_table_remove( id_hash, &b_ev->id );
 		if( b_ev->evinfo.ev_fd >= 0 )
Index: lib/http_client.c
===================================================================
--- lib/http_client.c	(revision c6ca3ee33e27feefb8cae0dc1d55a7239baf43cb)
+++ lib/http_client.c	(revision 7815a2b57887751a7e026747b27abea04b13abae)
@@ -59,6 +59,6 @@
 	if( error )
 	{
-		g_free( req );
-		return( NULL );
+		http_free( req );
+		return NULL;
 	}
 	
@@ -160,8 +160,5 @@
 	
 	req->func( req );
-	
-	g_free( req->request );
-	g_free( req );
-	
+	http_free( req );
 	return FALSE;
 }
@@ -444,10 +441,14 @@
 	
 	req->func( req );
-	
+	http_free( req );
+	return FALSE;
+}
+
+void http_free( struct http_request *req )
+{
 	g_free( req->request );
 	g_free( req->reply_headers );
 	g_free( req->status_string );
 	g_free( req );
-	
-	return FALSE;
-}
+}
+
Index: lib/http_client.h
===================================================================
--- lib/http_client.h	(revision c6ca3ee33e27feefb8cae0dc1d55a7239baf43cb)
+++ lib/http_client.h	(revision 7815a2b57887751a7e026747b27abea04b13abae)
@@ -81,2 +81,4 @@
 void *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data );
 void *http_dorequest_url( char *url_string, http_input_function func, gpointer data );
+
+void http_free( struct http_request *req );
Index: lib/ini.c
===================================================================
--- lib/ini.c	(revision c6ca3ee33e27feefb8cae0dc1d55a7239baf43cb)
+++ lib/ini.c	(revision 7815a2b57887751a7e026747b27abea04b13abae)
@@ -2,5 +2,5 @@
   * BitlBee -- An IRC to other IM-networks gateway                     *
   *                                                                    *
-  * Copyright 2002-2005 Wilmer van der Gaast and others                *
+  * Copyright 2002-2008 Wilmer van der Gaast and others                *
   \********************************************************************/
 
@@ -28,63 +28,118 @@
 ini_t *ini_open( char *file )
 {
-	ini_t *ini = g_new0( ini_t, 1 );
+	int fd;
+	ini_t *ini = NULL;
+	struct stat fi;
 	
-	if( ( ini->fp = fopen( file, "r" ) ) == NULL )
+	if( ( fd = open( file, O_RDONLY ) ) != -1 &&
+	    fstat( fd, &fi ) == 0 &&
+	    fi.st_size <= 16384 &&
+	    ( ini = g_malloc( sizeof( ini_t ) + fi.st_size + 1 ) ) &&
+	    read( fd, ini->file, fi.st_size ) == fi.st_size )
 	{
-		g_free( ini );
-		return( NULL );
+		memset( ini, 0, sizeof( ini_t ) );
+		ini->size = fi.st_size;
+		ini->file[ini->size] = 0;
+		ini->cur = ini->file;
+		ini->c_section = "";
+		
+		close( fd );
+		
+		return ini;
 	}
+
+	if( fd >= 0 )
+		close( fd );
 	
-	return( ini );
+	ini_close( ini );
+
+	return NULL;
+}
+
+/* Strips leading and trailing whitespace and returns a pointer to the first
+   non-ws character of the given string. */
+static char *ini_strip_whitespace( char *in )
+{
+	char *e;
+
+	while( isspace( *in ) )
+		in++;
+
+	e = in + strlen( in ) - 1;
+	while( e > in && isspace( *e ) )
+		e--;
+	e[1] = 0;
+	
+	return in;
 }
 
 int ini_read( ini_t *file )
 {
-	char key[MAX_STRING], s[MAX_STRING], *t;
-	int i;
+	char *s;
 	
-	while( !feof( file->fp ) )
+	while( file->cur && file->cur < file->file + file->size )
 	{
-		*s = 0;
-		fscanf( file->fp, "%127[^\n#]s", s );
-		fscanf( file->fp, "%*[^\n]s" );
-		fgetc( file->fp );		/* Skip newline		*/
-		file->line ++;
-		if( strchr( s, '=' ) )
+		char *e, *next;
+		
+		file->line++;
+
+		/* Find the end of line */
+		if( ( e = strchr( file->cur, '\n' ) ) != NULL )
 		{
-			sscanf( s, "%[^ =]s", key );
-			if( ( t = strchr( key, '.' ) ) )
+			*e = 0;
+			next = e + 1;
+		}
+		else
+		{
+			/* No more lines. */
+			e = file->cur + strlen( file->cur );
+			next = NULL;
+		}
+		
+		/* Comment? */
+		if( ( s = strchr( file->cur, '#' ) ) != NULL )
+			*s = 0;
+		
+		file->cur = ini_strip_whitespace( file->cur );
+		
+		if( *file->cur == '[' )
+		{
+			file->cur++;
+			if( ( s = strchr( file->cur, ']' ) ) != NULL )
 			{
-				*t = 0;
-				strcpy( file->section, key );
-				t ++;
+				*s = 0;
+				file->c_section = file->cur;
+			}
+		}
+		else if( ( s = strchr( file->cur, '=' ) ) != NULL )
+		{
+			*s = 0;
+			file->key = ini_strip_whitespace( file->cur );
+			file->value = ini_strip_whitespace( s + 1 );
+			
+			if( ( s = strchr( file->key, '.' ) ) != NULL )
+			{
+				*s = 0;
+				file->section = file->key;
+				file->key = s + 1;
 			}
 			else
 			{
-				strcpy( file->section, file->c_section );
-				t = key;
+				file->section = file->c_section;
 			}
-			sscanf( t, "%s", file->key );
-			t = strchr( s, '=' ) + 1;
-			for( i = 0; t[i] == ' '; i ++ );
-			strcpy( file->value, &t[i] );
-			for( i = strlen( file->value ) - 1; file->value[i] == 32; i -- )
-				file->value[i] = 0;
 			
-			return( 1 );
+			file->cur = next;
+			return 1;
 		}
-		else if( ( t = strchr( s, '[' ) ) )
-		{
-			strcpy( file->c_section, t + 1 );
-			t = strchr( file->c_section, ']' );
-			*t = 0;
-		}
+		/* else: noise/comment/etc, let's just ignore it. */
+
+		file->cur = next;
 	}
-	return( 0 );
+	
+	return 0;
 }
 
 void ini_close( ini_t *file )
 {
-	fclose( file->fp );
 	g_free( file );
 }
Index: lib/ini.h
===================================================================
--- lib/ini.h	(revision c6ca3ee33e27feefb8cae0dc1d55a7239baf43cb)
+++ lib/ini.h	(revision 7815a2b57887751a7e026747b27abea04b13abae)
@@ -29,10 +29,12 @@
 typedef struct
 {
-	FILE *fp;
 	int line;
-	char c_section[MAX_STRING];
-	char section[MAX_STRING];
-	char key[MAX_STRING];
-	char value[MAX_STRING];
+	char *c_section;
+	char *section;
+	char *key;
+	char *value;
+	int size;
+	char *cur, *tok;
+	char file[];
 } ini_t;
 
Index: lib/misc.c
===================================================================
--- lib/misc.c	(revision c6ca3ee33e27feefb8cae0dc1d55a7239baf43cb)
+++ lib/misc.c	(revision 7815a2b57887751a7e026747b27abea04b13abae)
@@ -47,4 +47,5 @@
 #endif
 
+#include "md5.h"
 #include "ssl_client.h"
 
@@ -89,4 +90,5 @@
 	{ "gt",     ">" },
 	{ "amp",    "&" },
+	{ "apos",   "'" },
 	{ "quot",   "\"" },
 	{ "aacute", "á" },
Index: lib/proxy.c
===================================================================
--- lib/proxy.c	(revision c6ca3ee33e27feefb8cae0dc1d55a7239baf43cb)
+++ lib/proxy.c	(revision 7815a2b57887751a7e026747b27abea04b13abae)
@@ -558,5 +558,4 @@
 		return proxy_connect_socks5(host, port, phb);
 	
-	if (phb->host) g_free(phb);
 	g_free(phb);
 	return -1;
Index: lib/xmltree.c
===================================================================
--- lib/xmltree.c	(revision c6ca3ee33e27feefb8cae0dc1d55a7239baf43cb)
+++ lib/xmltree.c	(revision 7815a2b57887751a7e026747b27abea04b13abae)
@@ -472,5 +472,5 @@
 }
 
-struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children )
+struct xt_node *xt_new_node( char *name, const char *text, struct xt_node *children )
 {
 	struct xt_node *node, *c;
Index: lib/xmltree.h
===================================================================
--- lib/xmltree.h	(revision c6ca3ee33e27feefb8cae0dc1d55a7239baf43cb)
+++ lib/xmltree.h	(revision 7815a2b57887751a7e026747b27abea04b13abae)
@@ -90,5 +90,5 @@
 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 );
+struct xt_node *xt_new_node( char *name, const 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 );
