Index: Makefile
===================================================================
--- Makefile	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ Makefile	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -10,7 +10,7 @@
 
 # Program variables
-objects = account.o bitlbee.o conf.o crypting.o help.o ini.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_text.o storage_xml.o unix.o url.o user.o util.o
+objects = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_text.o storage_xml.o unix.o user.o
 headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ini.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h url.h user.h protocols/http_client.h protocols/md5.h protocols/nogaim.h protocols/proxy.h protocols/sha.h protocols/ssl_client.h
-subdirs = protocols
+subdirs = protocols lib
 
 objects += $(LDAP_OBJ)
Index: bitlbee.h
===================================================================
--- bitlbee.h	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ bitlbee.h	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -130,5 +130,5 @@
 #include "query.h"
 #include "sock.h"
-#include "util.h"
+#include "misc.h"
 #include "proxy.h"
 
Index: conf.c
===================================================================
--- conf.c	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ conf.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -34,5 +34,5 @@
 #include "ipc.h"
 
-#include "protocols/proxy.h"
+#include "proxy.h"
 
 char *CONF_FILE;
Index: configure
===================================================================
--- configure	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ configure	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -144,5 +144,5 @@
 fi
 
-echo CFLAGS+=-I`pwd` -I`pwd`/protocols -I. >> Makefile.settings
+echo CFLAGS+=-I`pwd` -I`pwd`/lib -I`pwd`/protocols -I. >> Makefile.settings
 
 echo CFLAGS+=-DHAVE_CONFIG_H >> Makefile.settings
Index: i.c
===================================================================
--- ini.c	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,90 +1,0 @@
-  /********************************************************************\
-  * BitlBee -- An IRC to other IM-networks gateway                     *
-  *                                                                    *
-  * Copyright 2002-2005 Wilmer van der Gaast and others                *
-  \********************************************************************/
-
-/* INI file reading code						*/
-
-/*
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program 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 General Public License for more details.
-
-  You should have received a copy of the GNU General Public License with
-  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
-  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
-  Suite 330, Boston, MA  02111-1307  USA
-*/
-#define BITLBEE_CORE
-#include "bitlbee.h"
-
-ini_t *ini_open( char *file )
-{
-	ini_t *ini = g_new0( ini_t, 1 );
-	
-	if( ( ini->fp = fopen( file, "r" ) ) == NULL )
-	{
-		g_free( ini );
-		return( NULL );
-	}
-	
-	return( ini );
-}
-
-int ini_read( ini_t *file )
-{
-	char key[MAX_STRING], s[MAX_STRING], *t;
-	int i;
-	
-	while( !feof( file->fp ) )
-	{
-		*s = 0;
-		fscanf( file->fp, "%127[^\n#]s", s );
-		fscanf( file->fp, "%*[^\n]s" );
-		fgetc( file->fp );		/* Skip newline		*/
-		file->line ++;
-		if( strchr( s, '=' ) )
-		{
-			sscanf( s, "%[^ =]s", key );
-			if( ( t = strchr( key, '.' ) ) )
-			{
-				*t = 0;
-				strcpy( file->section, key );
-				t ++;
-			}
-			else
-			{
-				strcpy( file->section, file->c_section );
-				t = key;
-			}
-			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 );
-		}
-		else if( ( t = strchr( s, '[' ) ) )
-		{
-			strcpy( file->c_section, t + 1 );
-			t = strchr( file->c_section, ']' );
-			*t = 0;
-		}
-	}
-	return( 0 );
-}
-
-void ini_close( ini_t *file )
-{
-	fclose( file->fp );
-	g_free( file );
-}
Index: i.h
===================================================================
--- ini.h	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,43 +1,0 @@
-  /********************************************************************\
-  * BitlBee -- An IRC to other IM-networks gateway                     *
-  *                                                                    *
-  * Copyright 2002-2004 Wilmer van der Gaast and others                *
-  \********************************************************************/
-
-/* INI file reading code						*/
-
-/*
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program 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 General Public License for more details.
-
-  You should have received a copy of the GNU General Public License with
-  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
-  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
-  Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#ifndef _INI_H
-#define _INI_H
-
-typedef struct
-{
-	FILE *fp;
-	int line;
-	char c_section[MAX_STRING];
-	char section[MAX_STRING];
-	char key[MAX_STRING];
-	char value[MAX_STRING];
-} ini_t;
-
-ini_t *ini_open( char *file );
-int ini_read( ini_t *file );
-void ini_close( ini_t *file );
-
-#endif
Index: irc_commands.c
===================================================================
--- irc_commands.c	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ irc_commands.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -321,5 +321,5 @@
 {
 	user_t *u;
-	char buff[IRC_MAX_LINE], *s;
+	char buff[IRC_MAX_LINE];
 	int lenleft, i;
 	
Index: lib/Makefile
===================================================================
--- lib/Makefile	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/Makefile	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,37 @@
+###########################
+## Makefile for BitlBee  ##
+##                       ##
+## Copyright 2006 Lintux ##
+###########################
+
+### DEFINITIONS
+
+-include ../Makefile.settings
+
+# [SH] Program variables
+objects = $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o rc4.o sha.o $(SSL_CLIENT) url.o
+
+CFLAGS += -Wall
+LFLAGS += -r
+
+# [SH] Phony targets
+all: lib.o
+
+.PHONY: all clean distclean
+
+clean: $(subdirs)
+	rm -f *.o $(OUTFILE) core
+
+distclean: clean $(subdirs)
+
+### MAIN PROGRAM
+
+lib.o: $(objects) $(subdirs)
+	@echo '*' Linking lib.o
+	@$(LD) $(LFLAGS) $(objects) -o lib.o
+
+$(objects): ../Makefile.settings Makefile
+
+$(objects): %.o: %.c
+	@echo '*' Compiling $<
+	@$(CC) -c $(CFLAGS) $< -o $@
Index: lib/events.h
===================================================================
--- lib/events.h	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/events.h	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,66 @@
+/*
+ * nogaim
+ *
+ * Copyright (C) 2006 Wilmer van der Gaast and others
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+ * Split off the event handling things from proxy.[ch] (and adding timer
+ * stuff. This to allow BitlBee to use other libs than GLib for event
+ * handling.
+ */
+
+
+#ifndef _EVENTS_H_
+#define _EVENTS_H_
+
+#include <sys/types.h>
+#ifndef _WIN32
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#endif
+#include <glib.h>
+#include <gmodule.h>
+
+typedef enum {
+	GAIM_INPUT_READ = 1 << 1,
+	GAIM_INPUT_WRITE = 1 << 2
+} b_input_condition;
+typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition cond);
+
+#define GAIM_READ_COND  (G_IO_IN | G_IO_HUP | G_IO_ERR)
+#define GAIM_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
+#define GAIM_ERR_COND   (G_IO_HUP | G_IO_ERR | G_IO_NVAL)
+
+// #define event_debug( x... ) printf( x )
+#define event_debug( x... )
+
+G_MODULE_EXPORT void b_main_init();
+G_MODULE_EXPORT void b_main_run();
+G_MODULE_EXPORT void b_main_quit();
+
+G_MODULE_EXPORT gint b_input_add(int fd, b_input_condition cond, b_event_handler func, gpointer data);
+G_MODULE_EXPORT gint b_timeout_add(gint timeout, b_event_handler func, gpointer data);
+G_MODULE_EXPORT void b_event_remove(gint id);
+
+#ifdef EVENTS_LIBEVENT
+G_MODULE_EXPORT void closesocket(int fd);
+#endif
+
+#endif /* _EVENTS_H_ */
Index: lib/events_glib.c
===================================================================
--- lib/events_glib.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/events_glib.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,137 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2006 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/*
+ * Event handling (using GLib)
+ */
+
+/*
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#define BITLBEE_CORE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#ifndef _WIN32
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#else
+#include "sock.h"
+#define ETIMEDOUT WSAETIMEDOUT
+#define EINPROGRESS WSAEINPROGRESS
+#endif
+#include <fcntl.h>
+#include <errno.h>
+#include "proxy.h"
+
+typedef struct _GaimIOClosure {
+	b_event_handler function;
+	guint result;
+	gpointer data;
+} GaimIOClosure;
+
+static GMainLoop *loop;
+
+void b_main_init()
+{
+	loop = g_main_new( FALSE );
+}
+
+void b_main_run()
+{
+	g_main_run( loop );
+}
+
+void b_main_quit()
+{
+	g_main_quit( loop );
+}
+
+static gboolean gaim_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data)
+{
+	GaimIOClosure *closure = data;
+	b_input_condition gaim_cond = 0;
+	gboolean st;
+
+	if (condition & GAIM_READ_COND)
+		gaim_cond |= GAIM_INPUT_READ;
+	if (condition & GAIM_WRITE_COND)
+		gaim_cond |= GAIM_INPUT_WRITE;
+	
+	event_debug( "gaim_io_invoke( %d, %d, 0x%x )\n", g_io_channel_unix_get_fd(source), condition, data );
+
+	st = closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond);
+	
+	if( !st )
+		event_debug( "Returned FALSE, cancelling.\n" );
+	
+	return st;
+}
+
+static void gaim_io_destroy(gpointer data)
+{
+	event_debug( "gaim_io_destroy( 0x%x )\n", data );
+	g_free(data);
+}
+
+gint b_input_add(gint source, b_input_condition condition, b_event_handler function, gpointer data)
+{
+	GaimIOClosure *closure = g_new0(GaimIOClosure, 1);
+	GIOChannel *channel;
+	GIOCondition cond = 0;
+	
+	closure->function = function;
+	closure->data = data;
+	
+	if (condition & GAIM_INPUT_READ)
+		cond |= GAIM_READ_COND;
+	if (condition & GAIM_INPUT_WRITE)
+		cond |= GAIM_WRITE_COND;
+	
+	channel = g_io_channel_unix_new(source);
+	closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond,
+					      gaim_io_invoke, closure, gaim_io_destroy);
+	
+	event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) = %d (0x%x)\n", source, condition, function, data, closure->result, closure );
+	
+	g_io_channel_unref(channel);
+	return closure->result;
+}
+
+gint b_timeout_add(gint timeout, b_event_handler func, gpointer data)
+{
+	gint st = g_timeout_add(timeout, func, data);
+	
+	event_debug( "b_timeout_add( %d, %d, %d ) = %d\n", timeout, func, data, st );
+	
+	return st;
+}
+
+void b_event_remove(gint tag)
+{
+	event_debug( "b_event_remove( %d )\n", tag );
+	
+	if (tag > 0)
+		g_source_remove(tag);
+}
Index: lib/events_libevent.c
===================================================================
--- lib/events_libevent.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/events_libevent.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,247 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2006 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/*
+ * Event handling (using libevent)
+ */
+
+/*
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#define BITLBEE_CORE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include "proxy.h"
+
+#include <sys/time.h>
+#include <event.h>
+
+static guint id_next;
+static GHashTable *id_hash;
+static int quitting = 0;
+
+/* Since libevent doesn't handle two event handlers for one fd-condition
+   very well (which happens sometimes when BitlBee changes event handlers
+   for a combination), let's buid some indexes so we can delete them here
+   already, just in time. */
+static GHashTable *read_hash;
+static GHashTable *write_hash;
+
+struct b_event_data
+{
+	guint id;
+	struct event evinfo;
+	gint timeout;
+	b_event_handler function;
+	void *data;
+};
+
+void b_main_init()
+{
+	event_init();
+	
+	id_next = 1;
+	id_hash = g_hash_table_new( g_int_hash, g_int_equal );
+	read_hash = g_hash_table_new( g_int_hash, g_int_equal );
+	write_hash = g_hash_table_new( g_int_hash, g_int_equal );
+}
+
+void b_main_run()
+{
+	event_dispatch();
+}
+
+void b_main_quit()
+{
+	struct timeval tv;
+	
+	/* libevent sometimes generates events before really quitting,
+	   we want to stop them. */
+	quitting = 1;
+	
+	memset( &tv, 0, sizeof( struct timeval ) );
+	event_loopexit( &tv );
+}
+
+static void b_event_passthrough( int fd, short event, void *data )
+{
+	struct b_event_data *b_ev = data;
+	b_input_condition cond = 0;
+	int id;
+	
+	if( fd >= 0 )
+	{
+		if( event & EV_READ )
+			cond |= GAIM_INPUT_READ;
+		if( event & EV_WRITE )
+			cond |= GAIM_INPUT_WRITE;
+	}
+	
+	event_debug( "b_event_passthrough( %d, %d, 0x%x ) (%d)\n", fd, event, (int) data, b_ev->id );
+	
+	/* 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;
+	
+	if( quitting )
+	{
+		b_event_remove( id );
+		return;
+	}
+	
+	if( !b_ev->function( b_ev->data, fd, cond ) )
+	{
+		event_debug( "Handler returned FALSE: " );
+		b_event_remove( id );
+	}
+	else if( fd == -1 )
+	{
+		struct timeval tv;
+		
+		tv.tv_sec = b_ev->timeout / 1000;
+		tv.tv_usec = ( b_ev->timeout % 1000 ) * 1000;
+		
+		evtimer_add( &b_ev->evinfo, &tv );
+	}
+}
+
+gint b_input_add( gint fd, b_input_condition condition, b_event_handler function, gpointer data )
+{
+	struct b_event_data *b_ev;
+	
+	event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) ", fd, condition, function, data );
+	
+	if( ( condition & GAIM_INPUT_READ  && ( b_ev = g_hash_table_lookup( read_hash,  &fd ) ) ) ||
+	    ( condition & GAIM_INPUT_WRITE && ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) )
+	{
+		/* We'll stick with this libevent entry, but give it a new BitlBee id. */
+		g_hash_table_remove( id_hash, &b_ev->id );
+		
+		event_debug( "(replacing old handler (id = %d)) = %d\n", b_ev->id, id_next );
+		
+		b_ev->id = id_next++;
+		b_ev->function = function;
+		b_ev->data = data;
+	}
+	else
+	{
+		GIOCondition out_cond;
+		
+		event_debug( "(new) = %d\n", id_next );
+		
+		b_ev = g_new0( struct b_event_data, 1 );
+		b_ev->id = id_next++;
+		b_ev->function = function;
+		b_ev->data = data;
+		
+		out_cond = EV_PERSIST;
+		if( condition & GAIM_INPUT_READ )
+			out_cond |= EV_READ;
+		if( condition & GAIM_INPUT_WRITE )
+			out_cond |= EV_WRITE;
+		
+		event_set( &b_ev->evinfo, fd, out_cond, b_event_passthrough, b_ev );
+		event_add( &b_ev->evinfo, NULL );
+		
+		if( out_cond & EV_READ )
+			g_hash_table_insert( read_hash, &b_ev->evinfo.ev_fd, b_ev );
+		if( out_cond & EV_WRITE )
+			g_hash_table_insert( write_hash, &b_ev->evinfo.ev_fd, b_ev );
+	}
+	
+	g_hash_table_insert( id_hash, &b_ev->id, b_ev );
+	return b_ev->id;
+}
+
+/* TODO: Persistence for timers! */
+gint b_timeout_add( gint timeout, b_event_handler function, gpointer data )
+{
+	struct b_event_data *b_ev = g_new0( struct b_event_data, 1 );
+	struct timeval tv;
+	
+	b_ev->id = id_next++;
+	b_ev->timeout = timeout;
+	b_ev->function = function;
+	b_ev->data = data;
+	
+	tv.tv_sec = timeout / 1000;
+	tv.tv_usec = ( timeout % 1000 ) * 1000;
+	
+	evtimer_set( &b_ev->evinfo, b_event_passthrough, b_ev );
+	evtimer_add( &b_ev->evinfo, &tv );
+	
+	event_debug( "b_timeout_add( %d, 0x%x, 0x%x ) = %d\n", timeout, function, data, b_ev->id );
+	
+	g_hash_table_insert( id_hash, &b_ev->id, b_ev );
+	
+	return b_ev->id;
+}
+
+void b_event_remove( gint id )
+{
+	struct b_event_data *b_ev = g_hash_table_lookup( id_hash, &id );
+	
+	event_debug( "b_event_remove( %d )\n", id );
+	if( b_ev )
+	{
+		g_hash_table_remove( id_hash, &b_ev->id );
+		if( b_ev->evinfo.ev_fd >= 0 )
+		{
+			if( b_ev->evinfo.ev_events & EV_READ )
+				g_hash_table_remove( read_hash, &b_ev->evinfo.ev_fd );
+			if( b_ev->evinfo.ev_events & EV_WRITE )
+				g_hash_table_remove( write_hash, &b_ev->evinfo.ev_fd );
+		}
+		
+		event_del( &b_ev->evinfo );
+		g_free( b_ev );
+	}
+	else
+	{
+		event_debug( "Already removed?\n" );
+	}
+}
+
+void closesocket( int fd )
+{
+	struct b_event_data *b_ev;
+	
+	/* Since epoll() (the main reason we use libevent) automatically removes sockets from
+	   the epoll() list when a socket gets closed and some modules have a habit of
+	   closing sockets before removing event handlers, our and libevent's administration
+	   get a little bit messed up. So this little function will remove the handlers
+	   properly before closing a socket. */
+	
+	if( ( b_ev = g_hash_table_lookup( read_hash, &fd ) ) )
+	{
+		event_debug( "Warning: fd %d still had a read event handler when shutting down.\n", fd );
+		b_event_remove( b_ev->id );
+	}
+	if( ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) )
+	{
+		event_debug( "Warning: fd %d still had a write event handler when shutting down.\n", fd );
+		b_event_remove( b_ev->id );
+	}
+	
+	close( fd );
+}
Index: lib/http_client.c
===================================================================
--- lib/http_client.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/http_client.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,453 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2005 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/* HTTP(S) module                                                       */
+
+/*
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <string.h>
+#include <stdio.h>
+
+#include "http_client.h"
+#include "url.h"
+#include "sock.h"
+
+
+static gboolean http_connected( gpointer data, int source, b_input_condition cond );
+static gboolean http_ssl_connected( gpointer data, void *source, b_input_condition cond );
+static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond );
+
+
+void *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data )
+{
+	struct http_request *req;
+	int error = 0;
+	
+	req = g_new0( struct http_request, 1 );
+	
+	if( ssl )
+	{
+		req->ssl = ssl_connect( host, port, http_ssl_connected, req );
+		if( req->ssl == NULL )
+			error = 1;
+	}
+	else
+	{
+		req->fd = proxy_connect( host, port, http_connected, req );
+		if( req->fd < 0 )
+			error = 1;
+	}
+	
+	if( error )
+	{
+		g_free( req );
+		return( NULL );
+	}
+	
+	req->func = func;
+	req->data = data;
+	req->request = g_strdup( request );
+	req->request_length = strlen( request );
+	
+	return( req );
+}
+
+void *http_dorequest_url( char *url_string, http_input_function func, gpointer data )
+{
+	url_t *url = g_new0( url_t, 1 );
+	char *request;
+	void *ret;
+	
+	if( !url_set( url, url_string ) )
+	{
+		g_free( url );
+		return NULL;
+	}
+	
+	if( url->proto != PROTO_HTTP && url->proto != PROTO_HTTPS )
+	{
+		g_free( url );
+		return NULL;
+	}
+	
+	request = g_strdup_printf( "GET %s HTTP/1.0\r\n"
+	                           "Host: %s\r\n"
+	                           "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n"
+	                           "\r\n", url->file, url->host );
+	
+	ret = http_dorequest( url->host, url->port,
+	                      url->proto == PROTO_HTTPS, request, func, data );
+	
+	g_free( url );
+	g_free( request );
+	return ret;
+}
+
+/* This one is actually pretty simple... Might get more calls if we can't write 
+   the whole request at once. */
+static gboolean http_connected( gpointer data, int source, b_input_condition cond )
+{
+	struct http_request *req = data;
+	int st;
+	
+	if( source < 0 )
+		goto error;
+	
+	if( req->inpa > 0 )
+		b_event_remove( req->inpa );
+	
+	sock_make_nonblocking( req->fd );
+	
+	if( req->ssl )
+	{
+		st = ssl_write( req->ssl, req->request + req->bytes_written,
+		                req->request_length - req->bytes_written );
+		if( st < 0 )
+		{
+			if( ssl_errno != SSL_AGAIN )
+			{
+				ssl_disconnect( req->ssl );
+				goto error;
+			}
+		}
+	}
+	else
+	{
+		st = write( source, req->request + req->bytes_written,
+		                    req->request_length - req->bytes_written );
+		if( st < 0 )
+		{
+			if( !sockerr_again() )
+			{
+				closesocket( req->fd );
+				goto error;
+			}
+		}
+	}
+	
+	if( st > 0 )
+		req->bytes_written += st;
+	
+	if( req->bytes_written < req->request_length )
+		req->inpa = b_input_add( source,
+		                         req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_WRITE,
+	        	                 http_connected, req );
+	else
+		req->inpa = b_input_add( source, GAIM_INPUT_READ, http_incoming_data, req );
+	
+	return FALSE;
+	
+error:
+	req->status_string = g_strdup( "Error while writing HTTP request" );
+	
+	req->func( req );
+	
+	g_free( req->request );
+	g_free( req );
+	
+	return FALSE;
+}
+
+static gboolean http_ssl_connected( gpointer data, void *source, b_input_condition cond )
+{
+	struct http_request *req = data;
+	
+	if( source == NULL )
+		return http_connected( data, -1, cond );
+	
+	req->fd = ssl_getfd( source );
+	
+	return http_connected( data, req->fd, cond );
+}
+
+static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond )
+{
+	struct http_request *req = data;
+	int evil_server = 0;
+	char buffer[2048];
+	char *end1, *end2;
+	int st;
+	
+	if( req->inpa > 0 )
+		b_event_remove( req->inpa );
+	
+	if( req->ssl )
+	{
+		st = ssl_read( req->ssl, buffer, sizeof( buffer ) );
+		if( st < 0 )
+		{
+			if( ssl_errno != SSL_AGAIN )
+			{
+				/* goto cleanup; */
+				
+				/* YAY! We have to deal with crappy Microsoft
+				   servers that LOVE to send invalid TLS
+				   packets that abort connections! \o/ */
+				
+				goto got_reply;
+			}
+		}
+		else if( st == 0 )
+		{
+			goto got_reply;
+		}
+	}
+	else
+	{
+		st = read( req->fd, buffer, sizeof( buffer ) );
+		if( st < 0 )
+		{
+			if( !sockerr_again() )
+			{
+				req->status_string = g_strdup( strerror( errno ) );
+				goto cleanup;
+			}
+		}
+		else if( st == 0 )
+		{
+			goto got_reply;
+		}
+	}
+	
+	if( st > 0 )
+	{
+		req->reply_headers = g_realloc( req->reply_headers, req->bytes_read + st + 1 );
+		memcpy( req->reply_headers + req->bytes_read, buffer, st );
+		req->bytes_read += st;
+	}
+	
+	/* There will be more! */
+	req->inpa = b_input_add( req->fd,
+	                         req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_READ,
+	                         http_incoming_data, req );
+	
+	return FALSE;
+
+got_reply:
+	/* Maybe if the webserver is overloaded, or when there's bad SSL
+	   support... */
+	if( req->bytes_read == 0 )
+	{
+		req->status_string = g_strdup( "Empty HTTP reply" );
+		goto cleanup;
+	}
+	
+	/* Zero termination is very convenient. */
+	req->reply_headers[req->bytes_read] = 0;
+	
+	/* Find the separation between headers and body, and keep stupid
+	   webservers in mind. */
+	end1 = strstr( req->reply_headers, "\r\n\r\n" );
+	end2 = strstr( req->reply_headers, "\n\n" );
+	
+	if( end2 && end2 < end1 )
+	{
+		end1 = end2 + 1;
+		evil_server = 1;
+	}
+	else if( end1 )
+	{
+		end1 += 2;
+	}
+	else
+	{
+		req->status_string = g_strdup( "Malformed HTTP reply" );
+		goto cleanup;
+	}
+	
+	*end1 = 0;
+	
+	if( evil_server )
+		req->reply_body = end1 + 1;
+	else
+		req->reply_body = end1 + 2;
+	
+	req->body_size = req->reply_headers + req->bytes_read - req->reply_body;
+	
+	if( ( end1 = strchr( req->reply_headers, ' ' ) ) != NULL )
+	{
+		if( sscanf( end1 + 1, "%d", &req->status_code ) != 1 )
+		{
+			req->status_string = g_strdup( "Can't parse status code" );
+			req->status_code = -1;
+		}
+		else
+		{
+			char *eol;
+			
+			if( evil_server )
+				eol = strchr( end1, '\n' );
+			else
+				eol = strchr( end1, '\r' );
+			
+			req->status_string = g_strndup( end1 + 1, eol - end1 - 1 );
+			
+			/* Just to be sure... */
+			if( ( eol = strchr( req->status_string, '\r' ) ) )
+				*eol = 0;
+			if( ( eol = strchr( req->status_string, '\n' ) ) )
+				*eol = 0;
+		}
+	}
+	else
+	{
+		req->status_string = g_strdup( "Can't locate status code" );
+		req->status_code = -1;
+	}
+	
+	if( req->status_code == 301 || req->status_code == 302 )
+	{
+		char *loc, *new_request, *new_host;
+		int error = 0, new_port, new_proto;
+		
+		/* We might fill it again, so let's not leak any memory. */
+		g_free( req->status_string );
+		req->status_string = NULL;
+		
+		loc = strstr( req->reply_headers, "\nLocation: " );
+		if( loc == NULL ) /* We can't handle this redirect... */
+		{
+			req->status_string = g_strdup( "Can't locate Location: header" );
+			goto cleanup;
+		}
+		
+		loc += 11;
+		while( *loc == ' ' )
+			loc ++;
+		
+		/* TODO/FIXME: Possibly have to handle relative redirections,
+		   and rewrite Host: headers. Not necessary for now, it's
+		   enough for passport authentication like this. */
+		
+		if( *loc == '/' )
+		{
+			/* Just a different pathname... */
+			
+			/* Since we don't cache the servername, and since we
+			   don't need this yet anyway, I won't implement it. */
+			
+			req->status_string = g_strdup( "Can't handle recursive redirects" );
+			
+			goto cleanup;
+		}
+		else
+		{
+			/* A whole URL */
+			url_t *url;
+			char *s;
+			
+			s = strstr( loc, "\r\n" );
+			if( s == NULL )
+				goto cleanup;
+			
+			url = g_new0( url_t, 1 );
+			*s = 0;
+			
+			if( !url_set( url, loc ) )
+			{
+				req->status_string = g_strdup( "Malformed redirect URL" );
+				g_free( url );
+				goto cleanup;
+			}
+			
+			/* Okay, this isn't fun! We have to rebuild the request... :-( */
+			new_request = g_malloc( req->request_length + strlen( url->file ) );
+			
+			/* So, now I just allocated enough memory, so I'm
+			   going to use strcat(), whether you like it or not. :-) */
+			
+			sprintf( new_request, "GET %s HTTP/1.0", url->file );
+			
+			s = strstr( req->request, "\r\n" );
+			if( s == NULL )
+			{
+				req->status_string = g_strdup( "Error while rebuilding request string" );
+				g_free( new_request );
+				g_free( url );
+				goto cleanup;
+			}
+			
+			strcat( new_request, s );
+			new_host = g_strdup( url->host );
+			new_port = url->port;
+			new_proto = url->proto;
+			
+			g_free( url );
+		}
+		
+		if( req->ssl )
+			ssl_disconnect( req->ssl );
+		else
+			closesocket( req->fd );
+		
+		req->fd = -1;
+		req->ssl = NULL;
+		
+		if( new_proto == PROTO_HTTPS )
+		{
+			req->ssl = ssl_connect( new_host, new_port, http_ssl_connected, req );
+			if( req->ssl == NULL )
+				error = 1;
+		}
+		else
+		{
+			req->fd = proxy_connect( new_host, new_port, http_connected, req );
+			if( req->fd < 0 )
+				error = 1;
+		}
+		g_free( new_host );
+		
+		if( error )
+		{
+			req->status_string = g_strdup( "Connection problem during redirect" );
+			g_free( new_request );
+			goto cleanup;
+		}
+		
+		g_free( req->request );
+		g_free( req->reply_headers );
+		req->request = new_request;
+		req->request_length = strlen( new_request );
+		req->bytes_read = req->bytes_written = req->inpa = 0;
+		req->reply_headers = req->reply_body = NULL;
+		
+		return FALSE;
+	}
+	
+	/* Assume that a closed connection means we're finished, this indeed
+	   breaks with keep-alive connections and faulty connections. */
+	req->finished = 1;
+
+cleanup:
+	if( req->ssl )
+		ssl_disconnect( req->ssl );
+	else
+		closesocket( req->fd );
+	
+	req->func( 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 df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/http_client.h	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,57 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2005 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/* HTTP(S) module                                                       */
+
+/*
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <glib.h>
+
+#include "ssl_client.h"
+
+struct http_request;
+
+typedef void (*http_input_function)( struct http_request * );
+
+struct http_request
+{
+	char *request;
+	int request_length;
+	int status_code;
+	char *status_string;
+	char *reply_headers;
+	char *reply_body;
+	int body_size;
+	int finished;
+	
+	void *ssl;
+	int fd;
+	
+	int inpa;
+	int bytes_written;
+	int bytes_read;
+	
+	http_input_function func;
+	gpointer data;
+};
+
+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 );
Index: lib/ini.c
===================================================================
--- lib/ini.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/ini.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,90 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2005 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/* INI file reading code						*/
+
+/*
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+#define BITLBEE_CORE
+#include "bitlbee.h"
+
+ini_t *ini_open( char *file )
+{
+	ini_t *ini = g_new0( ini_t, 1 );
+	
+	if( ( ini->fp = fopen( file, "r" ) ) == NULL )
+	{
+		g_free( ini );
+		return( NULL );
+	}
+	
+	return( ini );
+}
+
+int ini_read( ini_t *file )
+{
+	char key[MAX_STRING], s[MAX_STRING], *t;
+	int i;
+	
+	while( !feof( file->fp ) )
+	{
+		*s = 0;
+		fscanf( file->fp, "%127[^\n#]s", s );
+		fscanf( file->fp, "%*[^\n]s" );
+		fgetc( file->fp );		/* Skip newline		*/
+		file->line ++;
+		if( strchr( s, '=' ) )
+		{
+			sscanf( s, "%[^ =]s", key );
+			if( ( t = strchr( key, '.' ) ) )
+			{
+				*t = 0;
+				strcpy( file->section, key );
+				t ++;
+			}
+			else
+			{
+				strcpy( file->section, file->c_section );
+				t = key;
+			}
+			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 );
+		}
+		else if( ( t = strchr( s, '[' ) ) )
+		{
+			strcpy( file->c_section, t + 1 );
+			t = strchr( file->c_section, ']' );
+			*t = 0;
+		}
+	}
+	return( 0 );
+}
+
+void ini_close( ini_t *file )
+{
+	fclose( file->fp );
+	g_free( file );
+}
Index: lib/ini.h
===================================================================
--- lib/ini.h	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/ini.h	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,43 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2004 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/* INI file reading code						*/
+
+/*
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _INI_H
+#define _INI_H
+
+typedef struct
+{
+	FILE *fp;
+	int line;
+	char c_section[MAX_STRING];
+	char section[MAX_STRING];
+	char key[MAX_STRING];
+	char value[MAX_STRING];
+} ini_t;
+
+ini_t *ini_open( char *file );
+int ini_read( ini_t *file );
+void ini_close( ini_t *file );
+
+#endif
Index: lib/md5.c
===================================================================
--- lib/md5.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/md5.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,392 @@
+/*
+  Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  L. Peter Deutsch
+  ghost@aladdin.com
+
+ */
+/*
+  Independent implementation of MD5 (RFC 1321).
+
+  This code implements the MD5 Algorithm defined in RFC 1321.
+  It is derived directly from the text of the RFC and not from the
+  reference implementation.
+
+  The original and principal author of md5.c is L. Peter Deutsch
+  <ghost@aladdin.com>.  Other authors are noted in the change history
+  that follows (in reverse chronological order):
+
+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+  1999-05-03 lpd Original version.
+ */
+
+#include "md5.h"
+#include <string.h>
+
+#ifdef TEST
+/*
+ * Compile with -DTEST to create a self-contained executable test program.
+ * The test program should print out the same values as given in section
+ * A.5 of RFC 1321, reproduced below.
+ */
+#include <string.h>
+main()
+{
+    static const char *const test[7] = {
+	"", /*d41d8cd98f00b204e9800998ecf8427e*/
+	"945399884.61923487334tuvga", /*0cc175b9c0f1b6a831c399e269772661*/
+	"abc", /*900150983cd24fb0d6963f7d28e17f72*/
+	"message digest", /*f96b697d7cb7938d525a2f31aaf161d0*/
+	"abcdefghijklmnopqrstuvwxyz", /*c3fcd3d76192e4007dfb496cca67e13b*/
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+				/*d174ab98d277d9f5a5611c2c9f419d9f*/
+	"12345678901234567890123456789012345678901234567890123456789012345678901234567890" /*57edf4a22be3c955ac49da2e2107b67a*/
+    };
+    int i;
+
+    for (i = 0; i < 7; ++i) {
+	md5_state_t state;
+	md5_byte_t digest[16];
+	int di;
+
+	md5_init(&state);
+	md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i]));
+	md5_finish(&state, digest);
+	printf("MD5 (\"%s\") = ", test[i]);
+	for (di = 0; di < 16; ++di)
+	    printf("%02x", digest[di]);
+	printf("\n");
+    }
+    return 0;
+}
+#endif /* TEST */
+
+
+/*
+ * For reference, here is the program that computed the T values.
+ */
+#if 0
+#include <math.h>
+main()
+{
+    int i;
+    for (i = 1; i <= 64; ++i) {
+	unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i)));
+	printf("#define T%d 0x%08lx\n", i, v);
+    }
+    return 0;
+}
+#endif
+/*
+ * End of T computation program.
+ */
+#define T1 0xd76aa478
+#define T2 0xe8c7b756
+#define T3 0x242070db
+#define T4 0xc1bdceee
+#define T5 0xf57c0faf
+#define T6 0x4787c62a
+#define T7 0xa8304613
+#define T8 0xfd469501
+#define T9 0x698098d8
+#define T10 0x8b44f7af
+#define T11 0xffff5bb1
+#define T12 0x895cd7be
+#define T13 0x6b901122
+#define T14 0xfd987193
+#define T15 0xa679438e
+#define T16 0x49b40821
+#define T17 0xf61e2562
+#define T18 0xc040b340
+#define T19 0x265e5a51
+#define T20 0xe9b6c7aa
+#define T21 0xd62f105d
+#define T22 0x02441453
+#define T23 0xd8a1e681
+#define T24 0xe7d3fbc8
+#define T25 0x21e1cde6
+#define T26 0xc33707d6
+#define T27 0xf4d50d87
+#define T28 0x455a14ed
+#define T29 0xa9e3e905
+#define T30 0xfcefa3f8
+#define T31 0x676f02d9
+#define T32 0x8d2a4c8a
+#define T33 0xfffa3942
+#define T34 0x8771f681
+#define T35 0x6d9d6122
+#define T36 0xfde5380c
+#define T37 0xa4beea44
+#define T38 0x4bdecfa9
+#define T39 0xf6bb4b60
+#define T40 0xbebfbc70
+#define T41 0x289b7ec6
+#define T42 0xeaa127fa
+#define T43 0xd4ef3085
+#define T44 0x04881d05
+#define T45 0xd9d4d039
+#define T46 0xe6db99e5
+#define T47 0x1fa27cf8
+#define T48 0xc4ac5665
+#define T49 0xf4292244
+#define T50 0x432aff97
+#define T51 0xab9423a7
+#define T52 0xfc93a039
+#define T53 0x655b59c3
+#define T54 0x8f0ccc92
+#define T55 0xffeff47d
+#define T56 0x85845dd1
+#define T57 0x6fa87e4f
+#define T58 0xfe2ce6e0
+#define T59 0xa3014314
+#define T60 0x4e0811a1
+#define T61 0xf7537e82
+#define T62 0xbd3af235
+#define T63 0x2ad7d2bb
+#define T64 0xeb86d391
+
+static void
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+{
+    md5_word_t
+	a = pms->abcd[0], b = pms->abcd[1],
+	c = pms->abcd[2], d = pms->abcd[3];
+    md5_word_t t;
+
+#ifndef ARCH_IS_BIG_ENDIAN
+# define ARCH_IS_BIG_ENDIAN 1	/* slower, default implementation */
+#endif
+#if ARCH_IS_BIG_ENDIAN
+
+    /*
+     * On big-endian machines, we must arrange the bytes in the right
+     * order.  (This also works on machines of unknown byte order.)
+     */
+    md5_word_t X[16];
+    const md5_byte_t *xp = data;
+    int i;
+
+    for (i = 0; i < 16; ++i, xp += 4)
+	X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+
+#else  /* !ARCH_IS_BIG_ENDIAN */
+
+    /*
+     * On little-endian machines, we can process properly aligned data
+     * without copying it.
+     */
+    md5_word_t xbuf[16];
+    const md5_word_t *X;
+
+    if (!((data - (const md5_byte_t *)0) & 3)) {
+	/* data are properly aligned */
+	X = (const md5_word_t *)data;
+    } else {
+	/* not aligned */
+	memcpy(xbuf, data, 64);
+	X = xbuf;
+    }
+#endif
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+    /* Round 1. */
+    /* Let [abcd k s i] denote the operation
+       a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + F(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+    /* Do the following 16 operations. */
+    SET(a, b, c, d,  0,  7,  T1);
+    SET(d, a, b, c,  1, 12,  T2);
+    SET(c, d, a, b,  2, 17,  T3);
+    SET(b, c, d, a,  3, 22,  T4);
+    SET(a, b, c, d,  4,  7,  T5);
+    SET(d, a, b, c,  5, 12,  T6);
+    SET(c, d, a, b,  6, 17,  T7);
+    SET(b, c, d, a,  7, 22,  T8);
+    SET(a, b, c, d,  8,  7,  T9);
+    SET(d, a, b, c,  9, 12, T10);
+    SET(c, d, a, b, 10, 17, T11);
+    SET(b, c, d, a, 11, 22, T12);
+    SET(a, b, c, d, 12,  7, T13);
+    SET(d, a, b, c, 13, 12, T14);
+    SET(c, d, a, b, 14, 17, T15);
+    SET(b, c, d, a, 15, 22, T16);
+#undef SET
+
+     /* Round 2. */
+     /* Let [abcd k s i] denote the operation
+          a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + G(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  1,  5, T17);
+    SET(d, a, b, c,  6,  9, T18);
+    SET(c, d, a, b, 11, 14, T19);
+    SET(b, c, d, a,  0, 20, T20);
+    SET(a, b, c, d,  5,  5, T21);
+    SET(d, a, b, c, 10,  9, T22);
+    SET(c, d, a, b, 15, 14, T23);
+    SET(b, c, d, a,  4, 20, T24);
+    SET(a, b, c, d,  9,  5, T25);
+    SET(d, a, b, c, 14,  9, T26);
+    SET(c, d, a, b,  3, 14, T27);
+    SET(b, c, d, a,  8, 20, T28);
+    SET(a, b, c, d, 13,  5, T29);
+    SET(d, a, b, c,  2,  9, T30);
+    SET(c, d, a, b,  7, 14, T31);
+    SET(b, c, d, a, 12, 20, T32);
+#undef SET
+
+     /* Round 3. */
+     /* Let [abcd k s t] denote the operation
+          a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + H(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  5,  4, T33);
+    SET(d, a, b, c,  8, 11, T34);
+    SET(c, d, a, b, 11, 16, T35);
+    SET(b, c, d, a, 14, 23, T36);
+    SET(a, b, c, d,  1,  4, T37);
+    SET(d, a, b, c,  4, 11, T38);
+    SET(c, d, a, b,  7, 16, T39);
+    SET(b, c, d, a, 10, 23, T40);
+    SET(a, b, c, d, 13,  4, T41);
+    SET(d, a, b, c,  0, 11, T42);
+    SET(c, d, a, b,  3, 16, T43);
+    SET(b, c, d, a,  6, 23, T44);
+    SET(a, b, c, d,  9,  4, T45);
+    SET(d, a, b, c, 12, 11, T46);
+    SET(c, d, a, b, 15, 16, T47);
+    SET(b, c, d, a,  2, 23, T48);
+#undef SET
+
+     /* Round 4. */
+     /* Let [abcd k s t] denote the operation
+          a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + I(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  0,  6, T49);
+    SET(d, a, b, c,  7, 10, T50);
+    SET(c, d, a, b, 14, 15, T51);
+    SET(b, c, d, a,  5, 21, T52);
+    SET(a, b, c, d, 12,  6, T53);
+    SET(d, a, b, c,  3, 10, T54);
+    SET(c, d, a, b, 10, 15, T55);
+    SET(b, c, d, a,  1, 21, T56);
+    SET(a, b, c, d,  8,  6, T57);
+    SET(d, a, b, c, 15, 10, T58);
+    SET(c, d, a, b,  6, 15, T59);
+    SET(b, c, d, a, 13, 21, T60);
+    SET(a, b, c, d,  4,  6, T61);
+    SET(d, a, b, c, 11, 10, T62);
+    SET(c, d, a, b,  2, 15, T63);
+    SET(b, c, d, a,  9, 21, T64);
+#undef SET
+
+     /* Then perform the following additions. (That is increment each
+        of the four registers by the value it had before this block
+        was started.) */
+    pms->abcd[0] += a;
+    pms->abcd[1] += b;
+    pms->abcd[2] += c;
+    pms->abcd[3] += d;
+}
+
+void
+md5_init(md5_state_t *pms)
+{
+    pms->count[0] = pms->count[1] = 0;
+    pms->abcd[0] = 0x67452301;
+    pms->abcd[1] = 0xefcdab89;
+    pms->abcd[2] = 0x98badcfe;
+    pms->abcd[3] = 0x10325476;
+}
+
+void
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+{
+    const md5_byte_t *p = data;
+    int left = nbytes;
+    int offset = (pms->count[0] >> 3) & 63;
+    md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+    if (nbytes <= 0)
+	return;
+
+    /* Update the message length. */
+    pms->count[1] += nbytes >> 29;
+    pms->count[0] += nbits;
+    if (pms->count[0] < nbits)
+	pms->count[1]++;
+
+    /* Process an initial partial block. */
+    if (offset) {
+	int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+	memcpy(pms->buf + offset, p, copy);
+	if (offset + copy < 64)
+	    return;
+	p += copy;
+	left -= copy;
+	md5_process(pms, pms->buf);
+    }
+
+    /* Process full blocks. */
+    for (; left >= 64; p += 64, left -= 64)
+	md5_process(pms, p);
+
+    /* Process a final partial block. */
+    if (left)
+	memcpy(pms->buf, p, left);
+}
+
+void
+md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+{
+    static const md5_byte_t pad[64] = {
+	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+    };
+    md5_byte_t data[8];
+    int i;
+
+    /* Save the length before padding. */
+    for (i = 0; i < 8; ++i)
+	data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+    /* Pad to 56 bytes mod 64. */
+    md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+    /* Append the length. */
+    md5_append(pms, data, 8);
+    for (i = 0; i < 16; ++i)
+	digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
Index: lib/md5.h
===================================================================
--- lib/md5.h	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/md5.h	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,85 @@
+/*
+  Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.
+  
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  L. Peter Deutsch
+  ghost@aladdin.com
+
+ */
+/*
+  Independent implementation of MD5 (RFC 1321).
+
+  This code implements the MD5 Algorithm defined in RFC 1321.
+  It is derived directly from the text of the RFC and not from the
+  reference implementation.
+
+  The original and principal author of md5.h is L. Peter Deutsch
+  <ghost@aladdin.com>.  Other authors are noted in the change history
+  that follows (in reverse chronological order):
+
+  2004-03-09 Jelmer Vernooij add G_MODULE_EXPORT for Bitlbee
+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+	added conditionalization for C++ compilation from Martin
+	Purschke <purschke@bnl.gov>.
+  1999-05-03 lpd Original version.
+ */
+
+#ifndef md5_INCLUDED
+#  define md5_INCLUDED
+
+#include <glib.h>
+#include <gmodule.h>
+
+/*
+ * This code has some adaptations for the Ghostscript environment, but it
+ * will compile and run correctly in any environment with 8-bit chars and
+ * 32-bit ints.  Specifically, it assumes that if the following are
+ * defined, they have the same meaning as in Ghostscript: P1, P2, P3,
+ * ARCH_IS_BIG_ENDIAN.
+ */
+
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
+
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s {
+    md5_word_t count[2];	/* message length in bits, lsw first */
+    md5_word_t abcd[4];		/* digest buffer */
+    md5_byte_t buf[64];		/* accumulate block */
+} md5_state_t;
+
+#ifdef __cplusplus
+extern "C" 
+{
+#endif
+
+/* Initialize the algorithm. */
+G_MODULE_EXPORT void md5_init(md5_state_t *pms);
+
+/* Append a string to the message. */
+G_MODULE_EXPORT void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+
+/* Finish the message and return the digest. */
+G_MODULE_EXPORT void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+
+#ifdef __cplusplus
+}  /* end extern "C" */
+#endif
+
+#endif /* md5_INCLUDED */
Index: lib/misc.c
===================================================================
--- lib/misc.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/misc.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,481 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2004 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/*
+ * Various utility functions. Some are copied from Gaim to support the
+ * IM-modules, most are from BitlBee.
+ *
+ * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
+ *                          (and possibly other members of the Gaim team)
+ * Copyright 2002-2005 Wilmer van der Gaast <wilmer@gaast.net>
+ */
+
+/*
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#define BITLBEE_CORE
+#include "nogaim.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <glib.h>
+#include <time.h>
+
+void strip_linefeed(gchar *text)
+{
+	int i, j;
+	gchar *text2 = g_malloc(strlen(text) + 1);
+
+	for (i = 0, j = 0; text[i]; i++)
+		if (text[i] != '\r')
+			text2[j++] = text[i];
+	text2[j] = '\0';
+
+	strcpy(text, text2);
+	g_free(text2);
+}
+
+char *add_cr(char *text)
+{
+	char *ret = NULL;
+	int count = 0, j;
+	unsigned int i;
+
+	if (text[0] == '\n')
+		count++;
+	for (i = 1; i < strlen(text); i++)
+		if (text[i] == '\n' && text[i - 1] != '\r')
+			count++;
+
+	if (count == 0)
+		return g_strdup(text);
+
+	ret = g_malloc0(strlen(text) + count + 1);
+
+	i = 0; j = 0;
+	if (text[i] == '\n')
+		ret[j++] = '\r';
+	ret[j++] = text[i++];
+	for (; i < strlen(text); i++) {
+		if (text[i] == '\n' && text[i - 1] != '\r')
+			ret[j++] = '\r';
+		ret[j++] = text[i];
+	}
+
+	return ret;
+}
+
+char *tobase64(const char *text)
+{
+	char *out;
+	int len;
+	
+	len = strlen(text);
+	out = g_malloc((len + 2)    /* the == padding */
+	                    / 3     /* every 3-byte block */
+	                    * 4     /* becomes a 4-byte one */
+	                    + 1);   /* and of course, ASCIIZ! */
+	
+	base64_encode_real(text, len, out, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=");
+	
+	return out;
+}
+
+void base64_encode_real(const unsigned char *in, int inlen, unsigned char *out, char *b64digits)
+{
+	for (; inlen >= 3; inlen -= 3)
+	{
+		*out++ = b64digits[in[0] >> 2];
+		*out++ = b64digits[((in[0]<<4) & 0x30) | (in[1]>>4)];
+		*out++ = b64digits[((in[1]<<2) & 0x3c) | (in[2]>>6)];
+		*out++ = b64digits[in[2] & 0x3f];
+		in += 3;
+	}
+	if (inlen > 0)
+	{
+		*out++ = b64digits[in[0] >> 2];
+		if (inlen > 1)
+		{
+			*out++ = b64digits[((in[0]<<4) & 0x30) | (in[1]>>4)];
+			*out++ = b64digits[((in[1]<<2) & 0x3c)];
+		}
+		else
+		{
+			*out++ = b64digits[((in[0]<<4) & 0x30) | (in[1]>>4)];
+			*out++ = b64digits[64];
+		}
+		*out++ = b64digits[64];
+	}
+	*out = '\0';
+}
+
+char *normalize(const char *s)
+{
+	static char buf[BUF_LEN];
+	char *t, *u;
+	int x = 0;
+
+	g_return_val_if_fail((s != NULL), NULL);
+
+	u = t = g_strdup(s);
+
+	strcpy(t, s);
+	g_strdown(t);
+
+	while (*t && (x < BUF_LEN - 1)) {
+		if (*t != ' ') {
+			buf[x] = *t;
+			x++;
+		}
+		t++;
+	}
+	buf[x] = '\0';
+	g_free(u);
+	return buf;
+}
+
+time_t get_time(int year, int month, int day, int hour, int min, int sec)
+{
+	struct tm tm;
+
+	tm.tm_year = year - 1900;
+	tm.tm_mon = month - 1;
+	tm.tm_mday = day;
+	tm.tm_hour = hour;
+	tm.tm_min = min;
+	tm.tm_sec = sec >= 0 ? sec : time(NULL) % 60;
+	return mktime(&tm);
+}
+
+typedef struct htmlentity
+{
+	char code[8];
+	char is[4];
+} htmlentity_t;
+
+/* FIXME: This is ISO8859-1(5) centric, so might cause problems with other charsets. */
+
+static const htmlentity_t ent[] =
+{
+	{ "lt",     "<" },
+	{ "gt",     ">" },
+	{ "amp",    "&" },
+	{ "quot",   "\"" },
+	{ "aacute", "á" },
+	{ "eacute", "é" },
+	{ "iacute", "é" },
+	{ "oacute", "ó" },
+	{ "uacute", "ú" },
+	{ "agrave", "à" },
+	{ "egrave", "è" },
+	{ "igrave", "ì" },
+	{ "ograve", "ò" },
+	{ "ugrave", "ù" },
+	{ "acirc",  "â" },
+	{ "ecirc",  "ê" },
+	{ "icirc",  "î" },
+	{ "ocirc",  "ô" },
+	{ "ucirc",  "û" },
+	{ "auml",   "ä" },
+	{ "euml",   "ë" },
+	{ "iuml",   "ï" },
+	{ "ouml",   "ö" },
+	{ "uuml",   "ü" },
+	{ "nbsp",   " " },
+	{ "",        ""  }
+};
+
+void strip_html( char *in )
+{
+	char *start = in;
+	char *out = g_malloc( strlen( in ) + 1 );
+	char *s = out, *cs;
+	int i, matched;
+	
+	memset( out, 0, strlen( in ) + 1 );
+	
+	while( *in )
+	{
+		if( *in == '<' && ( isalpha( *(in+1) ) || *(in+1) == '/' ) )
+		{
+			/* If in points at a < and in+1 points at a letter or a slash, this is probably
+			   a HTML-tag. Try to find a closing > and continue there. If the > can't be
+			   found, assume that it wasn't a HTML-tag after all. */
+			
+			cs = in;
+			
+			while( *in && *in != '>' )
+				in ++;
+			
+			if( *in )
+			{
+				if( g_strncasecmp( cs+1, "br", 2) == 0 )
+					*(s++) = '\n';
+				in ++;
+			}
+			else
+			{
+				in = cs;
+				*(s++) = *(in++);
+			}
+		}
+		else if( *in == '&' )
+		{
+			cs = ++in;
+			while( *in && isalpha( *in ) )
+				in ++;
+			
+			if( *in == ';' ) in ++;
+			matched = 0;
+			
+			for( i = 0; *ent[i].code; i ++ )
+				if( g_strncasecmp( ent[i].code, cs, strlen( ent[i].code ) ) == 0 )
+				{
+					int j;
+					
+					for( j = 0; ent[i].is[j]; j ++ )
+						*(s++) = ent[i].is[j];
+					
+					matched = 1;
+					break;
+				}
+
+			/* None of the entities were matched, so return the string */
+			if( !matched )
+			{
+				in = cs - 1;
+				*(s++) = *(in++);
+			}
+		}
+		else
+		{
+			*(s++) = *(in++);
+		}
+	}
+	
+	strcpy( start, out );
+	g_free( out );
+}
+
+char *escape_html( const char *html )
+{
+	const char *c = html;
+	GString *ret;
+	char *str;
+	
+	if( html == NULL )
+		return( NULL );
+	
+	ret = g_string_new( "" );
+	
+	while( *c )
+	{
+		switch( *c )
+		{
+			case '&':
+				ret = g_string_append( ret, "&amp;" );
+				break;
+			case '<':
+				ret = g_string_append( ret, "&lt;" );
+				break;
+			case '>':
+				ret = g_string_append( ret, "&gt;" );
+				break;
+			case '"':
+				ret = g_string_append( ret, "&quot;" );
+				break;
+			default:
+				ret = g_string_append_c( ret, *c );
+		}
+		c ++;
+	}
+	
+	str = ret->str;
+	g_string_free( ret, FALSE );
+	return( str );
+}
+
+void info_string_append(GString *str, char *newline, char *name, char *value)
+{
+	if( value && value[0] )
+		g_string_sprintfa( str, "%s%s: %s", newline, name, value );
+}
+
+/* Decode%20a%20file%20name						*/
+void http_decode( char *s )
+{
+	char *t;
+	int i, j, k;
+	
+	t = g_new( char, strlen( s ) + 1 );
+	
+	for( i = j = 0; s[i]; i ++, j ++ )
+	{
+		if( s[i] == '%' )
+		{
+			if( sscanf( s + i + 1, "%2x", &k ) )
+			{
+				t[j] = k;
+				i += 2;
+			}
+			else
+			{
+				*t = 0;
+				break;
+			}
+		}
+		else
+		{
+			t[j] = s[i];
+		}
+	}
+	t[j] = 0;
+	
+	strcpy( s, t );
+	g_free( t );
+}
+
+/* Warning: This one explodes the string. Worst-cases can make the string 3x its original size! */
+/* This fuction is safe, but make sure you call it safely as well! */
+void http_encode( char *s )
+{
+	char *t;
+	int i, j;
+	
+	t = g_strdup( s );
+	
+	for( i = j = 0; t[i]; i ++, j ++ )
+	{
+		/* if( t[i] <= ' ' || ((unsigned char *)t)[i] >= 128 || t[i] == '%' ) */
+		if( !isalnum( t[i] ) )
+		{
+			sprintf( s + j, "%%%02X", ((unsigned char*)t)[i] );
+			j += 2;
+		}
+		else
+		{
+			s[j] = t[i];
+		}
+	}
+	s[j] = 0;
+	
+	g_free( t );
+}
+
+/* Strip newlines from a string. Modifies the string passed to it. */ 
+char *strip_newlines( char *source )
+{
+	int i;	
+
+	for( i = 0; source[i] != '\0'; i ++ )
+		if( source[i] == '\n' || source[i] == '\r' )
+			source[i] = ' ';
+	
+	return source;
+}
+
+#ifdef IPV6
+/* Wrap an IPv4 address into IPv6 space. Not thread-safe... */
+char *ipv6_wrap( char *src )
+{
+	static char dst[64];
+	int i;
+	
+	for( i = 0; src[i]; i ++ )
+		if( ( src[i] < '0' || src[i] > '9' ) && src[i] != '.' )
+			break;
+	
+	/* Hmm, it's not even an IP... */
+	if( src[i] )
+		return src;
+	
+	g_snprintf( dst, sizeof( dst ), "::ffff:%s", src );
+	
+	return dst;
+}
+
+/* Unwrap an IPv4 address into IPv6 space. Thread-safe, because it's very simple. :-) */
+char *ipv6_unwrap( char *src )
+{
+	int i;
+	
+	if( g_strncasecmp( src, "::ffff:", 7 ) != 0 )
+		return src;
+	
+	for( i = 7; src[i]; i ++ )
+		if( ( src[i] < '0' || src[i] > '9' ) && src[i] != '.' )
+			break;
+	
+	/* Hmm, it's not even an IP... */
+	if( src[i] )
+		return src;
+	
+	return ( src + 7 );
+}
+#endif
+
+/* Convert from one charset to another.
+   
+   from_cs, to_cs: Source and destination charsets
+   src, dst: Source and destination strings
+   size: Size if src. 0 == use strlen(). strlen() is not reliable for UNICODE/UTF16 strings though.
+   maxbuf: Maximum number of bytes to write to dst
+   
+   Returns the number of bytes written to maxbuf or -1 on an error.
+*/
+signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf )
+{
+	GIConv cd;
+	size_t res;
+	size_t inbytesleft, outbytesleft;
+	char *inbuf = src;
+	char *outbuf = dst;
+	
+	cd = g_iconv_open( to_cs, from_cs );
+	if( cd == (GIConv) -1 )
+		return( -1 );
+	
+	inbytesleft = size ? size : strlen( src );
+	outbytesleft = maxbuf - 1;
+	res = g_iconv( cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft );
+	*outbuf = '\0';
+	g_iconv_close( cd );
+	
+	if( res == (size_t) -1 )
+		return( -1 );
+	else
+		return( outbuf - dst );
+}
+
+char *set_eval_charset( irc_t *irc, set_t *set, char *value )
+{
+	GIConv cd;
+
+	if ( g_strncasecmp( value, "none", 4 ) == 0 )
+		return( value );
+
+	cd = g_iconv_open( "UTF-8", value );
+	if( cd == (GIConv) -1 )
+		return( NULL );
+
+	g_iconv_close( cd );
+	return( value );
+}
Index: lib/misc.h
===================================================================
--- lib/misc.h	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/misc.h	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,51 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2004 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/* Misc. functions                                                      */
+
+/*
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _UTIL_H
+#define _UTIL_H
+
+G_MODULE_EXPORT void strip_linefeed( gchar *text );
+G_MODULE_EXPORT char *add_cr( char *text );
+G_MODULE_EXPORT char *strip_newlines(char *source);
+G_MODULE_EXPORT char *tobase64( const char *text );
+G_MODULE_EXPORT void base64_encode_real( const unsigned char *in, int inlen, unsigned char *out, char *b64digits );
+G_MODULE_EXPORT char *normalize( const char *s );
+G_MODULE_EXPORT void info_string_append( GString *str, char *newline, char *name, char *value );
+
+G_MODULE_EXPORT time_t get_time( int year, int month, int day, int hour, int min, int sec );
+double gettime( void );
+
+G_MODULE_EXPORT void strip_html( char *msg );
+G_MODULE_EXPORT char *escape_html( const char *html );
+G_MODULE_EXPORT void http_decode( char *s );
+G_MODULE_EXPORT void http_encode( char *s );
+
+G_MODULE_EXPORT char *ipv6_wrap( char *src );
+G_MODULE_EXPORT char *ipv6_unwrap( char *src );
+
+G_MODULE_EXPORT signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf );
+char *set_eval_charset( irc_t *irc, set_t *set, char *value );
+
+#endif
Index: lib/proxy.c
===================================================================
--- lib/proxy.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/proxy.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,556 @@
+/*
+ * gaim
+ *
+ * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
+ * Copyright (C) 2002-2004, Wilmer van der Gaast, Jelmer Vernooij
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#define BITLBEE_CORE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#ifndef _WIN32
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#else
+#include "sock.h"
+#define ETIMEDOUT WSAETIMEDOUT
+#define EINPROGRESS WSAEINPROGRESS
+#endif
+#include <fcntl.h>
+#include <errno.h>
+#include "nogaim.h"
+#include "proxy.h"
+
+char proxyhost[128] = "";
+int proxyport = 0;
+int proxytype = PROXY_NONE;
+char proxyuser[128] = "";
+char proxypass[128] = "";
+
+struct PHB {
+	b_event_handler func, proxy_func;
+	gpointer data, proxy_data;
+	char *host;
+	int port;
+	int fd;
+	gint inpa;
+};
+
+
+
+static struct sockaddr_in *gaim_gethostbyname(const char *host, int port)
+{
+	static struct sockaddr_in sin;
+
+	if (!inet_aton(host, &sin.sin_addr)) {
+		struct hostent *hp;
+		if (!(hp = gethostbyname(host))) {
+			return NULL;
+		}
+		memset(&sin, 0, sizeof(struct sockaddr_in));
+		memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
+		sin.sin_family = hp->h_addrtype;
+	} else
+		sin.sin_family = AF_INET;
+	sin.sin_port = htons(port);
+
+	return &sin;
+}
+
+static gboolean gaim_io_connected(gpointer data, gint source, b_input_condition cond)
+{
+	struct PHB *phb = data;
+	unsigned int len;
+	int error = ETIMEDOUT;
+	len = sizeof(error);
+	
+#ifndef _WIN32
+	if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
+		closesocket(source);
+		b_event_remove(phb->inpa);
+		if( phb->proxy_func )
+			phb->proxy_func(phb->proxy_data, -1, GAIM_INPUT_READ);
+		else {
+			phb->func(phb->data, -1, GAIM_INPUT_READ);
+			g_free(phb);
+		}
+		return FALSE;
+	}
+#endif
+	sock_make_blocking(source);
+	b_event_remove(phb->inpa);
+	if( phb->proxy_func )
+		phb->proxy_func(phb->proxy_data, source, GAIM_INPUT_READ);
+	else {
+		phb->func(phb->data, source, GAIM_INPUT_READ);
+		g_free(phb);
+	}
+	
+	return FALSE;
+}
+
+static int proxy_connect_none(const char *host, unsigned short port, struct PHB *phb)
+{
+	struct sockaddr_in *sin;
+	int fd = -1;
+
+	if (!(sin = gaim_gethostbyname(host, port))) {
+		g_free(phb);
+		return -1;
+	}
+
+	if ((fd = socket(sin->sin_family, SOCK_STREAM, 0)) < 0) {
+		g_free(phb);
+		return -1;
+	}
+
+	sock_make_nonblocking(fd);
+	
+	event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port, fd);
+	
+	if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0) {
+		if (sockerr_again()) {
+			phb->inpa = b_input_add(fd, GAIM_INPUT_WRITE, gaim_io_connected, phb);
+			phb->fd = fd;
+		} else {
+			closesocket(fd);
+			g_free(phb);
+			return -1;
+		}
+	}
+
+	return fd;
+}
+
+
+/* Connecting to HTTP proxies */
+
+#define HTTP_GOODSTRING "HTTP/1.0 200 Connection established"
+#define HTTP_GOODSTRING2 "HTTP/1.1 200 Connection established"
+
+static gboolean http_canread(gpointer data, gint source, b_input_condition cond)
+{
+	int nlc = 0;
+	int pos = 0;
+	struct PHB *phb = data;
+	char inputline[8192];
+
+	b_event_remove(phb->inpa);
+
+	while ((pos < sizeof(inputline)-1) && (nlc != 2) && (read(source, &inputline[pos++], 1) == 1)) {
+		if (inputline[pos - 1] == '\n')
+			nlc++;
+		else if (inputline[pos - 1] != '\r')
+			nlc = 0;
+	}
+	inputline[pos] = '\0';
+
+	if ((memcmp(HTTP_GOODSTRING, inputline, strlen(HTTP_GOODSTRING)) == 0) ||
+	    (memcmp(HTTP_GOODSTRING2, inputline, strlen(HTTP_GOODSTRING2)) == 0)) {
+		phb->func(phb->data, source, GAIM_INPUT_READ);
+		g_free(phb->host);
+		g_free(phb);
+		return FALSE;
+	}
+
+	close(source);
+	phb->func(phb->data, -1, GAIM_INPUT_READ);
+	g_free(phb->host);
+	g_free(phb);
+	
+	return FALSE;
+}
+
+static gboolean http_canwrite(gpointer data, gint source, b_input_condition cond)
+{
+	char cmd[384];
+	struct PHB *phb = data;
+	unsigned int len;
+	int error = ETIMEDOUT;
+	if (phb->inpa > 0)
+		b_event_remove(phb->inpa);
+	len = sizeof(error);
+	if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
+		close(source);
+		phb->func(phb->data, -1, GAIM_INPUT_READ);
+		g_free(phb->host);
+		g_free(phb);
+		return FALSE;
+	}
+	sock_make_blocking(source);
+
+	g_snprintf(cmd, sizeof(cmd), "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", phb->host, phb->port,
+		   phb->host, phb->port);
+	if (send(source, cmd, strlen(cmd), 0) < 0) {
+		close(source);
+		phb->func(phb->data, -1, GAIM_INPUT_READ);
+		g_free(phb->host);
+		g_free(phb);
+		return FALSE;
+	}
+
+	if (proxyuser && *proxyuser) {
+		char *t1, *t2;
+		t1 = g_strdup_printf("%s:%s", proxyuser, proxypass);
+		t2 = tobase64(t1);
+		g_free(t1);
+		g_snprintf(cmd, sizeof(cmd), "Proxy-Authorization: Basic %s\r\n", t2);
+		g_free(t2);
+		if (send(source, cmd, strlen(cmd), 0) < 0) {
+			close(source);
+			phb->func(phb->data, -1, GAIM_INPUT_READ);
+			g_free(phb->host);
+			g_free(phb);
+			return FALSE;
+		}
+	}
+
+	g_snprintf(cmd, sizeof(cmd), "\r\n");
+	if (send(source, cmd, strlen(cmd), 0) < 0) {
+		close(source);
+		phb->func(phb->data, -1, GAIM_INPUT_READ);
+		g_free(phb->host);
+		g_free(phb);
+		return FALSE;
+	}
+
+	phb->inpa = b_input_add(source, GAIM_INPUT_READ, http_canread, phb);
+	
+	return FALSE;
+}
+
+static int proxy_connect_http(const char *host, unsigned short port, struct PHB *phb)
+{
+	phb->host = g_strdup(host);
+	phb->port = port;
+	phb->proxy_func = http_canwrite;
+	phb->proxy_data = phb;
+	
+	return( proxy_connect_none( proxyhost, proxyport, phb ) );
+}
+
+
+/* Connecting to SOCKS4 proxies */
+
+static gboolean s4_canread(gpointer data, gint source, b_input_condition cond)
+{
+	unsigned char packet[12];
+	struct PHB *phb = data;
+
+	b_event_remove(phb->inpa);
+
+	memset(packet, 0, sizeof(packet));
+	if (read(source, packet, 9) >= 4 && packet[1] == 90) {
+		phb->func(phb->data, source, GAIM_INPUT_READ);
+		g_free(phb->host);
+		g_free(phb);
+		return FALSE;
+	}
+
+	close(source);
+	phb->func(phb->data, -1, GAIM_INPUT_READ);
+	g_free(phb->host);
+	g_free(phb);
+	
+	return FALSE;
+}
+
+static gboolean s4_canwrite(gpointer data, gint source, b_input_condition cond)
+{
+	unsigned char packet[12];
+	struct hostent *hp;
+	struct PHB *phb = data;
+	unsigned int len;
+	int error = ETIMEDOUT;
+	if (phb->inpa > 0)
+		b_event_remove(phb->inpa);
+	len = sizeof(error);
+	if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
+		close(source);
+		phb->func(phb->data, -1, GAIM_INPUT_READ);
+		g_free(phb->host);
+		g_free(phb);
+		return FALSE;
+	}
+	sock_make_blocking(source);
+
+	/* XXX does socks4 not support host name lookups by the proxy? */
+	if (!(hp = gethostbyname(phb->host))) {
+		close(source);
+		phb->func(phb->data, -1, GAIM_INPUT_READ);
+		g_free(phb->host);
+		g_free(phb);
+		return FALSE;
+	}
+
+	packet[0] = 4;
+	packet[1] = 1;
+	packet[2] = phb->port >> 8;
+	packet[3] = phb->port & 0xff;
+	packet[4] = (unsigned char)(hp->h_addr_list[0])[0];
+	packet[5] = (unsigned char)(hp->h_addr_list[0])[1];
+	packet[6] = (unsigned char)(hp->h_addr_list[0])[2];
+	packet[7] = (unsigned char)(hp->h_addr_list[0])[3];
+	packet[8] = 0;
+	if (write(source, packet, 9) != 9) {
+		close(source);
+		phb->func(phb->data, -1, GAIM_INPUT_READ);
+		g_free(phb->host);
+		g_free(phb);
+		return FALSE;
+	}
+
+	phb->inpa = b_input_add(source, GAIM_INPUT_READ, s4_canread, phb);
+	
+	return FALSE;
+}
+
+static int proxy_connect_socks4(const char *host, unsigned short port, struct PHB *phb)
+{
+	phb->host = g_strdup(host);
+	phb->port = port;
+	phb->proxy_func = s4_canwrite;
+	phb->proxy_data = phb;
+	
+	return( proxy_connect_none( proxyhost, proxyport, phb ) );
+}
+
+
+/* Connecting to SOCKS5 proxies */
+
+static gboolean s5_canread_again(gpointer data, gint source, b_input_condition cond)
+{
+	unsigned char buf[512];
+	struct PHB *phb = data;
+
+	b_event_remove(phb->inpa);
+
+	if (read(source, buf, 10) < 10) {
+		close(source);
+		phb->func(phb->data, -1, GAIM_INPUT_READ);
+		g_free(phb->host);
+		g_free(phb);
+		return FALSE;
+	}
+	if ((buf[0] != 0x05) || (buf[1] != 0x00)) {
+		close(source);
+		phb->func(phb->data, -1, GAIM_INPUT_READ);
+		g_free(phb->host);
+		g_free(phb);
+		return FALSE;
+	}
+
+	phb->func(phb->data, source, GAIM_INPUT_READ);
+	g_free(phb->host);
+	g_free(phb);
+	
+	return FALSE;
+}
+
+static void s5_sendconnect(gpointer data, gint source)
+{
+	unsigned char buf[512];
+	struct PHB *phb = data;
+	int hlen = strlen(phb->host);
+	
+	buf[0] = 0x05;
+	buf[1] = 0x01;		/* CONNECT */
+	buf[2] = 0x00;		/* reserved */
+	buf[3] = 0x03;		/* address type -- host name */
+	buf[4] = hlen;
+	memcpy(buf + 5, phb->host, hlen);
+	buf[5 + strlen(phb->host)] = phb->port >> 8;
+	buf[5 + strlen(phb->host) + 1] = phb->port & 0xff;
+
+	if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) {
+		close(source);
+		phb->func(phb->data, -1, GAIM_INPUT_READ);
+		g_free(phb->host);
+		g_free(phb);
+		return;
+	}
+
+	phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_canread_again, phb);
+}
+
+static gboolean s5_readauth(gpointer data, gint source, b_input_condition cond)
+{
+	unsigned char buf[512];
+	struct PHB *phb = data;
+
+	b_event_remove(phb->inpa);
+
+	if (read(source, buf, 2) < 2) {
+		close(source);
+		phb->func(phb->data, -1, GAIM_INPUT_READ);
+		g_free(phb->host);
+		g_free(phb);
+		return FALSE;
+	}
+
+	if ((buf[0] != 0x01) || (buf[1] != 0x00)) {
+		close(source);
+		phb->func(phb->data, -1, GAIM_INPUT_READ);
+		g_free(phb->host);
+		g_free(phb);
+		return FALSE;
+	}
+
+	s5_sendconnect(phb, source);
+	
+	return FALSE;
+}
+
+static gboolean s5_canread(gpointer data, gint source, b_input_condition cond)
+{
+	unsigned char buf[512];
+	struct PHB *phb = data;
+
+	b_event_remove(phb->inpa);
+
+	if (read(source, buf, 2) < 2) {
+		close(source);
+		phb->func(phb->data, -1, GAIM_INPUT_READ);
+		g_free(phb->host);
+		g_free(phb);
+		return FALSE;
+	}
+
+	if ((buf[0] != 0x05) || (buf[1] == 0xff)) {
+		close(source);
+		phb->func(phb->data, -1, GAIM_INPUT_READ);
+		g_free(phb->host);
+		g_free(phb);
+		return FALSE;
+	}
+
+	if (buf[1] == 0x02) {
+		unsigned int i = strlen(proxyuser), j = strlen(proxypass);
+		buf[0] = 0x01;	/* version 1 */
+		buf[1] = i;
+		memcpy(buf + 2, proxyuser, i);
+		buf[2 + i] = j;
+		memcpy(buf + 2 + i + 1, proxypass, j);
+		if (write(source, buf, 3 + i + j) < 3 + i + j) {
+			close(source);
+			phb->func(phb->data, -1, GAIM_INPUT_READ);
+			g_free(phb->host);
+			g_free(phb);
+			return FALSE;
+		}
+
+		phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_readauth, phb);
+	} else {
+		s5_sendconnect(phb, source);
+	}
+	
+	return FALSE;
+}
+
+static gboolean s5_canwrite(gpointer data, gint source, b_input_condition cond)
+{
+	unsigned char buf[512];
+	int i;
+	struct PHB *phb = data;
+	unsigned int len;
+	int error = ETIMEDOUT;
+	if (phb->inpa > 0)
+		b_event_remove(phb->inpa);
+	len = sizeof(error);
+	if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
+		close(source);
+		phb->func(phb->data, -1, GAIM_INPUT_READ);
+		g_free(phb->host);
+		g_free(phb);
+		return FALSE;
+	}
+	sock_make_blocking(source);
+
+	i = 0;
+	buf[0] = 0x05;		/* SOCKS version 5 */
+	if (proxyuser[0]) {
+		buf[1] = 0x02;	/* two methods */
+		buf[2] = 0x00;	/* no authentication */
+		buf[3] = 0x02;	/* username/password authentication */
+		i = 4;
+	} else {
+		buf[1] = 0x01;
+		buf[2] = 0x00;
+		i = 3;
+	}
+
+	if (write(source, buf, i) < i) {
+		close(source);
+		phb->func(phb->data, -1, GAIM_INPUT_READ);
+		g_free(phb->host);
+		g_free(phb);
+		return FALSE;
+	}
+
+	phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_canread, phb);
+	
+	return FALSE;
+}
+
+static int proxy_connect_socks5(const char *host, unsigned short port, struct PHB *phb)
+{
+	phb->host = g_strdup(host);
+	phb->port = port;
+	phb->proxy_func = s5_canwrite;
+	phb->proxy_data = phb;
+	
+	return( proxy_connect_none( proxyhost, proxyport, phb ) );
+}
+
+
+/* Export functions */
+
+int proxy_connect(const char *host, int port, b_event_handler func, gpointer data)
+{
+	struct PHB *phb;
+	
+	if (!host || !port || (port == -1) || !func || strlen(host) > 128) {
+		return -1;
+	}
+	
+	phb = g_new0(struct PHB, 1);
+	phb->func = func;
+	phb->data = data;
+	
+#ifndef _WIN32
+	sethostent(1);
+#endif
+	
+	if ((proxytype == PROXY_NONE) || !proxyhost || !proxyhost[0] || !proxyport || (proxyport == -1))
+		return proxy_connect_none(host, port, phb);
+	else if (proxytype == PROXY_HTTP)
+		return proxy_connect_http(host, port, phb);
+	else if (proxytype == PROXY_SOCKS4)
+		return proxy_connect_socks4(host, port, phb);
+	else if (proxytype == PROXY_SOCKS5)
+		return proxy_connect_socks5(host, port, phb);
+	
+	if (phb->host) g_free(phb);
+	g_free(phb);
+	return -1;
+}
Index: lib/proxy.h
===================================================================
--- lib/proxy.h	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/proxy.h	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,53 @@
+/*
+ * nogaim
+ *
+ * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/* this is the export part of the proxy.c file. it does a little
+   prototype-ing stuff and redefine some net function to mask them
+   with some kind of transparent layer */ 
+
+#ifndef _PROXY_H_
+#define _PROXY_H_
+
+#include <sys/types.h>
+#ifndef _WIN32
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#endif
+#include <glib.h>
+#include <gmodule.h>
+
+#include "events.h"
+
+#define PROXY_NONE 0
+#define PROXY_HTTP 1
+#define PROXY_SOCKS4 2
+#define PROXY_SOCKS5 3
+
+extern char proxyhost[128];
+extern int  proxyport;
+extern int  proxytype;
+extern char proxyuser[128];
+extern char proxypass[128];
+
+G_MODULE_EXPORT int proxy_connect(const char *host, int port, b_event_handler func, gpointer data);
+
+#endif /* _PROXY_H_ */
Index: lib/rc4.c
===================================================================
--- lib/rc4.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/rc4.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,179 @@
+/***************************************************************************\
+*                                                                           *
+*  BitlBee - An IRC to IM gateway                                           *
+*  Simple (but secure) RC4 implementation for safer password storage.       *
+*                                                                           *
+*  Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net>                   *
+*                                                                           *
+*                                                                           *
+*  This program is free software; you can redistribute it and/or modify     *
+*  it under the terms of the GNU General Public License as published by     *
+*  the Free Software Foundation; either version 2 of the License, or        *
+*  (at your option) any later version.                                      *
+*                                                                           *
+*  This program 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 General Public License for more details.                             *
+*                                                                           *
+*  You should have received a copy of the GNU General Public License along  *
+*  with this program; if not, write to the Free Software Foundation, Inc.,  *
+*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              *
+*                                                                           *
+\***************************************************************************/
+
+/* 
+   This file implements RC4-encryption, which will mainly be used to save IM
+   passwords safely in the new XML-format. Possibly other uses will come up
+   later. It's supposed to be quite reliable (thanks to the use of a 6-byte
+   IV/seed), certainly compared to the old format. The only realistic way to
+   crack BitlBee passwords now is to use a sniffer to get your hands on the
+   user's password.
+   
+   If you see that something's wrong in this implementation (I asked a
+   couple of people to look at it already, but who knows), please tell me.
+   
+   The reason I chose for RC4 is because it's pretty simple but effective,
+   so it will work without adding several KBs or an extra library dependency.
+*/
+
+
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+#include "rc4.h"
+
+/* Add some seed to the password, to make sure we *never* use the same key.
+   This defines how many byes we use as a seed. */
+#define RC4_IV_LEN 6
+
+/* To defend against a "Fluhrer, Mantin and Shamir attack", it is recommended
+   to shuffle S[] just a bit more before you start to use it. This defines how
+   many bytes we'll request before we'll really use them for encryption. */
+#define RC4_CYCLES 1024
+
+struct rc4_state *rc4_keymaker( unsigned char *key, int kl, int cycles )
+{
+	struct rc4_state *st;
+	int i, j, tmp;
+	
+	st = g_malloc( sizeof( struct rc4_state ) );
+	st->i = st->j = 0;
+	for( i = 0; i < 256; i ++ )
+		st->S[i] = i;
+	
+	if( kl <= 0 )
+		kl = strlen( (char*) key );
+	
+	for( i = j = 0; i < 256; i ++ )
+	{
+		j = ( j + st->S[i] + key[i%kl] ) & 0xff;
+		tmp = st->S[i];
+		st->S[i] = st->S[j];
+		st->S[j] = tmp;
+	}
+	
+	for( i = 0; i < cycles; i ++ )
+		rc4_getbyte( st );
+	
+	return st;
+}
+
+/*
+   For those who don't know, RC4 is basically an algorithm that generates a
+   stream of bytes after you give it a key. Just get a byte from it and xor
+   it with your cleartext. To decrypt, just give it the same key again and
+   start xorring.
+   
+   The function above initializes the RC4 byte generator, the next function
+   can be used to get bytes from the generator (and shuffle things a bit).
+*/
+
+unsigned char rc4_getbyte( struct rc4_state *st )
+{
+	unsigned char tmp;
+	
+	/* Unfortunately the st-> stuff doesn't really improve readability here... */
+	st->i ++;
+	st->j += st->S[st->i];
+	tmp = st->S[st->i];
+	st->S[st->i] = st->S[st->j];
+	st->S[st->j] = tmp;
+	
+	return st->S[(st->S[st->i] + st->S[st->j]) & 0xff];
+}
+
+/*
+   The following two functions can be used for reliable encryption and
+   decryption. Known plaintext attacks are prevented by adding some (6,
+   by default) random bytes to the password before setting up the RC4
+   structures. These 6 bytes are also saved in the results, because of
+   course we'll need them in rc4_decode().
+   
+   Because the length of the resulting string is unknown to the caller,
+   it should pass a char**. Since the encode/decode functions allocate
+   memory for the string, make sure the char** points at a NULL-pointer
+   (or at least to something you already free()d), or you'll leak
+   memory. And of course, don't forget to free() the result when you
+   don't need it anymore.
+   
+   Both functions return the number of bytes in the result string.
+*/
+
+int rc4_encode( unsigned char *clear, int clear_len, unsigned char **crypt, char *password )
+{
+	struct rc4_state *st;
+	unsigned char *key;
+	int key_len, i;
+	
+	key_len = strlen( password ) + RC4_IV_LEN;
+	if( clear_len <= 0 )
+		clear_len = strlen( (char*) clear );
+	
+	/* Prepare buffers and the key + IV */
+	*crypt = g_malloc( clear_len + RC4_IV_LEN );
+	key = g_malloc( key_len );
+	strcpy( (char*) key, password );
+	for( i = 0; i < RC4_IV_LEN; i ++ )
+		key[key_len-RC4_IV_LEN+i] = crypt[0][i] = rand() & 0xff;
+	
+	/* Generate the initial S[] from the IVed key. */
+	st = rc4_keymaker( key, key_len, RC4_CYCLES );
+	g_free( key );
+	
+	for( i = 0; i < clear_len; i ++ )
+		crypt[0][i+RC4_IV_LEN] = clear[i] ^ rc4_getbyte( st );
+	
+	g_free( st );
+	
+	return clear_len + RC4_IV_LEN;
+}
+
+int rc4_decode( unsigned char *crypt, int crypt_len, unsigned char **clear, char *password )
+{
+	struct rc4_state *st;
+	unsigned char *key;
+	int key_len, clear_len, i;
+	
+	key_len = strlen( password ) + RC4_IV_LEN;
+	clear_len = crypt_len - RC4_IV_LEN;
+	
+	/* Prepare buffers and the key + IV */
+	*clear = g_malloc( clear_len + 1 );
+	key = g_malloc( key_len );
+	strcpy( (char*) key, password );
+	for( i = 0; i < RC4_IV_LEN; i ++ )
+		key[key_len-RC4_IV_LEN+i] = crypt[i];
+	
+	/* Generate the initial S[] from the IVed key. */
+	st = rc4_keymaker( key, key_len, RC4_CYCLES );
+	g_free( key );
+	
+	for( i = 0; i < clear_len; i ++ )
+		clear[0][i] = crypt[i+RC4_IV_LEN] ^ rc4_getbyte( st );
+	clear[0][i] = 0; /* Nice to have for plaintexts. */
+	
+	g_free( st );
+	
+	return clear_len;
+}
Index: lib/rc4.h
===================================================================
--- lib/rc4.h	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/rc4.h	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,35 @@
+/***************************************************************************\
+*                                                                           *
+*  BitlBee - An IRC to IM gateway                                           *
+*  Simple (but secure) RC4 implementation for safer password storage.       *
+*                                                                           *
+*  Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net>                   *
+*                                                                           *
+*                                                                           *
+*  This program is free software; you can redistribute it and/or modify     *
+*  it under the terms of the GNU General Public License as published by     *
+*  the Free Software Foundation; either version 2 of the License, or        *
+*  (at your option) any later version.                                      *
+*                                                                           *
+*  This program 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 General Public License for more details.                             *
+*                                                                           *
+*  You should have received a copy of the GNU General Public License along  *
+*  with this program; if not, write to the Free Software Foundation, Inc.,  *
+*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              *
+*                                                                           *
+\***************************************************************************/
+
+
+struct rc4_state
+{
+	unsigned char S[256];
+	unsigned char i, j;
+};
+
+struct rc4_state *rc4_keymaker( unsigned char *key, int kl, int cycles );
+unsigned char rc4_getbyte( struct rc4_state *st );
+int rc4_encode( unsigned char *clear, int clear_len, unsigned char **crypt, char *password );
+int rc4_decode( unsigned char *crypt, int crypt_len, unsigned char **clear, char *password );
Index: lib/sha.c
===================================================================
--- lib/sha.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/sha.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,173 @@
+/* 
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ * 
+ * The Original Code is SHA 180-1 Reference Implementation (Compact version)
+ * 
+ * The Initial Developer of the Original Code is Paul Kocher of
+ * Cryptography Research.  Portions created by Paul Kocher are 
+ * Copyright (C) 1995-9 by Cryptography Research, Inc.  All
+ * Rights Reserved.
+ * 
+ * Contributor(s):
+ *
+ */
+
+#define BITLBEE_CORE
+#include "nogaim.h"
+
+static void shaHashBlock(SHA_CTX *ctx);
+
+void shaInit(SHA_CTX *ctx) {
+  int i;
+
+  ctx->lenW = 0;
+  ctx->sizeHi = ctx->sizeLo = 0;
+
+  /* Initialize H with the magic constants (see FIPS180 for constants)
+   */
+  ctx->H[0] = 0x67452301L;
+  ctx->H[1] = 0xefcdab89L;
+  ctx->H[2] = 0x98badcfeL;
+  ctx->H[3] = 0x10325476L;
+  ctx->H[4] = 0xc3d2e1f0L;
+
+  for (i = 0; i < 80; i++)
+    ctx->W[i] = 0;
+}
+
+
+void shaUpdate(SHA_CTX *ctx, unsigned char *dataIn, int len) {
+  int i;
+
+  /* Read the data into W and process blocks as they get full
+   */
+  for (i = 0; i < len; i++) {
+    ctx->W[ctx->lenW / 4] <<= 8;
+    ctx->W[ctx->lenW / 4] |= (guint32)dataIn[i];
+    if ((++ctx->lenW) % 64 == 0) {
+      shaHashBlock(ctx);
+      ctx->lenW = 0;
+    }
+    ctx->sizeLo += 8;
+    ctx->sizeHi += (ctx->sizeLo < 8);
+  }
+}
+
+
+void shaFinal(SHA_CTX *ctx, unsigned char hashout[20]) {
+  unsigned char pad0x80 = 0x80;
+  unsigned char pad0x00 = 0x00;
+  unsigned char padlen[8];
+  int i;
+
+  /* Pad with a binary 1 (e.g. 0x80), then zeroes, then length
+   */
+  padlen[0] = (unsigned char)((ctx->sizeHi >> 24) & 255);
+  padlen[1] = (unsigned char)((ctx->sizeHi >> 16) & 255);
+  padlen[2] = (unsigned char)((ctx->sizeHi >> 8) & 255);
+  padlen[3] = (unsigned char)((ctx->sizeHi >> 0) & 255);
+  padlen[4] = (unsigned char)((ctx->sizeLo >> 24) & 255);
+  padlen[5] = (unsigned char)((ctx->sizeLo >> 16) & 255);
+  padlen[6] = (unsigned char)((ctx->sizeLo >> 8) & 255);
+  padlen[7] = (unsigned char)((ctx->sizeLo >> 0) & 255);
+  shaUpdate(ctx, &pad0x80, 1);
+  while (ctx->lenW != 56)
+    shaUpdate(ctx, &pad0x00, 1);
+  shaUpdate(ctx, padlen, 8);
+
+  /* Output hash
+   */
+  for (i = 0; i < 20; i++) {
+    hashout[i] = (unsigned char)(ctx->H[i / 4] >> 24);
+    ctx->H[i / 4] <<= 8;
+  }
+
+  /*
+   *  Re-initialize the context (also zeroizes contents)
+   */
+  shaInit(ctx); 
+}
+
+
+void shaBlock(unsigned char *dataIn, int len, unsigned char hashout[20]) {
+  SHA_CTX ctx;
+
+  shaInit(&ctx);
+  shaUpdate(&ctx, dataIn, len);
+  shaFinal(&ctx, hashout);
+}
+
+
+#define SHA_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xffffffffL)
+
+static void shaHashBlock(SHA_CTX *ctx) {
+  int t;
+  guint32 A,B,C,D,E,TEMP;
+
+  for (t = 16; t <= 79; t++)
+    ctx->W[t] =
+      SHA_ROTL(ctx->W[t-3] ^ ctx->W[t-8] ^ ctx->W[t-14] ^ ctx->W[t-16], 1);
+
+  A = ctx->H[0];
+  B = ctx->H[1];
+  C = ctx->H[2];
+  D = ctx->H[3];
+  E = ctx->H[4];
+
+  for (t = 0; t <= 19; t++) {
+    TEMP = (SHA_ROTL(A,5) + (((C^D)&B)^D)     + E + ctx->W[t] + 0x5a827999L) & 0xffffffffL;
+    E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
+  }
+  for (t = 20; t <= 39; t++) {
+    TEMP = (SHA_ROTL(A,5) + (B^C^D)           + E + ctx->W[t] + 0x6ed9eba1L) & 0xffffffffL;
+    E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
+  }
+  for (t = 40; t <= 59; t++) {
+    TEMP = (SHA_ROTL(A,5) + ((B&C)|(D&(B|C))) + E + ctx->W[t] + 0x8f1bbcdcL) & 0xffffffffL;
+    E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
+  }
+  for (t = 60; t <= 79; t++) {
+    TEMP = (SHA_ROTL(A,5) + (B^C^D)           + E + ctx->W[t] + 0xca62c1d6L) & 0xffffffffL;
+    E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
+  }
+
+  ctx->H[0] += A;
+  ctx->H[1] += B;
+  ctx->H[2] += C;
+  ctx->H[3] += D;
+  ctx->H[4] += E;
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * This code added by Thomas "temas" Muldowney for Jabber compatability
+ *
+ *---------------------------------------------------------------------------*/
+char *shahash(char *str)
+{
+    static char final[41];
+    char *pos;
+    unsigned char hashval[20];
+    int x;
+
+    if(!str || strlen(str) == 0)
+        return NULL;
+
+    shaBlock((unsigned char *)str, strlen(str), hashval);
+
+    pos = final;
+    for(x=0;x<20;x++)
+    {
+        g_snprintf(pos, 3, "%02x", hashval[x]);
+        pos += 2;
+    }
+    return (char *)final;
+}
Index: lib/sha.h
===================================================================
--- lib/sha.h	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/sha.h	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,21 @@
+#ifndef __SHA_H__
+#define __SHA_H__
+
+#include <gmodule.h>
+
+G_MODULE_EXPORT int strprintsha(char *dest, int *hashval);
+ 
+typedef struct {
+  guint32 H[5];
+  guint32 W[80];
+  int lenW;
+  guint32 sizeHi,sizeLo;
+} SHA_CTX;
+ 
+G_MODULE_EXPORT void shaInit(SHA_CTX *ctx);
+G_MODULE_EXPORT void shaUpdate(SHA_CTX *ctx, unsigned char *dataIn, int len);
+G_MODULE_EXPORT void shaFinal(SHA_CTX *ctx, unsigned char hashout[20]);
+G_MODULE_EXPORT void shaBlock(unsigned char *dataIn, int len, unsigned char hashout[20]);
+G_MODULE_EXPORT char *shahash(char *str);
+
+#endif
Index: lib/ssl_bogus.c
===================================================================
--- lib/ssl_bogus.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/ssl_bogus.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,57 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2004 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/* SSL module - dummy version                                           */
+
+/*
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "ssl_client.h"
+
+int ssl_errno;
+
+void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
+{
+	return( NULL );
+}
+
+int ssl_read( void *conn, char *buf, int len )
+{
+	return( -1 );
+}
+
+int ssl_write( void *conn, const char *buf, int len )
+{
+	return( -1 );
+}
+
+void ssl_disconnect( void *conn_ )
+{
+}
+
+int ssl_getfd( void *conn )
+{
+	return( -1 );
+}
+
+b_input_condition ssl_getdirection( void *conn )
+{
+	return GAIM_INPUT_READ;
+}
Index: lib/ssl_client.h
===================================================================
--- lib/ssl_client.h	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/ssl_client.h	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,42 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2004 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/* SSL module                                                           */
+
+/*
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <glib.h>
+#include "proxy.h"
+
+#define SSL_OK            0
+#define SSL_NOHANDSHAKE   1
+#define SSL_AGAIN         2
+
+extern int ssl_errno;
+
+typedef gboolean (*ssl_input_function)(gpointer, void*, b_input_condition);
+
+G_MODULE_EXPORT void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data );
+G_MODULE_EXPORT int ssl_read( void *conn, char *buf, int len );
+G_MODULE_EXPORT int ssl_write( void *conn, const char *buf, int len );
+G_MODULE_EXPORT void ssl_disconnect( void *conn_ );
+G_MODULE_EXPORT int ssl_getfd( void *conn );
+G_MODULE_EXPORT b_input_condition ssl_getdirection( void *conn );
Index: lib/ssl_gnutls.c
===================================================================
--- lib/ssl_gnutls.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/ssl_gnutls.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,206 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2004 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/* SSL module - GnuTLS version                                          */
+
+/*
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <gnutls/gnutls.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "proxy.h"
+#include "ssl_client.h"
+#include "sock.h"
+#include "stdlib.h"
+
+int ssl_errno = 0;
+
+static gboolean initialized = FALSE;
+
+struct scd
+{
+	ssl_input_function func;
+	gpointer data;
+	int fd;
+	gboolean established;
+	int inpa;
+	
+	gnutls_session session;
+	gnutls_certificate_credentials xcred;
+};
+
+static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond );
+
+
+void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
+{
+	struct scd *conn = g_new0( struct scd, 1 );
+	
+	conn->fd = proxy_connect( host, port, ssl_connected, conn );
+	conn->func = func;
+	conn->data = data;
+	conn->inpa = -1;
+	
+	if( conn->fd < 0 )
+	{
+		g_free( conn );
+		return( NULL );
+	}
+	
+	if( !initialized )
+	{
+		gnutls_global_init();
+		initialized = TRUE;
+		atexit( gnutls_global_deinit );
+	}
+	
+	gnutls_certificate_allocate_credentials( &conn->xcred );
+	gnutls_init( &conn->session, GNUTLS_CLIENT );
+	gnutls_set_default_priority( conn->session );
+	gnutls_credentials_set( conn->session, GNUTLS_CRD_CERTIFICATE, conn->xcred );
+	
+	return( conn );
+}
+
+static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond );
+
+static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond )
+{
+	struct scd *conn = data;
+	
+	if( source == -1 )
+	{
+		conn->func( conn->data, NULL, cond );
+		
+		gnutls_deinit( conn->session );
+		gnutls_certificate_free_credentials( conn->xcred );
+		
+		g_free( conn );
+		
+		return FALSE;
+	}
+	
+	sock_make_nonblocking( conn->fd );
+	gnutls_transport_set_ptr( conn->session, (gnutls_transport_ptr) conn->fd );
+	
+	return ssl_handshake( data, source, cond );
+}
+
+static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond )
+{
+	struct scd *conn = data;
+	int st;
+	
+	if( ( st = gnutls_handshake( conn->session ) ) < 0 )
+	{
+		if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED )
+		{
+			conn->inpa = b_input_add( conn->fd, ssl_getdirection( conn ),
+			                          ssl_handshake, data );
+		}
+		else
+		{
+			conn->func( conn->data, NULL, cond );
+			
+			gnutls_deinit( conn->session );
+			gnutls_certificate_free_credentials( conn->xcred );
+			closesocket( conn->fd );
+			
+			g_free( conn );
+		}
+	}
+	else
+	{
+		/* For now we can't handle non-blocking perfectly everywhere... */
+		sock_make_blocking( conn->fd );
+		
+		conn->established = TRUE;
+		conn->func( conn->data, conn, cond );
+	}
+	
+	return FALSE;
+}
+
+int ssl_read( void *conn, char *buf, int len )
+{
+	int st;
+	
+	if( !((struct scd*)conn)->established )
+	{
+		ssl_errno = SSL_NOHANDSHAKE;
+		return( -1 );
+	}
+	
+	st = gnutls_record_recv( ((struct scd*)conn)->session, buf, len );
+	
+	ssl_errno = SSL_OK;
+	if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED )
+		ssl_errno = SSL_AGAIN;
+	
+	return st;
+}
+
+int ssl_write( void *conn, const char *buf, int len )
+{
+	int st;
+	
+	if( !((struct scd*)conn)->established )
+	{
+		ssl_errno = SSL_NOHANDSHAKE;
+		return( -1 );
+	}
+	
+	st = gnutls_record_send( ((struct scd*)conn)->session, buf, len );
+	
+	ssl_errno = SSL_OK;
+	if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED )
+		ssl_errno = SSL_AGAIN;
+	
+	return st;
+}
+
+void ssl_disconnect( void *conn_ )
+{
+	struct scd *conn = conn_;
+	
+	if( conn->inpa != -1 )
+		b_event_remove( conn->inpa );
+	
+	if( conn->established )
+		gnutls_bye( conn->session, GNUTLS_SHUT_WR );
+	
+	closesocket( conn->fd );
+	
+	gnutls_deinit( conn->session );
+	gnutls_certificate_free_credentials( conn->xcred );
+	g_free( conn );
+}
+
+int ssl_getfd( void *conn )
+{
+	return( ((struct scd*)conn)->fd );
+}
+
+b_input_condition ssl_getdirection( void *conn )
+{
+	return( gnutls_record_get_direction( ((struct scd*)conn)->session ) ?
+	        GAIM_INPUT_WRITE : GAIM_INPUT_READ );
+}
Index: lib/ssl_nss.c
===================================================================
--- lib/ssl_nss.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/ssl_nss.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,190 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2005 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/* SSL module - NSS version                                             */
+
+/* Copyright 2005 Jelmer Vernooij                                       */
+
+/*
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "bitlbee.h"
+#include "proxy.h"
+#include "ssl_client.h"
+#include "sock.h"
+#include <nspr.h>
+#include <prio.h>
+#include <sslproto.h>
+#include <nss.h>
+#include <private/pprio.h>
+#include <ssl.h>
+#include <secerr.h>
+#include <sslerr.h>
+
+int ssl_errno = 0;
+
+static gboolean initialized = FALSE;
+
+struct scd
+{
+	ssl_input_function func;
+	gpointer data;
+	int fd;
+	PRFileDesc *prfd;
+	gboolean established;
+};
+
+static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond );
+
+
+static SECStatus nss_auth_cert (void *arg, PRFileDesc *socket, PRBool checksig, PRBool isserver)
+{
+	return SECSuccess;
+}
+
+static SECStatus nss_bad_cert (void *arg, PRFileDesc *socket) 
+{
+	PRErrorCode err;
+
+	if(!arg) return SECFailure;
+
+	*(PRErrorCode *)arg = err = PORT_GetError();
+
+	switch(err) {
+	case SEC_ERROR_INVALID_AVA:
+	case SEC_ERROR_INVALID_TIME:
+	case SEC_ERROR_BAD_SIGNATURE:
+	case SEC_ERROR_EXPIRED_CERTIFICATE:
+	case SEC_ERROR_UNKNOWN_ISSUER:
+	case SEC_ERROR_UNTRUSTED_CERT:
+	case SEC_ERROR_CERT_VALID:
+	case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
+	case SEC_ERROR_CRL_EXPIRED:
+	case SEC_ERROR_CRL_BAD_SIGNATURE:
+	case SEC_ERROR_EXTENSION_VALUE_INVALID:
+	case SEC_ERROR_CA_CERT_INVALID:
+	case SEC_ERROR_CERT_USAGES_INVALID:
+	case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION:
+		return SECSuccess;
+
+	default:
+		return SECFailure;
+	}
+}
+
+
+void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
+{
+	struct scd *conn = g_new0( struct scd, 1 );
+	
+	conn->fd = proxy_connect( host, port, ssl_connected, conn );
+	conn->func = func;
+	conn->data = data;
+	
+	if( conn->fd < 0 )
+	{
+		g_free( conn );
+		return( NULL );
+	}
+	
+	if( !initialized )
+	{
+		PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+		NSS_NoDB_Init(NULL);
+		NSS_SetDomesticPolicy();
+	}
+
+	
+	return( conn );
+}
+
+static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond )
+{
+	struct scd *conn = data;
+	
+	if( source == -1 )
+		goto ssl_connected_failure;
+	
+	/* Until we find out how to handle non-blocking I/O with NSS... */
+	sock_make_blocking( conn->fd );
+	
+	conn->prfd = SSL_ImportFD(NULL, PR_ImportTCPSocket(source));
+	SSL_OptionSet(conn->prfd, SSL_SECURITY, PR_TRUE);
+	SSL_OptionSet(conn->prfd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
+	SSL_BadCertHook(conn->prfd, (SSLBadCertHandler)nss_bad_cert, NULL);
+	SSL_AuthCertificateHook(conn->prfd, (SSLAuthCertificate)nss_auth_cert, (void *)CERT_GetDefaultCertDB());
+	SSL_ResetHandshake(conn->prfd, PR_FALSE);
+
+	if (SSL_ForceHandshake(conn->prfd)) {
+		goto ssl_connected_failure;
+	}
+	
+	
+	conn->established = TRUE;
+	conn->func( conn->data, conn, cond );
+	return FALSE;
+	
+	ssl_connected_failure:
+	
+	conn->func( conn->data, NULL, cond );
+	
+	PR_Close( conn -> prfd );
+	if( source >= 0 ) closesocket( source );
+	g_free( conn );
+	
+	return FALSE;
+}
+
+int ssl_read( void *conn, char *buf, int len )
+{
+	if( !((struct scd*)conn)->established )
+		return( 0 );
+	
+	return( PR_Read( ((struct scd*)conn)->prfd, buf, len ) );
+}
+
+int ssl_write( void *conn, const char *buf, int len )
+{
+	if( !((struct scd*)conn)->established )
+		return( 0 );
+	
+	return( PR_Write ( ((struct scd*)conn)->prfd, buf, len ) );
+}
+
+void ssl_disconnect( void *conn_ )
+{
+	struct scd *conn = conn_;
+	
+	PR_Close( conn->prfd );
+	closesocket( conn->fd );
+	
+	g_free( conn );
+}
+
+int ssl_getfd( void *conn )
+{
+	return( ((struct scd*)conn)->fd );
+}
+
+b_input_condition ssl_getdirection( void *conn )
+{
+	/* Just in case someone calls us, let's return the most likely case: */
+	return GAIM_INPUT_READ;
+}
Index: lib/ssl_openssl.c
===================================================================
--- lib/ssl_openssl.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/ssl_openssl.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,221 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2004 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/* SSL module - OpenSSL version                                         */
+
+/*
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <openssl/crypto.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+#include "proxy.h"
+#include "ssl_client.h"
+#include "sock.h"
+
+int ssl_errno = 0;
+
+static gboolean initialized = FALSE;
+
+struct scd
+{
+	ssl_input_function func;
+	gpointer data;
+	int fd;
+	gboolean established;
+	
+	int inpa;
+	int lasterr;		/* Necessary for SSL_get_error */
+	SSL *ssl;
+	SSL_CTX *ssl_ctx;
+};
+
+static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond );
+
+
+void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
+{
+	struct scd *conn = g_new0( struct scd, 1 );
+	SSL_METHOD *meth;
+	
+	conn->fd = proxy_connect( host, port, ssl_connected, conn );
+	conn->func = func;
+	conn->data = data;
+	
+	if( conn->fd < 0 )
+	{
+		g_free( conn );
+		return( NULL );
+	}
+	
+	if( !initialized )
+	{
+		initialized = TRUE;
+		SSLeay_add_ssl_algorithms();
+	}
+	
+	meth = TLSv1_client_method();
+	conn->ssl_ctx = SSL_CTX_new( meth );
+	if( conn->ssl_ctx == NULL )
+	{
+		conn->fd = -1;
+		return( NULL );
+	}
+	
+	conn->ssl = SSL_new( conn->ssl_ctx );
+	if( conn->ssl == NULL )
+	{
+		conn->fd = -1;
+		return( NULL );
+	}
+	
+	return( conn );
+}
+
+static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond );
+
+static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond )
+{
+	struct scd *conn = data;
+	
+	if( source == -1 )
+		return ssl_handshake( data, -1, cond );
+	
+	/* We can do at least the handshake with non-blocking I/O */
+	sock_make_nonblocking( conn->fd );
+	SSL_set_fd( conn->ssl, conn->fd );
+	
+	return ssl_handshake( data, source, cond );
+}	
+
+static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond )
+{
+	struct scd *conn = data;
+	int st;
+	
+	if( ( st = SSL_connect( conn->ssl ) ) < 0 )
+	{
+		conn->lasterr = SSL_get_error( conn->ssl, st );
+		if( conn->lasterr != SSL_ERROR_WANT_READ && conn->lasterr != SSL_ERROR_WANT_WRITE )
+			goto ssl_connected_failure;
+		
+		conn->inpa = b_input_add( conn->fd, ssl_getdirection( conn ), ssl_handshake, data );
+		return FALSE;
+	}
+	
+	conn->established = TRUE;
+	sock_make_blocking( conn->fd );		/* For now... */
+	conn->func( conn->data, conn, cond );
+	return FALSE;
+	
+ssl_connected_failure:
+	conn->func( conn->data, NULL, cond );
+	
+	if( conn->ssl )
+	{
+		SSL_shutdown( conn->ssl );
+		SSL_free( conn->ssl );
+	}
+	if( conn->ssl_ctx )
+	{
+		SSL_CTX_free( conn->ssl_ctx );
+	}
+	if( source >= 0 ) closesocket( source );
+	g_free( conn );
+	
+	return FALSE;
+}
+
+int ssl_read( void *conn, char *buf, int len )
+{
+	int st;
+	
+	if( !((struct scd*)conn)->established )
+	{
+		ssl_errno = SSL_NOHANDSHAKE;
+		return -1;
+	}
+	
+	st = SSL_read( ((struct scd*)conn)->ssl, buf, len );
+	
+	ssl_errno = SSL_OK;
+	if( st <= 0 )
+	{
+		((struct scd*)conn)->lasterr = SSL_get_error( ((struct scd*)conn)->ssl, st );
+		if( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_READ || ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE )
+			ssl_errno = SSL_AGAIN;
+	}
+	
+	return st;
+}
+
+int ssl_write( void *conn, const char *buf, int len )
+{
+	int st;
+	
+	if( !((struct scd*)conn)->established )
+	{
+		ssl_errno = SSL_NOHANDSHAKE;
+		return -1;
+	}
+	
+	st = SSL_write( ((struct scd*)conn)->ssl, buf, len );
+	
+	ssl_errno = SSL_OK;
+	if( st <= 0 )
+	{
+		((struct scd*)conn)->lasterr = SSL_get_error( ((struct scd*)conn)->ssl, st );
+		if( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_READ || ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE )
+			ssl_errno = SSL_AGAIN;
+	}
+	
+	return st;
+}
+
+void ssl_disconnect( void *conn_ )
+{
+	struct scd *conn = conn_;
+	
+	if( conn->inpa != -1 )
+		b_event_remove( conn->inpa );
+	
+	if( conn->established )
+		SSL_shutdown( conn->ssl );
+	
+	closesocket( conn->fd );
+	
+	SSL_free( conn->ssl );
+	SSL_CTX_free( conn->ssl_ctx );
+	g_free( conn );
+}
+
+int ssl_getfd( void *conn )
+{
+	return( ((struct scd*)conn)->fd );
+}
+
+b_input_condition ssl_getdirection( void *conn )
+{
+	return( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ? GAIM_INPUT_WRITE : GAIM_INPUT_READ );
+}
Index: lib/url.c
===================================================================
--- lib/url.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/url.c	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,107 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2001-2005 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/* URL/mirror stuff - Stolen from Axel                                  */
+
+/*
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "url.h"
+
+/* Convert an URL to a url_t structure					*/
+int url_set( url_t *url, char *set_url )
+{
+	char s[MAX_STRING];
+	char *i;
+	
+	/* protocol://							*/
+	if( ( i = strstr( set_url, "://" ) ) == NULL )
+	{
+		url->proto = PROTO_DEFAULT;
+		strncpy( s, set_url, MAX_STRING );
+	}
+	else
+	{
+		if( g_strncasecmp( set_url, "http", i - set_url ) == 0 )
+			url->proto = PROTO_HTTP;
+		else if( g_strncasecmp( set_url, "https", i - set_url ) == 0 )
+			url->proto = PROTO_HTTPS;
+		else if( g_strncasecmp( set_url, "socks4", i - set_url ) == 0 )
+			url->proto = PROTO_SOCKS4;
+		else if( g_strncasecmp( set_url, "socks5", i - set_url ) == 0 )
+			url->proto = PROTO_SOCKS5;
+		else
+		{
+			return( 0 );
+		}
+		strncpy( s, i + 3, MAX_STRING );
+	}
+	
+	/* Split							*/
+	if( ( i = strchr( s, '/' ) ) == NULL )
+	{
+		strcpy( url->file, "/" );
+	}
+	else
+	{
+		strncpy( url->file, i, MAX_STRING );
+		*i = 0;
+	}
+	strncpy( url->host, s, MAX_STRING );
+	
+	/* Check for username in host field				*/
+	if( strrchr( url->host, '@' ) != NULL )
+	{
+		strncpy( url->user, url->host, MAX_STRING );
+		i = strrchr( url->user, '@' );
+		*i = 0;
+		strcpy( url->host, i + 1 );
+		*url->pass = 0;
+	}
+	/* If not: Fill in defaults					*/
+	else
+	{
+		*url->user = *url->pass = 0;
+	}
+	
+	/* Password?							*/
+	if( ( i = strchr( url->user, ':' ) ) != NULL )
+	{
+		*i = 0;
+		strcpy( url->pass, i + 1 );
+	}
+	/* Port number?							*/
+	if( ( i = strchr( url->host, ':' ) ) != NULL )
+	{
+		*i = 0;
+		sscanf( i + 1, "%d", &url->port );
+	}
+	else
+	{
+		if( url->proto == PROTO_HTTP )
+			url->port = 80;
+		else if( url->proto == PROTO_HTTPS )
+			url->port = 443;
+		else if( url->proto == PROTO_SOCKS4 || url->proto == PROTO_SOCKS4 )
+			url->port = 1080;
+	}
+	
+	return( url->port > 0 );
+}
Index: lib/url.h
===================================================================
--- lib/url.h	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
+++ lib/url.h	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -0,0 +1,44 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2001-2004 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/* URL/mirror stuff - Stolen from Axel                                  */
+
+/*
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "bitlbee.h"
+
+#define PROTO_HTTP		2
+#define PROTO_HTTPS		5
+#define PROTO_SOCKS4	3
+#define PROTO_SOCKS5	4
+#define PROTO_DEFAULT	PROTO_HTTP
+
+typedef struct url
+{
+	int proto;
+	int port;
+	char host[MAX_STRING];
+	char file[MAX_STRING];
+	char user[MAX_STRING];
+	char pass[MAX_STRING];
+} url_t;
+
+int url_set( url_t *url, char *set_url );
Index: protocols/Makefile
===================================================================
--- protocols/Makefile	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ protocols/Makefile	(revision df1694b9559d4abec748b0506b5f44e684d022a8)
@@ -10,5 +10,5 @@
 
 # [SH] Program variables
-objects = $(EVENT_HANDLER) http_client.o md5.o nogaim.o proxy.o sha.o $(SSL_CLIENT)
+objects = nogaim.o
 
 # [SH] The next two lines should contain the directory name (in $(subdirs))
Index: otocols/events.h
===================================================================
--- protocols/events.h	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,66 +1,0 @@
-/*
- * nogaim
- *
- * Copyright (C) 2006 Wilmer van der Gaast and others
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-/*
- * Split off the event handling things from proxy.[ch] (and adding timer
- * stuff. This to allow BitlBee to use other libs than GLib for event
- * handling.
- */
-
-
-#ifndef _EVENTS_H_
-#define _EVENTS_H_
-
-#include <sys/types.h>
-#ifndef _WIN32
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#endif
-#include <glib.h>
-#include <gmodule.h>
-
-typedef enum {
-	GAIM_INPUT_READ = 1 << 1,
-	GAIM_INPUT_WRITE = 1 << 2
-} b_input_condition;
-typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition cond);
-
-#define GAIM_READ_COND  (G_IO_IN | G_IO_HUP | G_IO_ERR)
-#define GAIM_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
-#define GAIM_ERR_COND   (G_IO_HUP | G_IO_ERR | G_IO_NVAL)
-
-// #define event_debug( x... ) printf( x )
-#define event_debug( x... )
-
-G_MODULE_EXPORT void b_main_init();
-G_MODULE_EXPORT void b_main_run();
-G_MODULE_EXPORT void b_main_quit();
-
-G_MODULE_EXPORT gint b_input_add(int fd, b_input_condition cond, b_event_handler func, gpointer data);
-G_MODULE_EXPORT gint b_timeout_add(gint timeout, b_event_handler func, gpointer data);
-G_MODULE_EXPORT void b_event_remove(gint id);
-
-#ifdef EVENTS_LIBEVENT
-G_MODULE_EXPORT void closesocket(int fd);
-#endif
-
-#endif /* _EVENTS_H_ */
Index: otocols/events_glib.c
===================================================================
--- protocols/events_glib.c	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,137 +1,0 @@
-  /********************************************************************\
-  * BitlBee -- An IRC to other IM-networks gateway                     *
-  *                                                                    *
-  * Copyright 2002-2006 Wilmer van der Gaast and others                *
-  \********************************************************************/
-
-/*
- * Event handling (using GLib)
- */
-
-/*
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program 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 General Public License for more details.
-
-  You should have received a copy of the GNU General Public License with
-  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
-  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
-  Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#define BITLBEE_CORE
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#ifndef _WIN32
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#else
-#include "sock.h"
-#define ETIMEDOUT WSAETIMEDOUT
-#define EINPROGRESS WSAEINPROGRESS
-#endif
-#include <fcntl.h>
-#include <errno.h>
-#include "proxy.h"
-
-typedef struct _GaimIOClosure {
-	b_event_handler function;
-	guint result;
-	gpointer data;
-} GaimIOClosure;
-
-static GMainLoop *loop;
-
-void b_main_init()
-{
-	loop = g_main_new( FALSE );
-}
-
-void b_main_run()
-{
-	g_main_run( loop );
-}
-
-void b_main_quit()
-{
-	g_main_quit( loop );
-}
-
-static gboolean gaim_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data)
-{
-	GaimIOClosure *closure = data;
-	b_input_condition gaim_cond = 0;
-	gboolean st;
-
-	if (condition & GAIM_READ_COND)
-		gaim_cond |= GAIM_INPUT_READ;
-	if (condition & GAIM_WRITE_COND)
-		gaim_cond |= GAIM_INPUT_WRITE;
-	
-	event_debug( "gaim_io_invoke( %d, %d, 0x%x )\n", g_io_channel_unix_get_fd(source), condition, data );
-
-	st = closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond);
-	
-	if( !st )
-		event_debug( "Returned FALSE, cancelling.\n" );
-	
-	return st;
-}
-
-static void gaim_io_destroy(gpointer data)
-{
-	event_debug( "gaim_io_destroy( 0x%x )\n", data );
-	g_free(data);
-}
-
-gint b_input_add(gint source, b_input_condition condition, b_event_handler function, gpointer data)
-{
-	GaimIOClosure *closure = g_new0(GaimIOClosure, 1);
-	GIOChannel *channel;
-	GIOCondition cond = 0;
-	
-	closure->function = function;
-	closure->data = data;
-	
-	if (condition & GAIM_INPUT_READ)
-		cond |= GAIM_READ_COND;
-	if (condition & GAIM_INPUT_WRITE)
-		cond |= GAIM_WRITE_COND;
-	
-	channel = g_io_channel_unix_new(source);
-	closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond,
-					      gaim_io_invoke, closure, gaim_io_destroy);
-	
-	event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) = %d (0x%x)\n", source, condition, function, data, closure->result, closure );
-	
-	g_io_channel_unref(channel);
-	return closure->result;
-}
-
-gint b_timeout_add(gint timeout, b_event_handler func, gpointer data)
-{
-	gint st = g_timeout_add(timeout, func, data);
-	
-	event_debug( "b_timeout_add( %d, %d, %d ) = %d\n", timeout, func, data, st );
-	
-	return st;
-}
-
-void b_event_remove(gint tag)
-{
-	event_debug( "b_event_remove( %d )\n", tag );
-	
-	if (tag > 0)
-		g_source_remove(tag);
-}
Index: otocols/events_libevent.c
===================================================================
--- protocols/events_libevent.c	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,247 +1,0 @@
-  /********************************************************************\
-  * BitlBee -- An IRC to other IM-networks gateway                     *
-  *                                                                    *
-  * Copyright 2002-2006 Wilmer van der Gaast and others                *
-  \********************************************************************/
-
-/*
- * Event handling (using libevent)
- */
-
-/*
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program 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 General Public License for more details.
-
-  You should have received a copy of the GNU General Public License with
-  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
-  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
-  Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#define BITLBEE_CORE
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include "proxy.h"
-
-#include <sys/time.h>
-#include <event.h>
-
-static guint id_next;
-static GHashTable *id_hash;
-static int quitting = 0;
-
-/* Since libevent doesn't handle two event handlers for one fd-condition
-   very well (which happens sometimes when BitlBee changes event handlers
-   for a combination), let's buid some indexes so we can delete them here
-   already, just in time. */
-static GHashTable *read_hash;
-static GHashTable *write_hash;
-
-struct b_event_data
-{
-	guint id;
-	struct event evinfo;
-	gint timeout;
-	b_event_handler function;
-	void *data;
-};
-
-void b_main_init()
-{
-	event_init();
-	
-	id_next = 1;
-	id_hash = g_hash_table_new( g_int_hash, g_int_equal );
-	read_hash = g_hash_table_new( g_int_hash, g_int_equal );
-	write_hash = g_hash_table_new( g_int_hash, g_int_equal );
-}
-
-void b_main_run()
-{
-	event_dispatch();
-}
-
-void b_main_quit()
-{
-	struct timeval tv;
-	
-	/* libevent sometimes generates events before really quitting,
-	   we want to stop them. */
-	quitting = 1;
-	
-	memset( &tv, 0, sizeof( struct timeval ) );
-	event_loopexit( &tv );
-}
-
-static void b_event_passthrough( int fd, short event, void *data )
-{
-	struct b_event_data *b_ev = data;
-	b_input_condition cond = 0;
-	int id;
-	
-	if( fd >= 0 )
-	{
-		if( event & EV_READ )
-			cond |= GAIM_INPUT_READ;
-		if( event & EV_WRITE )
-			cond |= GAIM_INPUT_WRITE;
-	}
-	
-	event_debug( "b_event_passthrough( %d, %d, 0x%x ) (%d)\n", fd, event, (int) data, b_ev->id );
-	
-	/* 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;
-	
-	if( quitting )
-	{
-		b_event_remove( id );
-		return;
-	}
-	
-	if( !b_ev->function( b_ev->data, fd, cond ) )
-	{
-		event_debug( "Handler returned FALSE: " );
-		b_event_remove( id );
-	}
-	else if( fd == -1 )
-	{
-		struct timeval tv;
-		
-		tv.tv_sec = b_ev->timeout / 1000;
-		tv.tv_usec = ( b_ev->timeout % 1000 ) * 1000;
-		
-		evtimer_add( &b_ev->evinfo, &tv );
-	}
-}
-
-gint b_input_add( gint fd, b_input_condition condition, b_event_handler function, gpointer data )
-{
-	struct b_event_data *b_ev;
-	
-	event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) ", fd, condition, function, data );
-	
-	if( ( condition & GAIM_INPUT_READ  && ( b_ev = g_hash_table_lookup( read_hash,  &fd ) ) ) ||
-	    ( condition & GAIM_INPUT_WRITE && ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) )
-	{
-		/* We'll stick with this libevent entry, but give it a new BitlBee id. */
-		g_hash_table_remove( id_hash, &b_ev->id );
-		
-		event_debug( "(replacing old handler (id = %d)) = %d\n", b_ev->id, id_next );
-		
-		b_ev->id = id_next++;
-		b_ev->function = function;
-		b_ev->data = data;
-	}
-	else
-	{
-		GIOCondition out_cond;
-		
-		event_debug( "(new) = %d\n", id_next );
-		
-		b_ev = g_new0( struct b_event_data, 1 );
-		b_ev->id = id_next++;
-		b_ev->function = function;
-		b_ev->data = data;
-		
-		out_cond = EV_PERSIST;
-		if( condition & GAIM_INPUT_READ )
-			out_cond |= EV_READ;
-		if( condition & GAIM_INPUT_WRITE )
-			out_cond |= EV_WRITE;
-		
-		event_set( &b_ev->evinfo, fd, out_cond, b_event_passthrough, b_ev );
-		event_add( &b_ev->evinfo, NULL );
-		
-		if( out_cond & EV_READ )
-			g_hash_table_insert( read_hash, &b_ev->evinfo.ev_fd, b_ev );
-		if( out_cond & EV_WRITE )
-			g_hash_table_insert( write_hash, &b_ev->evinfo.ev_fd, b_ev );
-	}
-	
-	g_hash_table_insert( id_hash, &b_ev->id, b_ev );
-	return b_ev->id;
-}
-
-/* TODO: Persistence for timers! */
-gint b_timeout_add( gint timeout, b_event_handler function, gpointer data )
-{
-	struct b_event_data *b_ev = g_new0( struct b_event_data, 1 );
-	struct timeval tv;
-	
-	b_ev->id = id_next++;
-	b_ev->timeout = timeout;
-	b_ev->function = function;
-	b_ev->data = data;
-	
-	tv.tv_sec = timeout / 1000;
-	tv.tv_usec = ( timeout % 1000 ) * 1000;
-	
-	evtimer_set( &b_ev->evinfo, b_event_passthrough, b_ev );
-	evtimer_add( &b_ev->evinfo, &tv );
-	
-	event_debug( "b_timeout_add( %d, 0x%x, 0x%x ) = %d\n", timeout, function, data, b_ev->id );
-	
-	g_hash_table_insert( id_hash, &b_ev->id, b_ev );
-	
-	return b_ev->id;
-}
-
-void b_event_remove( gint id )
-{
-	struct b_event_data *b_ev = g_hash_table_lookup( id_hash, &id );
-	
-	event_debug( "b_event_remove( %d )\n", id );
-	if( b_ev )
-	{
-		g_hash_table_remove( id_hash, &b_ev->id );
-		if( b_ev->evinfo.ev_fd >= 0 )
-		{
-			if( b_ev->evinfo.ev_events & EV_READ )
-				g_hash_table_remove( read_hash, &b_ev->evinfo.ev_fd );
-			if( b_ev->evinfo.ev_events & EV_WRITE )
-				g_hash_table_remove( write_hash, &b_ev->evinfo.ev_fd );
-		}
-		
-		event_del( &b_ev->evinfo );
-		g_free( b_ev );
-	}
-	else
-	{
-		event_debug( "Already removed?\n" );
-	}
-}
-
-void closesocket( int fd )
-{
-	struct b_event_data *b_ev;
-	
-	/* Since epoll() (the main reason we use libevent) automatically removes sockets from
-	   the epoll() list when a socket gets closed and some modules have a habit of
-	   closing sockets before removing event handlers, our and libevent's administration
-	   get a little bit messed up. So this little function will remove the handlers
-	   properly before closing a socket. */
-	
-	if( ( b_ev = g_hash_table_lookup( read_hash, &fd ) ) )
-	{
-		event_debug( "Warning: fd %d still had a read event handler when shutting down.\n", fd );
-		b_event_remove( b_ev->id );
-	}
-	if( ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) )
-	{
-		event_debug( "Warning: fd %d still had a write event handler when shutting down.\n", fd );
-		b_event_remove( b_ev->id );
-	}
-	
-	close( fd );
-}
Index: otocols/http_client.c
===================================================================
--- protocols/http_client.c	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,453 +1,0 @@
-  /********************************************************************\
-  * BitlBee -- An IRC to other IM-networks gateway                     *
-  *                                                                    *
-  * Copyright 2002-2005 Wilmer van der Gaast and others                *
-  \********************************************************************/
-
-/* HTTP(S) module                                                       */
-
-/*
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program 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 General Public License for more details.
-
-  You should have received a copy of the GNU General Public License with
-  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
-  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
-  Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <string.h>
-#include <stdio.h>
-
-#include "http_client.h"
-#include "url.h"
-#include "sock.h"
-
-
-static gboolean http_connected( gpointer data, int source, b_input_condition cond );
-static gboolean http_ssl_connected( gpointer data, void *source, b_input_condition cond );
-static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond );
-
-
-void *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data )
-{
-	struct http_request *req;
-	int error = 0;
-	
-	req = g_new0( struct http_request, 1 );
-	
-	if( ssl )
-	{
-		req->ssl = ssl_connect( host, port, http_ssl_connected, req );
-		if( req->ssl == NULL )
-			error = 1;
-	}
-	else
-	{
-		req->fd = proxy_connect( host, port, http_connected, req );
-		if( req->fd < 0 )
-			error = 1;
-	}
-	
-	if( error )
-	{
-		g_free( req );
-		return( NULL );
-	}
-	
-	req->func = func;
-	req->data = data;
-	req->request = g_strdup( request );
-	req->request_length = strlen( request );
-	
-	return( req );
-}
-
-void *http_dorequest_url( char *url_string, http_input_function func, gpointer data )
-{
-	url_t *url = g_new0( url_t, 1 );
-	char *request;
-	void *ret;
-	
-	if( !url_set( url, url_string ) )
-	{
-		g_free( url );
-		return NULL;
-	}
-	
-	if( url->proto != PROTO_HTTP && url->proto != PROTO_HTTPS )
-	{
-		g_free( url );
-		return NULL;
-	}
-	
-	request = g_strdup_printf( "GET %s HTTP/1.0\r\n"
-	                           "Host: %s\r\n"
-	                           "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n"
-	                           "\r\n", url->file, url->host );
-	
-	ret = http_dorequest( url->host, url->port,
-	                      url->proto == PROTO_HTTPS, request, func, data );
-	
-	g_free( url );
-	g_free( request );
-	return ret;
-}
-
-/* This one is actually pretty simple... Might get more calls if we can't write 
-   the whole request at once. */
-static gboolean http_connected( gpointer data, int source, b_input_condition cond )
-{
-	struct http_request *req = data;
-	int st;
-	
-	if( source < 0 )
-		goto error;
-	
-	if( req->inpa > 0 )
-		b_event_remove( req->inpa );
-	
-	sock_make_nonblocking( req->fd );
-	
-	if( req->ssl )
-	{
-		st = ssl_write( req->ssl, req->request + req->bytes_written,
-		                req->request_length - req->bytes_written );
-		if( st < 0 )
-		{
-			if( ssl_errno != SSL_AGAIN )
-			{
-				ssl_disconnect( req->ssl );
-				goto error;
-			}
-		}
-	}
-	else
-	{
-		st = write( source, req->request + req->bytes_written,
-		                    req->request_length - req->bytes_written );
-		if( st < 0 )
-		{
-			if( !sockerr_again() )
-			{
-				closesocket( req->fd );
-				goto error;
-			}
-		}
-	}
-	
-	if( st > 0 )
-		req->bytes_written += st;
-	
-	if( req->bytes_written < req->request_length )
-		req->inpa = b_input_add( source,
-		                         req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_WRITE,
-	        	                 http_connected, req );
-	else
-		req->inpa = b_input_add( source, GAIM_INPUT_READ, http_incoming_data, req );
-	
-	return FALSE;
-	
-error:
-	req->status_string = g_strdup( "Error while writing HTTP request" );
-	
-	req->func( req );
-	
-	g_free( req->request );
-	g_free( req );
-	
-	return FALSE;
-}
-
-static gboolean http_ssl_connected( gpointer data, void *source, b_input_condition cond )
-{
-	struct http_request *req = data;
-	
-	if( source == NULL )
-		return http_connected( data, -1, cond );
-	
-	req->fd = ssl_getfd( source );
-	
-	return http_connected( data, req->fd, cond );
-}
-
-static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond )
-{
-	struct http_request *req = data;
-	int evil_server = 0;
-	char buffer[2048];
-	char *end1, *end2;
-	int st;
-	
-	if( req->inpa > 0 )
-		b_event_remove( req->inpa );
-	
-	if( req->ssl )
-	{
-		st = ssl_read( req->ssl, buffer, sizeof( buffer ) );
-		if( st < 0 )
-		{
-			if( ssl_errno != SSL_AGAIN )
-			{
-				/* goto cleanup; */
-				
-				/* YAY! We have to deal with crappy Microsoft
-				   servers that LOVE to send invalid TLS
-				   packets that abort connections! \o/ */
-				
-				goto got_reply;
-			}
-		}
-		else if( st == 0 )
-		{
-			goto got_reply;
-		}
-	}
-	else
-	{
-		st = read( req->fd, buffer, sizeof( buffer ) );
-		if( st < 0 )
-		{
-			if( !sockerr_again() )
-			{
-				req->status_string = g_strdup( strerror( errno ) );
-				goto cleanup;
-			}
-		}
-		else if( st == 0 )
-		{
-			goto got_reply;
-		}
-	}
-	
-	if( st > 0 )
-	{
-		req->reply_headers = g_realloc( req->reply_headers, req->bytes_read + st + 1 );
-		memcpy( req->reply_headers + req->bytes_read, buffer, st );
-		req->bytes_read += st;
-	}
-	
-	/* There will be more! */
-	req->inpa = b_input_add( req->fd,
-	                         req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_READ,
-	                         http_incoming_data, req );
-	
-	return FALSE;
-
-got_reply:
-	/* Maybe if the webserver is overloaded, or when there's bad SSL
-	   support... */
-	if( req->bytes_read == 0 )
-	{
-		req->status_string = g_strdup( "Empty HTTP reply" );
-		goto cleanup;
-	}
-	
-	/* Zero termination is very convenient. */
-	req->reply_headers[req->bytes_read] = 0;
-	
-	/* Find the separation between headers and body, and keep stupid
-	   webservers in mind. */
-	end1 = strstr( req->reply_headers, "\r\n\r\n" );
-	end2 = strstr( req->reply_headers, "\n\n" );
-	
-	if( end2 && end2 < end1 )
-	{
-		end1 = end2 + 1;
-		evil_server = 1;
-	}
-	else if( end1 )
-	{
-		end1 += 2;
-	}
-	else
-	{
-		req->status_string = g_strdup( "Malformed HTTP reply" );
-		goto cleanup;
-	}
-	
-	*end1 = 0;
-	
-	if( evil_server )
-		req->reply_body = end1 + 1;
-	else
-		req->reply_body = end1 + 2;
-	
-	req->body_size = req->reply_headers + req->bytes_read - req->reply_body;
-	
-	if( ( end1 = strchr( req->reply_headers, ' ' ) ) != NULL )
-	{
-		if( sscanf( end1 + 1, "%d", &req->status_code ) != 1 )
-		{
-			req->status_string = g_strdup( "Can't parse status code" );
-			req->status_code = -1;
-		}
-		else
-		{
-			char *eol;
-			
-			if( evil_server )
-				eol = strchr( end1, '\n' );
-			else
-				eol = strchr( end1, '\r' );
-			
-			req->status_string = g_strndup( end1 + 1, eol - end1 - 1 );
-			
-			/* Just to be sure... */
-			if( ( eol = strchr( req->status_string, '\r' ) ) )
-				*eol = 0;
-			if( ( eol = strchr( req->status_string, '\n' ) ) )
-				*eol = 0;
-		}
-	}
-	else
-	{
-		req->status_string = g_strdup( "Can't locate status code" );
-		req->status_code = -1;
-	}
-	
-	if( req->status_code == 301 || req->status_code == 302 )
-	{
-		char *loc, *new_request, *new_host;
-		int error = 0, new_port, new_proto;
-		
-		/* We might fill it again, so let's not leak any memory. */
-		g_free( req->status_string );
-		req->status_string = NULL;
-		
-		loc = strstr( req->reply_headers, "\nLocation: " );
-		if( loc == NULL ) /* We can't handle this redirect... */
-		{
-			req->status_string = g_strdup( "Can't locate Location: header" );
-			goto cleanup;
-		}
-		
-		loc += 11;
-		while( *loc == ' ' )
-			loc ++;
-		
-		/* TODO/FIXME: Possibly have to handle relative redirections,
-		   and rewrite Host: headers. Not necessary for now, it's
-		   enough for passport authentication like this. */
-		
-		if( *loc == '/' )
-		{
-			/* Just a different pathname... */
-			
-			/* Since we don't cache the servername, and since we
-			   don't need this yet anyway, I won't implement it. */
-			
-			req->status_string = g_strdup( "Can't handle recursive redirects" );
-			
-			goto cleanup;
-		}
-		else
-		{
-			/* A whole URL */
-			url_t *url;
-			char *s;
-			
-			s = strstr( loc, "\r\n" );
-			if( s == NULL )
-				goto cleanup;
-			
-			url = g_new0( url_t, 1 );
-			*s = 0;
-			
-			if( !url_set( url, loc ) )
-			{
-				req->status_string = g_strdup( "Malformed redirect URL" );
-				g_free( url );
-				goto cleanup;
-			}
-			
-			/* Okay, this isn't fun! We have to rebuild the request... :-( */
-			new_request = g_malloc( req->request_length + strlen( url->file ) );
-			
-			/* So, now I just allocated enough memory, so I'm
-			   going to use strcat(), whether you like it or not. :-) */
-			
-			sprintf( new_request, "GET %s HTTP/1.0", url->file );
-			
-			s = strstr( req->request, "\r\n" );
-			if( s == NULL )
-			{
-				req->status_string = g_strdup( "Error while rebuilding request string" );
-				g_free( new_request );
-				g_free( url );
-				goto cleanup;
-			}
-			
-			strcat( new_request, s );
-			new_host = g_strdup( url->host );
-			new_port = url->port;
-			new_proto = url->proto;
-			
-			g_free( url );
-		}
-		
-		if( req->ssl )
-			ssl_disconnect( req->ssl );
-		else
-			closesocket( req->fd );
-		
-		req->fd = -1;
-		req->ssl = NULL;
-		
-		if( new_proto == PROTO_HTTPS )
-		{
-			req->ssl = ssl_connect( new_host, new_port, http_ssl_connected, req );
-			if( req->ssl == NULL )
-				error = 1;
-		}
-		else
-		{
-			req->fd = proxy_connect( new_host, new_port, http_connected, req );
-			if( req->fd < 0 )
-				error = 1;
-		}
-		g_free( new_host );
-		
-		if( error )
-		{
-			req->status_string = g_strdup( "Connection problem during redirect" );
-			g_free( new_request );
-			goto cleanup;
-		}
-		
-		g_free( req->request );
-		g_free( req->reply_headers );
-		req->request = new_request;
-		req->request_length = strlen( new_request );
-		req->bytes_read = req->bytes_written = req->inpa = 0;
-		req->reply_headers = req->reply_body = NULL;
-		
-		return FALSE;
-	}
-	
-	/* Assume that a closed connection means we're finished, this indeed
-	   breaks with keep-alive connections and faulty connections. */
-	req->finished = 1;
-
-cleanup:
-	if( req->ssl )
-		ssl_disconnect( req->ssl );
-	else
-		closesocket( req->fd );
-	
-	req->func( req );
-	
-	g_free( req->request );
-	g_free( req->reply_headers );
-	g_free( req->status_string );
-	g_free( req );
-	
-	return FALSE;
-}
Index: otocols/http_client.h
===================================================================
--- protocols/http_client.h	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,57 +1,0 @@
-  /********************************************************************\
-  * BitlBee -- An IRC to other IM-networks gateway                     *
-  *                                                                    *
-  * Copyright 2002-2005 Wilmer van der Gaast and others                *
-  \********************************************************************/
-
-/* HTTP(S) module                                                       */
-
-/*
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program 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 General Public License for more details.
-
-  You should have received a copy of the GNU General Public License with
-  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
-  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
-  Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <glib.h>
-
-#include "ssl_client.h"
-
-struct http_request;
-
-typedef void (*http_input_function)( struct http_request * );
-
-struct http_request
-{
-	char *request;
-	int request_length;
-	int status_code;
-	char *status_string;
-	char *reply_headers;
-	char *reply_body;
-	int body_size;
-	int finished;
-	
-	void *ssl;
-	int fd;
-	
-	int inpa;
-	int bytes_written;
-	int bytes_read;
-	
-	http_input_function func;
-	gpointer data;
-};
-
-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 );
Index: otocols/md5.c
===================================================================
--- protocols/md5.c	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,392 +1,0 @@
-/*
-  Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-
-  L. Peter Deutsch
-  ghost@aladdin.com
-
- */
-/*
-  Independent implementation of MD5 (RFC 1321).
-
-  This code implements the MD5 Algorithm defined in RFC 1321.
-  It is derived directly from the text of the RFC and not from the
-  reference implementation.
-
-  The original and principal author of md5.c is L. Peter Deutsch
-  <ghost@aladdin.com>.  Other authors are noted in the change history
-  that follows (in reverse chronological order):
-
-  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
-  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
-  1999-05-03 lpd Original version.
- */
-
-#include "md5.h"
-#include <string.h>
-
-#ifdef TEST
-/*
- * Compile with -DTEST to create a self-contained executable test program.
- * The test program should print out the same values as given in section
- * A.5 of RFC 1321, reproduced below.
- */
-#include <string.h>
-main()
-{
-    static const char *const test[7] = {
-	"", /*d41d8cd98f00b204e9800998ecf8427e*/
-	"945399884.61923487334tuvga", /*0cc175b9c0f1b6a831c399e269772661*/
-	"abc", /*900150983cd24fb0d6963f7d28e17f72*/
-	"message digest", /*f96b697d7cb7938d525a2f31aaf161d0*/
-	"abcdefghijklmnopqrstuvwxyz", /*c3fcd3d76192e4007dfb496cca67e13b*/
-	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
-				/*d174ab98d277d9f5a5611c2c9f419d9f*/
-	"12345678901234567890123456789012345678901234567890123456789012345678901234567890" /*57edf4a22be3c955ac49da2e2107b67a*/
-    };
-    int i;
-
-    for (i = 0; i < 7; ++i) {
-	md5_state_t state;
-	md5_byte_t digest[16];
-	int di;
-
-	md5_init(&state);
-	md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i]));
-	md5_finish(&state, digest);
-	printf("MD5 (\"%s\") = ", test[i]);
-	for (di = 0; di < 16; ++di)
-	    printf("%02x", digest[di]);
-	printf("\n");
-    }
-    return 0;
-}
-#endif /* TEST */
-
-
-/*
- * For reference, here is the program that computed the T values.
- */
-#if 0
-#include <math.h>
-main()
-{
-    int i;
-    for (i = 1; i <= 64; ++i) {
-	unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i)));
-	printf("#define T%d 0x%08lx\n", i, v);
-    }
-    return 0;
-}
-#endif
-/*
- * End of T computation program.
- */
-#define T1 0xd76aa478
-#define T2 0xe8c7b756
-#define T3 0x242070db
-#define T4 0xc1bdceee
-#define T5 0xf57c0faf
-#define T6 0x4787c62a
-#define T7 0xa8304613
-#define T8 0xfd469501
-#define T9 0x698098d8
-#define T10 0x8b44f7af
-#define T11 0xffff5bb1
-#define T12 0x895cd7be
-#define T13 0x6b901122
-#define T14 0xfd987193
-#define T15 0xa679438e
-#define T16 0x49b40821
-#define T17 0xf61e2562
-#define T18 0xc040b340
-#define T19 0x265e5a51
-#define T20 0xe9b6c7aa
-#define T21 0xd62f105d
-#define T22 0x02441453
-#define T23 0xd8a1e681
-#define T24 0xe7d3fbc8
-#define T25 0x21e1cde6
-#define T26 0xc33707d6
-#define T27 0xf4d50d87
-#define T28 0x455a14ed
-#define T29 0xa9e3e905
-#define T30 0xfcefa3f8
-#define T31 0x676f02d9
-#define T32 0x8d2a4c8a
-#define T33 0xfffa3942
-#define T34 0x8771f681
-#define T35 0x6d9d6122
-#define T36 0xfde5380c
-#define T37 0xa4beea44
-#define T38 0x4bdecfa9
-#define T39 0xf6bb4b60
-#define T40 0xbebfbc70
-#define T41 0x289b7ec6
-#define T42 0xeaa127fa
-#define T43 0xd4ef3085
-#define T44 0x04881d05
-#define T45 0xd9d4d039
-#define T46 0xe6db99e5
-#define T47 0x1fa27cf8
-#define T48 0xc4ac5665
-#define T49 0xf4292244
-#define T50 0x432aff97
-#define T51 0xab9423a7
-#define T52 0xfc93a039
-#define T53 0x655b59c3
-#define T54 0x8f0ccc92
-#define T55 0xffeff47d
-#define T56 0x85845dd1
-#define T57 0x6fa87e4f
-#define T58 0xfe2ce6e0
-#define T59 0xa3014314
-#define T60 0x4e0811a1
-#define T61 0xf7537e82
-#define T62 0xbd3af235
-#define T63 0x2ad7d2bb
-#define T64 0xeb86d391
-
-static void
-md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
-{
-    md5_word_t
-	a = pms->abcd[0], b = pms->abcd[1],
-	c = pms->abcd[2], d = pms->abcd[3];
-    md5_word_t t;
-
-#ifndef ARCH_IS_BIG_ENDIAN
-# define ARCH_IS_BIG_ENDIAN 1	/* slower, default implementation */
-#endif
-#if ARCH_IS_BIG_ENDIAN
-
-    /*
-     * On big-endian machines, we must arrange the bytes in the right
-     * order.  (This also works on machines of unknown byte order.)
-     */
-    md5_word_t X[16];
-    const md5_byte_t *xp = data;
-    int i;
-
-    for (i = 0; i < 16; ++i, xp += 4)
-	X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
-
-#else  /* !ARCH_IS_BIG_ENDIAN */
-
-    /*
-     * On little-endian machines, we can process properly aligned data
-     * without copying it.
-     */
-    md5_word_t xbuf[16];
-    const md5_word_t *X;
-
-    if (!((data - (const md5_byte_t *)0) & 3)) {
-	/* data are properly aligned */
-	X = (const md5_word_t *)data;
-    } else {
-	/* not aligned */
-	memcpy(xbuf, data, 64);
-	X = xbuf;
-    }
-#endif
-
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
-
-    /* Round 1. */
-    /* Let [abcd k s i] denote the operation
-       a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
-#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + F(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-    /* Do the following 16 operations. */
-    SET(a, b, c, d,  0,  7,  T1);
-    SET(d, a, b, c,  1, 12,  T2);
-    SET(c, d, a, b,  2, 17,  T3);
-    SET(b, c, d, a,  3, 22,  T4);
-    SET(a, b, c, d,  4,  7,  T5);
-    SET(d, a, b, c,  5, 12,  T6);
-    SET(c, d, a, b,  6, 17,  T7);
-    SET(b, c, d, a,  7, 22,  T8);
-    SET(a, b, c, d,  8,  7,  T9);
-    SET(d, a, b, c,  9, 12, T10);
-    SET(c, d, a, b, 10, 17, T11);
-    SET(b, c, d, a, 11, 22, T12);
-    SET(a, b, c, d, 12,  7, T13);
-    SET(d, a, b, c, 13, 12, T14);
-    SET(c, d, a, b, 14, 17, T15);
-    SET(b, c, d, a, 15, 22, T16);
-#undef SET
-
-     /* Round 2. */
-     /* Let [abcd k s i] denote the operation
-          a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
-#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + G(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-     /* Do the following 16 operations. */
-    SET(a, b, c, d,  1,  5, T17);
-    SET(d, a, b, c,  6,  9, T18);
-    SET(c, d, a, b, 11, 14, T19);
-    SET(b, c, d, a,  0, 20, T20);
-    SET(a, b, c, d,  5,  5, T21);
-    SET(d, a, b, c, 10,  9, T22);
-    SET(c, d, a, b, 15, 14, T23);
-    SET(b, c, d, a,  4, 20, T24);
-    SET(a, b, c, d,  9,  5, T25);
-    SET(d, a, b, c, 14,  9, T26);
-    SET(c, d, a, b,  3, 14, T27);
-    SET(b, c, d, a,  8, 20, T28);
-    SET(a, b, c, d, 13,  5, T29);
-    SET(d, a, b, c,  2,  9, T30);
-    SET(c, d, a, b,  7, 14, T31);
-    SET(b, c, d, a, 12, 20, T32);
-#undef SET
-
-     /* Round 3. */
-     /* Let [abcd k s t] denote the operation
-          a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + H(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-     /* Do the following 16 operations. */
-    SET(a, b, c, d,  5,  4, T33);
-    SET(d, a, b, c,  8, 11, T34);
-    SET(c, d, a, b, 11, 16, T35);
-    SET(b, c, d, a, 14, 23, T36);
-    SET(a, b, c, d,  1,  4, T37);
-    SET(d, a, b, c,  4, 11, T38);
-    SET(c, d, a, b,  7, 16, T39);
-    SET(b, c, d, a, 10, 23, T40);
-    SET(a, b, c, d, 13,  4, T41);
-    SET(d, a, b, c,  0, 11, T42);
-    SET(c, d, a, b,  3, 16, T43);
-    SET(b, c, d, a,  6, 23, T44);
-    SET(a, b, c, d,  9,  4, T45);
-    SET(d, a, b, c, 12, 11, T46);
-    SET(c, d, a, b, 15, 16, T47);
-    SET(b, c, d, a,  2, 23, T48);
-#undef SET
-
-     /* Round 4. */
-     /* Let [abcd k s t] denote the operation
-          a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
-#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + I(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-     /* Do the following 16 operations. */
-    SET(a, b, c, d,  0,  6, T49);
-    SET(d, a, b, c,  7, 10, T50);
-    SET(c, d, a, b, 14, 15, T51);
-    SET(b, c, d, a,  5, 21, T52);
-    SET(a, b, c, d, 12,  6, T53);
-    SET(d, a, b, c,  3, 10, T54);
-    SET(c, d, a, b, 10, 15, T55);
-    SET(b, c, d, a,  1, 21, T56);
-    SET(a, b, c, d,  8,  6, T57);
-    SET(d, a, b, c, 15, 10, T58);
-    SET(c, d, a, b,  6, 15, T59);
-    SET(b, c, d, a, 13, 21, T60);
-    SET(a, b, c, d,  4,  6, T61);
-    SET(d, a, b, c, 11, 10, T62);
-    SET(c, d, a, b,  2, 15, T63);
-    SET(b, c, d, a,  9, 21, T64);
-#undef SET
-
-     /* Then perform the following additions. (That is increment each
-        of the four registers by the value it had before this block
-        was started.) */
-    pms->abcd[0] += a;
-    pms->abcd[1] += b;
-    pms->abcd[2] += c;
-    pms->abcd[3] += d;
-}
-
-void
-md5_init(md5_state_t *pms)
-{
-    pms->count[0] = pms->count[1] = 0;
-    pms->abcd[0] = 0x67452301;
-    pms->abcd[1] = 0xefcdab89;
-    pms->abcd[2] = 0x98badcfe;
-    pms->abcd[3] = 0x10325476;
-}
-
-void
-md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
-{
-    const md5_byte_t *p = data;
-    int left = nbytes;
-    int offset = (pms->count[0] >> 3) & 63;
-    md5_word_t nbits = (md5_word_t)(nbytes << 3);
-
-    if (nbytes <= 0)
-	return;
-
-    /* Update the message length. */
-    pms->count[1] += nbytes >> 29;
-    pms->count[0] += nbits;
-    if (pms->count[0] < nbits)
-	pms->count[1]++;
-
-    /* Process an initial partial block. */
-    if (offset) {
-	int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
-
-	memcpy(pms->buf + offset, p, copy);
-	if (offset + copy < 64)
-	    return;
-	p += copy;
-	left -= copy;
-	md5_process(pms, pms->buf);
-    }
-
-    /* Process full blocks. */
-    for (; left >= 64; p += 64, left -= 64)
-	md5_process(pms, p);
-
-    /* Process a final partial block. */
-    if (left)
-	memcpy(pms->buf, p, left);
-}
-
-void
-md5_finish(md5_state_t *pms, md5_byte_t digest[16])
-{
-    static const md5_byte_t pad[64] = {
-	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-    };
-    md5_byte_t data[8];
-    int i;
-
-    /* Save the length before padding. */
-    for (i = 0; i < 8; ++i)
-	data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
-    /* Pad to 56 bytes mod 64. */
-    md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
-    /* Append the length. */
-    md5_append(pms, data, 8);
-    for (i = 0; i < 16; ++i)
-	digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
-}
Index: otocols/md5.h
===================================================================
--- protocols/md5.h	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,85 +1,0 @@
-/*
-  Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.
-  
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-
-  L. Peter Deutsch
-  ghost@aladdin.com
-
- */
-/*
-  Independent implementation of MD5 (RFC 1321).
-
-  This code implements the MD5 Algorithm defined in RFC 1321.
-  It is derived directly from the text of the RFC and not from the
-  reference implementation.
-
-  The original and principal author of md5.h is L. Peter Deutsch
-  <ghost@aladdin.com>.  Other authors are noted in the change history
-  that follows (in reverse chronological order):
-
-  2004-03-09 Jelmer Vernooij add G_MODULE_EXPORT for Bitlbee
-  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
-  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
-	added conditionalization for C++ compilation from Martin
-	Purschke <purschke@bnl.gov>.
-  1999-05-03 lpd Original version.
- */
-
-#ifndef md5_INCLUDED
-#  define md5_INCLUDED
-
-#include <glib.h>
-#include <gmodule.h>
-
-/*
- * This code has some adaptations for the Ghostscript environment, but it
- * will compile and run correctly in any environment with 8-bit chars and
- * 32-bit ints.  Specifically, it assumes that if the following are
- * defined, they have the same meaning as in Ghostscript: P1, P2, P3,
- * ARCH_IS_BIG_ENDIAN.
- */
-
-typedef unsigned char md5_byte_t; /* 8-bit byte */
-typedef unsigned int md5_word_t; /* 32-bit word */
-
-/* Define the state of the MD5 Algorithm. */
-typedef struct md5_state_s {
-    md5_word_t count[2];	/* message length in bits, lsw first */
-    md5_word_t abcd[4];		/* digest buffer */
-    md5_byte_t buf[64];		/* accumulate block */
-} md5_state_t;
-
-#ifdef __cplusplus
-extern "C" 
-{
-#endif
-
-/* Initialize the algorithm. */
-G_MODULE_EXPORT void md5_init(md5_state_t *pms);
-
-/* Append a string to the message. */
-G_MODULE_EXPORT void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
-
-/* Finish the message and return the digest. */
-G_MODULE_EXPORT void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
-
-#ifdef __cplusplus
-}  /* end extern "C" */
-#endif
-
-#endif /* md5_INCLUDED */
Index: otocols/proxy.c
===================================================================
--- protocols/proxy.c	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,556 +1,0 @@
-/*
- * gaim
- *
- * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
- * Copyright (C) 2002-2004, Wilmer van der Gaast, Jelmer Vernooij
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#define BITLBEE_CORE
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#ifndef _WIN32
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#else
-#include "sock.h"
-#define ETIMEDOUT WSAETIMEDOUT
-#define EINPROGRESS WSAEINPROGRESS
-#endif
-#include <fcntl.h>
-#include <errno.h>
-#include "nogaim.h"
-#include "proxy.h"
-
-char proxyhost[128] = "";
-int proxyport = 0;
-int proxytype = PROXY_NONE;
-char proxyuser[128] = "";
-char proxypass[128] = "";
-
-struct PHB {
-	b_event_handler func, proxy_func;
-	gpointer data, proxy_data;
-	char *host;
-	int port;
-	int fd;
-	gint inpa;
-};
-
-
-
-static struct sockaddr_in *gaim_gethostbyname(const char *host, int port)
-{
-	static struct sockaddr_in sin;
-
-	if (!inet_aton(host, &sin.sin_addr)) {
-		struct hostent *hp;
-		if (!(hp = gethostbyname(host))) {
-			return NULL;
-		}
-		memset(&sin, 0, sizeof(struct sockaddr_in));
-		memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
-		sin.sin_family = hp->h_addrtype;
-	} else
-		sin.sin_family = AF_INET;
-	sin.sin_port = htons(port);
-
-	return &sin;
-}
-
-static gboolean gaim_io_connected(gpointer data, gint source, b_input_condition cond)
-{
-	struct PHB *phb = data;
-	unsigned int len;
-	int error = ETIMEDOUT;
-	len = sizeof(error);
-	
-#ifndef _WIN32
-	if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
-		closesocket(source);
-		b_event_remove(phb->inpa);
-		if( phb->proxy_func )
-			phb->proxy_func(phb->proxy_data, -1, GAIM_INPUT_READ);
-		else {
-			phb->func(phb->data, -1, GAIM_INPUT_READ);
-			g_free(phb);
-		}
-		return FALSE;
-	}
-#endif
-	sock_make_blocking(source);
-	b_event_remove(phb->inpa);
-	if( phb->proxy_func )
-		phb->proxy_func(phb->proxy_data, source, GAIM_INPUT_READ);
-	else {
-		phb->func(phb->data, source, GAIM_INPUT_READ);
-		g_free(phb);
-	}
-	
-	return FALSE;
-}
-
-static int proxy_connect_none(const char *host, unsigned short port, struct PHB *phb)
-{
-	struct sockaddr_in *sin;
-	int fd = -1;
-
-	if (!(sin = gaim_gethostbyname(host, port))) {
-		g_free(phb);
-		return -1;
-	}
-
-	if ((fd = socket(sin->sin_family, SOCK_STREAM, 0)) < 0) {
-		g_free(phb);
-		return -1;
-	}
-
-	sock_make_nonblocking(fd);
-	
-	event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port, fd);
-	
-	if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0) {
-		if (sockerr_again()) {
-			phb->inpa = b_input_add(fd, GAIM_INPUT_WRITE, gaim_io_connected, phb);
-			phb->fd = fd;
-		} else {
-			closesocket(fd);
-			g_free(phb);
-			return -1;
-		}
-	}
-
-	return fd;
-}
-
-
-/* Connecting to HTTP proxies */
-
-#define HTTP_GOODSTRING "HTTP/1.0 200 Connection established"
-#define HTTP_GOODSTRING2 "HTTP/1.1 200 Connection established"
-
-static gboolean http_canread(gpointer data, gint source, b_input_condition cond)
-{
-	int nlc = 0;
-	int pos = 0;
-	struct PHB *phb = data;
-	char inputline[8192];
-
-	b_event_remove(phb->inpa);
-
-	while ((pos < sizeof(inputline)-1) && (nlc != 2) && (read(source, &inputline[pos++], 1) == 1)) {
-		if (inputline[pos - 1] == '\n')
-			nlc++;
-		else if (inputline[pos - 1] != '\r')
-			nlc = 0;
-	}
-	inputline[pos] = '\0';
-
-	if ((memcmp(HTTP_GOODSTRING, inputline, strlen(HTTP_GOODSTRING)) == 0) ||
-	    (memcmp(HTTP_GOODSTRING2, inputline, strlen(HTTP_GOODSTRING2)) == 0)) {
-		phb->func(phb->data, source, GAIM_INPUT_READ);
-		g_free(phb->host);
-		g_free(phb);
-		return FALSE;
-	}
-
-	close(source);
-	phb->func(phb->data, -1, GAIM_INPUT_READ);
-	g_free(phb->host);
-	g_free(phb);
-	
-	return FALSE;
-}
-
-static gboolean http_canwrite(gpointer data, gint source, b_input_condition cond)
-{
-	char cmd[384];
-	struct PHB *phb = data;
-	unsigned int len;
-	int error = ETIMEDOUT;
-	if (phb->inpa > 0)
-		b_event_remove(phb->inpa);
-	len = sizeof(error);
-	if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
-		close(source);
-		phb->func(phb->data, -1, GAIM_INPUT_READ);
-		g_free(phb->host);
-		g_free(phb);
-		return FALSE;
-	}
-	sock_make_blocking(source);
-
-	g_snprintf(cmd, sizeof(cmd), "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", phb->host, phb->port,
-		   phb->host, phb->port);
-	if (send(source, cmd, strlen(cmd), 0) < 0) {
-		close(source);
-		phb->func(phb->data, -1, GAIM_INPUT_READ);
-		g_free(phb->host);
-		g_free(phb);
-		return FALSE;
-	}
-
-	if (proxyuser && *proxyuser) {
-		char *t1, *t2;
-		t1 = g_strdup_printf("%s:%s", proxyuser, proxypass);
-		t2 = tobase64(t1);
-		g_free(t1);
-		g_snprintf(cmd, sizeof(cmd), "Proxy-Authorization: Basic %s\r\n", t2);
-		g_free(t2);
-		if (send(source, cmd, strlen(cmd), 0) < 0) {
-			close(source);
-			phb->func(phb->data, -1, GAIM_INPUT_READ);
-			g_free(phb->host);
-			g_free(phb);
-			return FALSE;
-		}
-	}
-
-	g_snprintf(cmd, sizeof(cmd), "\r\n");
-	if (send(source, cmd, strlen(cmd), 0) < 0) {
-		close(source);
-		phb->func(phb->data, -1, GAIM_INPUT_READ);
-		g_free(phb->host);
-		g_free(phb);
-		return FALSE;
-	}
-
-	phb->inpa = b_input_add(source, GAIM_INPUT_READ, http_canread, phb);
-	
-	return FALSE;
-}
-
-static int proxy_connect_http(const char *host, unsigned short port, struct PHB *phb)
-{
-	phb->host = g_strdup(host);
-	phb->port = port;
-	phb->proxy_func = http_canwrite;
-	phb->proxy_data = phb;
-	
-	return( proxy_connect_none( proxyhost, proxyport, phb ) );
-}
-
-
-/* Connecting to SOCKS4 proxies */
-
-static gboolean s4_canread(gpointer data, gint source, b_input_condition cond)
-{
-	unsigned char packet[12];
-	struct PHB *phb = data;
-
-	b_event_remove(phb->inpa);
-
-	memset(packet, 0, sizeof(packet));
-	if (read(source, packet, 9) >= 4 && packet[1] == 90) {
-		phb->func(phb->data, source, GAIM_INPUT_READ);
-		g_free(phb->host);
-		g_free(phb);
-		return FALSE;
-	}
-
-	close(source);
-	phb->func(phb->data, -1, GAIM_INPUT_READ);
-	g_free(phb->host);
-	g_free(phb);
-	
-	return FALSE;
-}
-
-static gboolean s4_canwrite(gpointer data, gint source, b_input_condition cond)
-{
-	unsigned char packet[12];
-	struct hostent *hp;
-	struct PHB *phb = data;
-	unsigned int len;
-	int error = ETIMEDOUT;
-	if (phb->inpa > 0)
-		b_event_remove(phb->inpa);
-	len = sizeof(error);
-	if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
-		close(source);
-		phb->func(phb->data, -1, GAIM_INPUT_READ);
-		g_free(phb->host);
-		g_free(phb);
-		return FALSE;
-	}
-	sock_make_blocking(source);
-
-	/* XXX does socks4 not support host name lookups by the proxy? */
-	if (!(hp = gethostbyname(phb->host))) {
-		close(source);
-		phb->func(phb->data, -1, GAIM_INPUT_READ);
-		g_free(phb->host);
-		g_free(phb);
-		return FALSE;
-	}
-
-	packet[0] = 4;
-	packet[1] = 1;
-	packet[2] = phb->port >> 8;
-	packet[3] = phb->port & 0xff;
-	packet[4] = (unsigned char)(hp->h_addr_list[0])[0];
-	packet[5] = (unsigned char)(hp->h_addr_list[0])[1];
-	packet[6] = (unsigned char)(hp->h_addr_list[0])[2];
-	packet[7] = (unsigned char)(hp->h_addr_list[0])[3];
-	packet[8] = 0;
-	if (write(source, packet, 9) != 9) {
-		close(source);
-		phb->func(phb->data, -1, GAIM_INPUT_READ);
-		g_free(phb->host);
-		g_free(phb);
-		return FALSE;
-	}
-
-	phb->inpa = b_input_add(source, GAIM_INPUT_READ, s4_canread, phb);
-	
-	return FALSE;
-}
-
-static int proxy_connect_socks4(const char *host, unsigned short port, struct PHB *phb)
-{
-	phb->host = g_strdup(host);
-	phb->port = port;
-	phb->proxy_func = s4_canwrite;
-	phb->proxy_data = phb;
-	
-	return( proxy_connect_none( proxyhost, proxyport, phb ) );
-}
-
-
-/* Connecting to SOCKS5 proxies */
-
-static gboolean s5_canread_again(gpointer data, gint source, b_input_condition cond)
-{
-	unsigned char buf[512];
-	struct PHB *phb = data;
-
-	b_event_remove(phb->inpa);
-
-	if (read(source, buf, 10) < 10) {
-		close(source);
-		phb->func(phb->data, -1, GAIM_INPUT_READ);
-		g_free(phb->host);
-		g_free(phb);
-		return FALSE;
-	}
-	if ((buf[0] != 0x05) || (buf[1] != 0x00)) {
-		close(source);
-		phb->func(phb->data, -1, GAIM_INPUT_READ);
-		g_free(phb->host);
-		g_free(phb);
-		return FALSE;
-	}
-
-	phb->func(phb->data, source, GAIM_INPUT_READ);
-	g_free(phb->host);
-	g_free(phb);
-	
-	return FALSE;
-}
-
-static void s5_sendconnect(gpointer data, gint source)
-{
-	unsigned char buf[512];
-	struct PHB *phb = data;
-	int hlen = strlen(phb->host);
-	
-	buf[0] = 0x05;
-	buf[1] = 0x01;		/* CONNECT */
-	buf[2] = 0x00;		/* reserved */
-	buf[3] = 0x03;		/* address type -- host name */
-	buf[4] = hlen;
-	memcpy(buf + 5, phb->host, hlen);
-	buf[5 + strlen(phb->host)] = phb->port >> 8;
-	buf[5 + strlen(phb->host) + 1] = phb->port & 0xff;
-
-	if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) {
-		close(source);
-		phb->func(phb->data, -1, GAIM_INPUT_READ);
-		g_free(phb->host);
-		g_free(phb);
-		return;
-	}
-
-	phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_canread_again, phb);
-}
-
-static gboolean s5_readauth(gpointer data, gint source, b_input_condition cond)
-{
-	unsigned char buf[512];
-	struct PHB *phb = data;
-
-	b_event_remove(phb->inpa);
-
-	if (read(source, buf, 2) < 2) {
-		close(source);
-		phb->func(phb->data, -1, GAIM_INPUT_READ);
-		g_free(phb->host);
-		g_free(phb);
-		return FALSE;
-	}
-
-	if ((buf[0] != 0x01) || (buf[1] != 0x00)) {
-		close(source);
-		phb->func(phb->data, -1, GAIM_INPUT_READ);
-		g_free(phb->host);
-		g_free(phb);
-		return FALSE;
-	}
-
-	s5_sendconnect(phb, source);
-	
-	return FALSE;
-}
-
-static gboolean s5_canread(gpointer data, gint source, b_input_condition cond)
-{
-	unsigned char buf[512];
-	struct PHB *phb = data;
-
-	b_event_remove(phb->inpa);
-
-	if (read(source, buf, 2) < 2) {
-		close(source);
-		phb->func(phb->data, -1, GAIM_INPUT_READ);
-		g_free(phb->host);
-		g_free(phb);
-		return FALSE;
-	}
-
-	if ((buf[0] != 0x05) || (buf[1] == 0xff)) {
-		close(source);
-		phb->func(phb->data, -1, GAIM_INPUT_READ);
-		g_free(phb->host);
-		g_free(phb);
-		return FALSE;
-	}
-
-	if (buf[1] == 0x02) {
-		unsigned int i = strlen(proxyuser), j = strlen(proxypass);
-		buf[0] = 0x01;	/* version 1 */
-		buf[1] = i;
-		memcpy(buf + 2, proxyuser, i);
-		buf[2 + i] = j;
-		memcpy(buf + 2 + i + 1, proxypass, j);
-		if (write(source, buf, 3 + i + j) < 3 + i + j) {
-			close(source);
-			phb->func(phb->data, -1, GAIM_INPUT_READ);
-			g_free(phb->host);
-			g_free(phb);
-			return FALSE;
-		}
-
-		phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_readauth, phb);
-	} else {
-		s5_sendconnect(phb, source);
-	}
-	
-	return FALSE;
-}
-
-static gboolean s5_canwrite(gpointer data, gint source, b_input_condition cond)
-{
-	unsigned char buf[512];
-	int i;
-	struct PHB *phb = data;
-	unsigned int len;
-	int error = ETIMEDOUT;
-	if (phb->inpa > 0)
-		b_event_remove(phb->inpa);
-	len = sizeof(error);
-	if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
-		close(source);
-		phb->func(phb->data, -1, GAIM_INPUT_READ);
-		g_free(phb->host);
-		g_free(phb);
-		return FALSE;
-	}
-	sock_make_blocking(source);
-
-	i = 0;
-	buf[0] = 0x05;		/* SOCKS version 5 */
-	if (proxyuser[0]) {
-		buf[1] = 0x02;	/* two methods */
-		buf[2] = 0x00;	/* no authentication */
-		buf[3] = 0x02;	/* username/password authentication */
-		i = 4;
-	} else {
-		buf[1] = 0x01;
-		buf[2] = 0x00;
-		i = 3;
-	}
-
-	if (write(source, buf, i) < i) {
-		close(source);
-		phb->func(phb->data, -1, GAIM_INPUT_READ);
-		g_free(phb->host);
-		g_free(phb);
-		return FALSE;
-	}
-
-	phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_canread, phb);
-	
-	return FALSE;
-}
-
-static int proxy_connect_socks5(const char *host, unsigned short port, struct PHB *phb)
-{
-	phb->host = g_strdup(host);
-	phb->port = port;
-	phb->proxy_func = s5_canwrite;
-	phb->proxy_data = phb;
-	
-	return( proxy_connect_none( proxyhost, proxyport, phb ) );
-}
-
-
-/* Export functions */
-
-int proxy_connect(const char *host, int port, b_event_handler func, gpointer data)
-{
-	struct PHB *phb;
-	
-	if (!host || !port || (port == -1) || !func || strlen(host) > 128) {
-		return -1;
-	}
-	
-	phb = g_new0(struct PHB, 1);
-	phb->func = func;
-	phb->data = data;
-	
-#ifndef _WIN32
-	sethostent(1);
-#endif
-	
-	if ((proxytype == PROXY_NONE) || !proxyhost || !proxyhost[0] || !proxyport || (proxyport == -1))
-		return proxy_connect_none(host, port, phb);
-	else if (proxytype == PROXY_HTTP)
-		return proxy_connect_http(host, port, phb);
-	else if (proxytype == PROXY_SOCKS4)
-		return proxy_connect_socks4(host, port, phb);
-	else if (proxytype == PROXY_SOCKS5)
-		return proxy_connect_socks5(host, port, phb);
-	
-	if (phb->host) g_free(phb);
-	g_free(phb);
-	return -1;
-}
Index: otocols/proxy.h
===================================================================
--- protocols/proxy.h	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,53 +1,0 @@
-/*
- * nogaim
- *
- * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-/* this is the export part of the proxy.c file. it does a little
-   prototype-ing stuff and redefine some net function to mask them
-   with some kind of transparent layer */ 
-
-#ifndef _PROXY_H_
-#define _PROXY_H_
-
-#include <sys/types.h>
-#ifndef _WIN32
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#endif
-#include <glib.h>
-#include <gmodule.h>
-
-#include "events.h"
-
-#define PROXY_NONE 0
-#define PROXY_HTTP 1
-#define PROXY_SOCKS4 2
-#define PROXY_SOCKS5 3
-
-extern char proxyhost[128];
-extern int  proxyport;
-extern int  proxytype;
-extern char proxyuser[128];
-extern char proxypass[128];
-
-G_MODULE_EXPORT int proxy_connect(const char *host, int port, b_event_handler func, gpointer data);
-
-#endif /* _PROXY_H_ */
Index: otocols/sha.c
===================================================================
--- protocols/sha.c	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,173 +1,0 @@
-/* 
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is SHA 180-1 Reference Implementation (Compact version)
- * 
- * The Initial Developer of the Original Code is Paul Kocher of
- * Cryptography Research.  Portions created by Paul Kocher are 
- * Copyright (C) 1995-9 by Cryptography Research, Inc.  All
- * Rights Reserved.
- * 
- * Contributor(s):
- *
- */
-
-#define BITLBEE_CORE
-#include "nogaim.h"
-
-static void shaHashBlock(SHA_CTX *ctx);
-
-void shaInit(SHA_CTX *ctx) {
-  int i;
-
-  ctx->lenW = 0;
-  ctx->sizeHi = ctx->sizeLo = 0;
-
-  /* Initialize H with the magic constants (see FIPS180 for constants)
-   */
-  ctx->H[0] = 0x67452301L;
-  ctx->H[1] = 0xefcdab89L;
-  ctx->H[2] = 0x98badcfeL;
-  ctx->H[3] = 0x10325476L;
-  ctx->H[4] = 0xc3d2e1f0L;
-
-  for (i = 0; i < 80; i++)
-    ctx->W[i] = 0;
-}
-
-
-void shaUpdate(SHA_CTX *ctx, unsigned char *dataIn, int len) {
-  int i;
-
-  /* Read the data into W and process blocks as they get full
-   */
-  for (i = 0; i < len; i++) {
-    ctx->W[ctx->lenW / 4] <<= 8;
-    ctx->W[ctx->lenW / 4] |= (guint32)dataIn[i];
-    if ((++ctx->lenW) % 64 == 0) {
-      shaHashBlock(ctx);
-      ctx->lenW = 0;
-    }
-    ctx->sizeLo += 8;
-    ctx->sizeHi += (ctx->sizeLo < 8);
-  }
-}
-
-
-void shaFinal(SHA_CTX *ctx, unsigned char hashout[20]) {
-  unsigned char pad0x80 = 0x80;
-  unsigned char pad0x00 = 0x00;
-  unsigned char padlen[8];
-  int i;
-
-  /* Pad with a binary 1 (e.g. 0x80), then zeroes, then length
-   */
-  padlen[0] = (unsigned char)((ctx->sizeHi >> 24) & 255);
-  padlen[1] = (unsigned char)((ctx->sizeHi >> 16) & 255);
-  padlen[2] = (unsigned char)((ctx->sizeHi >> 8) & 255);
-  padlen[3] = (unsigned char)((ctx->sizeHi >> 0) & 255);
-  padlen[4] = (unsigned char)((ctx->sizeLo >> 24) & 255);
-  padlen[5] = (unsigned char)((ctx->sizeLo >> 16) & 255);
-  padlen[6] = (unsigned char)((ctx->sizeLo >> 8) & 255);
-  padlen[7] = (unsigned char)((ctx->sizeLo >> 0) & 255);
-  shaUpdate(ctx, &pad0x80, 1);
-  while (ctx->lenW != 56)
-    shaUpdate(ctx, &pad0x00, 1);
-  shaUpdate(ctx, padlen, 8);
-
-  /* Output hash
-   */
-  for (i = 0; i < 20; i++) {
-    hashout[i] = (unsigned char)(ctx->H[i / 4] >> 24);
-    ctx->H[i / 4] <<= 8;
-  }
-
-  /*
-   *  Re-initialize the context (also zeroizes contents)
-   */
-  shaInit(ctx); 
-}
-
-
-void shaBlock(unsigned char *dataIn, int len, unsigned char hashout[20]) {
-  SHA_CTX ctx;
-
-  shaInit(&ctx);
-  shaUpdate(&ctx, dataIn, len);
-  shaFinal(&ctx, hashout);
-}
-
-
-#define SHA_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xffffffffL)
-
-static void shaHashBlock(SHA_CTX *ctx) {
-  int t;
-  guint32 A,B,C,D,E,TEMP;
-
-  for (t = 16; t <= 79; t++)
-    ctx->W[t] =
-      SHA_ROTL(ctx->W[t-3] ^ ctx->W[t-8] ^ ctx->W[t-14] ^ ctx->W[t-16], 1);
-
-  A = ctx->H[0];
-  B = ctx->H[1];
-  C = ctx->H[2];
-  D = ctx->H[3];
-  E = ctx->H[4];
-
-  for (t = 0; t <= 19; t++) {
-    TEMP = (SHA_ROTL(A,5) + (((C^D)&B)^D)     + E + ctx->W[t] + 0x5a827999L) & 0xffffffffL;
-    E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
-  }
-  for (t = 20; t <= 39; t++) {
-    TEMP = (SHA_ROTL(A,5) + (B^C^D)           + E + ctx->W[t] + 0x6ed9eba1L) & 0xffffffffL;
-    E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
-  }
-  for (t = 40; t <= 59; t++) {
-    TEMP = (SHA_ROTL(A,5) + ((B&C)|(D&(B|C))) + E + ctx->W[t] + 0x8f1bbcdcL) & 0xffffffffL;
-    E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
-  }
-  for (t = 60; t <= 79; t++) {
-    TEMP = (SHA_ROTL(A,5) + (B^C^D)           + E + ctx->W[t] + 0xca62c1d6L) & 0xffffffffL;
-    E = D; D = C; C = SHA_ROTL(B, 30); B = A; A = TEMP;
-  }
-
-  ctx->H[0] += A;
-  ctx->H[1] += B;
-  ctx->H[2] += C;
-  ctx->H[3] += D;
-  ctx->H[4] += E;
-}
-
-/*----------------------------------------------------------------------------
- *
- * This code added by Thomas "temas" Muldowney for Jabber compatability
- *
- *---------------------------------------------------------------------------*/
-char *shahash(char *str)
-{
-    static char final[41];
-    char *pos;
-    unsigned char hashval[20];
-    int x;
-
-    if(!str || strlen(str) == 0)
-        return NULL;
-
-    shaBlock((unsigned char *)str, strlen(str), hashval);
-
-    pos = final;
-    for(x=0;x<20;x++)
-    {
-        g_snprintf(pos, 3, "%02x", hashval[x]);
-        pos += 2;
-    }
-    return (char *)final;
-}
Index: otocols/sha.h
===================================================================
--- protocols/sha.h	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,21 +1,0 @@
-#ifndef __SHA_H__
-#define __SHA_H__
-
-#include <gmodule.h>
-
-G_MODULE_EXPORT int strprintsha(char *dest, int *hashval);
- 
-typedef struct {
-  guint32 H[5];
-  guint32 W[80];
-  int lenW;
-  guint32 sizeHi,sizeLo;
-} SHA_CTX;
- 
-G_MODULE_EXPORT void shaInit(SHA_CTX *ctx);
-G_MODULE_EXPORT void shaUpdate(SHA_CTX *ctx, unsigned char *dataIn, int len);
-G_MODULE_EXPORT void shaFinal(SHA_CTX *ctx, unsigned char hashout[20]);
-G_MODULE_EXPORT void shaBlock(unsigned char *dataIn, int len, unsigned char hashout[20]);
-G_MODULE_EXPORT char *shahash(char *str);
-
-#endif
Index: otocols/ssl_bogus.c
===================================================================
--- protocols/ssl_bogus.c	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,57 +1,0 @@
-  /********************************************************************\
-  * BitlBee -- An IRC to other IM-networks gateway                     *
-  *                                                                    *
-  * Copyright 2002-2004 Wilmer van der Gaast and others                *
-  \********************************************************************/
-
-/* SSL module - dummy version                                           */
-
-/*
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program 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 General Public License for more details.
-
-  You should have received a copy of the GNU General Public License with
-  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
-  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
-  Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include "ssl_client.h"
-
-int ssl_errno;
-
-void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
-{
-	return( NULL );
-}
-
-int ssl_read( void *conn, char *buf, int len )
-{
-	return( -1 );
-}
-
-int ssl_write( void *conn, const char *buf, int len )
-{
-	return( -1 );
-}
-
-void ssl_disconnect( void *conn_ )
-{
-}
-
-int ssl_getfd( void *conn )
-{
-	return( -1 );
-}
-
-b_input_condition ssl_getdirection( void *conn )
-{
-	return GAIM_INPUT_READ;
-}
Index: otocols/ssl_client.h
===================================================================
--- protocols/ssl_client.h	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,42 +1,0 @@
-  /********************************************************************\
-  * BitlBee -- An IRC to other IM-networks gateway                     *
-  *                                                                    *
-  * Copyright 2002-2004 Wilmer van der Gaast and others                *
-  \********************************************************************/
-
-/* SSL module                                                           */
-
-/*
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program 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 General Public License for more details.
-
-  You should have received a copy of the GNU General Public License with
-  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
-  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
-  Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <glib.h>
-#include "proxy.h"
-
-#define SSL_OK            0
-#define SSL_NOHANDSHAKE   1
-#define SSL_AGAIN         2
-
-extern int ssl_errno;
-
-typedef gboolean (*ssl_input_function)(gpointer, void*, b_input_condition);
-
-G_MODULE_EXPORT void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data );
-G_MODULE_EXPORT int ssl_read( void *conn, char *buf, int len );
-G_MODULE_EXPORT int ssl_write( void *conn, const char *buf, int len );
-G_MODULE_EXPORT void ssl_disconnect( void *conn_ );
-G_MODULE_EXPORT int ssl_getfd( void *conn );
-G_MODULE_EXPORT b_input_condition ssl_getdirection( void *conn );
Index: otocols/ssl_gnutls.c
===================================================================
--- protocols/ssl_gnutls.c	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,206 +1,0 @@
-  /********************************************************************\
-  * BitlBee -- An IRC to other IM-networks gateway                     *
-  *                                                                    *
-  * Copyright 2002-2004 Wilmer van der Gaast and others                *
-  \********************************************************************/
-
-/* SSL module - GnuTLS version                                          */
-
-/*
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program 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 General Public License for more details.
-
-  You should have received a copy of the GNU General Public License with
-  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
-  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
-  Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <gnutls/gnutls.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include "proxy.h"
-#include "ssl_client.h"
-#include "sock.h"
-#include "stdlib.h"
-
-int ssl_errno = 0;
-
-static gboolean initialized = FALSE;
-
-struct scd
-{
-	ssl_input_function func;
-	gpointer data;
-	int fd;
-	gboolean established;
-	int inpa;
-	
-	gnutls_session session;
-	gnutls_certificate_credentials xcred;
-};
-
-static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond );
-
-
-void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
-{
-	struct scd *conn = g_new0( struct scd, 1 );
-	
-	conn->fd = proxy_connect( host, port, ssl_connected, conn );
-	conn->func = func;
-	conn->data = data;
-	conn->inpa = -1;
-	
-	if( conn->fd < 0 )
-	{
-		g_free( conn );
-		return( NULL );
-	}
-	
-	if( !initialized )
-	{
-		gnutls_global_init();
-		initialized = TRUE;
-		atexit( gnutls_global_deinit );
-	}
-	
-	gnutls_certificate_allocate_credentials( &conn->xcred );
-	gnutls_init( &conn->session, GNUTLS_CLIENT );
-	gnutls_set_default_priority( conn->session );
-	gnutls_credentials_set( conn->session, GNUTLS_CRD_CERTIFICATE, conn->xcred );
-	
-	return( conn );
-}
-
-static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond );
-
-static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond )
-{
-	struct scd *conn = data;
-	
-	if( source == -1 )
-	{
-		conn->func( conn->data, NULL, cond );
-		
-		gnutls_deinit( conn->session );
-		gnutls_certificate_free_credentials( conn->xcred );
-		
-		g_free( conn );
-		
-		return FALSE;
-	}
-	
-	sock_make_nonblocking( conn->fd );
-	gnutls_transport_set_ptr( conn->session, (gnutls_transport_ptr) conn->fd );
-	
-	return ssl_handshake( data, source, cond );
-}
-
-static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond )
-{
-	struct scd *conn = data;
-	int st;
-	
-	if( ( st = gnutls_handshake( conn->session ) ) < 0 )
-	{
-		if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED )
-		{
-			conn->inpa = b_input_add( conn->fd, ssl_getdirection( conn ),
-			                          ssl_handshake, data );
-		}
-		else
-		{
-			conn->func( conn->data, NULL, cond );
-			
-			gnutls_deinit( conn->session );
-			gnutls_certificate_free_credentials( conn->xcred );
-			closesocket( conn->fd );
-			
-			g_free( conn );
-		}
-	}
-	else
-	{
-		/* For now we can't handle non-blocking perfectly everywhere... */
-		sock_make_blocking( conn->fd );
-		
-		conn->established = TRUE;
-		conn->func( conn->data, conn, cond );
-	}
-	
-	return FALSE;
-}
-
-int ssl_read( void *conn, char *buf, int len )
-{
-	int st;
-	
-	if( !((struct scd*)conn)->established )
-	{
-		ssl_errno = SSL_NOHANDSHAKE;
-		return( -1 );
-	}
-	
-	st = gnutls_record_recv( ((struct scd*)conn)->session, buf, len );
-	
-	ssl_errno = SSL_OK;
-	if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED )
-		ssl_errno = SSL_AGAIN;
-	
-	return st;
-}
-
-int ssl_write( void *conn, const char *buf, int len )
-{
-	int st;
-	
-	if( !((struct scd*)conn)->established )
-	{
-		ssl_errno = SSL_NOHANDSHAKE;
-		return( -1 );
-	}
-	
-	st = gnutls_record_send( ((struct scd*)conn)->session, buf, len );
-	
-	ssl_errno = SSL_OK;
-	if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED )
-		ssl_errno = SSL_AGAIN;
-	
-	return st;
-}
-
-void ssl_disconnect( void *conn_ )
-{
-	struct scd *conn = conn_;
-	
-	if( conn->inpa != -1 )
-		b_event_remove( conn->inpa );
-	
-	if( conn->established )
-		gnutls_bye( conn->session, GNUTLS_SHUT_WR );
-	
-	closesocket( conn->fd );
-	
-	gnutls_deinit( conn->session );
-	gnutls_certificate_free_credentials( conn->xcred );
-	g_free( conn );
-}
-
-int ssl_getfd( void *conn )
-{
-	return( ((struct scd*)conn)->fd );
-}
-
-b_input_condition ssl_getdirection( void *conn )
-{
-	return( gnutls_record_get_direction( ((struct scd*)conn)->session ) ?
-	        GAIM_INPUT_WRITE : GAIM_INPUT_READ );
-}
Index: otocols/ssl_nss.c
===================================================================
--- protocols/ssl_nss.c	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,190 +1,0 @@
-  /********************************************************************\
-  * BitlBee -- An IRC to other IM-networks gateway                     *
-  *                                                                    *
-  * Copyright 2002-2005 Wilmer van der Gaast and others                *
-  \********************************************************************/
-
-/* SSL module - NSS version                                             */
-
-/* Copyright 2005 Jelmer Vernooij                                       */
-
-/*
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program 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 General Public License for more details.
-
-  You should have received a copy of the GNU General Public License with
-  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
-  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
-  Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include "bitlbee.h"
-#include "proxy.h"
-#include "ssl_client.h"
-#include "sock.h"
-#include <nspr.h>
-#include <prio.h>
-#include <sslproto.h>
-#include <nss.h>
-#include <private/pprio.h>
-#include <ssl.h>
-#include <secerr.h>
-#include <sslerr.h>
-
-int ssl_errno = 0;
-
-static gboolean initialized = FALSE;
-
-struct scd
-{
-	ssl_input_function func;
-	gpointer data;
-	int fd;
-	PRFileDesc *prfd;
-	gboolean established;
-};
-
-static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond );
-
-
-static SECStatus nss_auth_cert (void *arg, PRFileDesc *socket, PRBool checksig, PRBool isserver)
-{
-	return SECSuccess;
-}
-
-static SECStatus nss_bad_cert (void *arg, PRFileDesc *socket) 
-{
-	PRErrorCode err;
-
-	if(!arg) return SECFailure;
-
-	*(PRErrorCode *)arg = err = PORT_GetError();
-
-	switch(err) {
-	case SEC_ERROR_INVALID_AVA:
-	case SEC_ERROR_INVALID_TIME:
-	case SEC_ERROR_BAD_SIGNATURE:
-	case SEC_ERROR_EXPIRED_CERTIFICATE:
-	case SEC_ERROR_UNKNOWN_ISSUER:
-	case SEC_ERROR_UNTRUSTED_CERT:
-	case SEC_ERROR_CERT_VALID:
-	case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
-	case SEC_ERROR_CRL_EXPIRED:
-	case SEC_ERROR_CRL_BAD_SIGNATURE:
-	case SEC_ERROR_EXTENSION_VALUE_INVALID:
-	case SEC_ERROR_CA_CERT_INVALID:
-	case SEC_ERROR_CERT_USAGES_INVALID:
-	case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION:
-		return SECSuccess;
-
-	default:
-		return SECFailure;
-	}
-}
-
-
-void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
-{
-	struct scd *conn = g_new0( struct scd, 1 );
-	
-	conn->fd = proxy_connect( host, port, ssl_connected, conn );
-	conn->func = func;
-	conn->data = data;
-	
-	if( conn->fd < 0 )
-	{
-		g_free( conn );
-		return( NULL );
-	}
-	
-	if( !initialized )
-	{
-		PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
-		NSS_NoDB_Init(NULL);
-		NSS_SetDomesticPolicy();
-	}
-
-	
-	return( conn );
-}
-
-static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond )
-{
-	struct scd *conn = data;
-	
-	if( source == -1 )
-		goto ssl_connected_failure;
-	
-	/* Until we find out how to handle non-blocking I/O with NSS... */
-	sock_make_blocking( conn->fd );
-	
-	conn->prfd = SSL_ImportFD(NULL, PR_ImportTCPSocket(source));
-	SSL_OptionSet(conn->prfd, SSL_SECURITY, PR_TRUE);
-	SSL_OptionSet(conn->prfd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
-	SSL_BadCertHook(conn->prfd, (SSLBadCertHandler)nss_bad_cert, NULL);
-	SSL_AuthCertificateHook(conn->prfd, (SSLAuthCertificate)nss_auth_cert, (void *)CERT_GetDefaultCertDB());
-	SSL_ResetHandshake(conn->prfd, PR_FALSE);
-
-	if (SSL_ForceHandshake(conn->prfd)) {
-		goto ssl_connected_failure;
-	}
-	
-	
-	conn->established = TRUE;
-	conn->func( conn->data, conn, cond );
-	return FALSE;
-	
-	ssl_connected_failure:
-	
-	conn->func( conn->data, NULL, cond );
-	
-	PR_Close( conn -> prfd );
-	if( source >= 0 ) closesocket( source );
-	g_free( conn );
-	
-	return FALSE;
-}
-
-int ssl_read( void *conn, char *buf, int len )
-{
-	if( !((struct scd*)conn)->established )
-		return( 0 );
-	
-	return( PR_Read( ((struct scd*)conn)->prfd, buf, len ) );
-}
-
-int ssl_write( void *conn, const char *buf, int len )
-{
-	if( !((struct scd*)conn)->established )
-		return( 0 );
-	
-	return( PR_Write ( ((struct scd*)conn)->prfd, buf, len ) );
-}
-
-void ssl_disconnect( void *conn_ )
-{
-	struct scd *conn = conn_;
-	
-	PR_Close( conn->prfd );
-	closesocket( conn->fd );
-	
-	g_free( conn );
-}
-
-int ssl_getfd( void *conn )
-{
-	return( ((struct scd*)conn)->fd );
-}
-
-b_input_condition ssl_getdirection( void *conn )
-{
-	/* Just in case someone calls us, let's return the most likely case: */
-	return GAIM_INPUT_READ;
-}
Index: otocols/ssl_openssl.c
===================================================================
--- protocols/ssl_openssl.c	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,221 +1,0 @@
-  /********************************************************************\
-  * BitlBee -- An IRC to other IM-networks gateway                     *
-  *                                                                    *
-  * Copyright 2002-2004 Wilmer van der Gaast and others                *
-  \********************************************************************/
-
-/* SSL module - OpenSSL version                                         */
-
-/*
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program 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 General Public License for more details.
-
-  You should have received a copy of the GNU General Public License with
-  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
-  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
-  Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <openssl/crypto.h>
-#include <openssl/rand.h>
-#include <openssl/x509.h>
-#include <openssl/pem.h>
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-
-#include "proxy.h"
-#include "ssl_client.h"
-#include "sock.h"
-
-int ssl_errno = 0;
-
-static gboolean initialized = FALSE;
-
-struct scd
-{
-	ssl_input_function func;
-	gpointer data;
-	int fd;
-	gboolean established;
-	
-	int inpa;
-	int lasterr;		/* Necessary for SSL_get_error */
-	SSL *ssl;
-	SSL_CTX *ssl_ctx;
-};
-
-static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond );
-
-
-void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
-{
-	struct scd *conn = g_new0( struct scd, 1 );
-	SSL_METHOD *meth;
-	
-	conn->fd = proxy_connect( host, port, ssl_connected, conn );
-	conn->func = func;
-	conn->data = data;
-	
-	if( conn->fd < 0 )
-	{
-		g_free( conn );
-		return( NULL );
-	}
-	
-	if( !initialized )
-	{
-		initialized = TRUE;
-		SSLeay_add_ssl_algorithms();
-	}
-	
-	meth = TLSv1_client_method();
-	conn->ssl_ctx = SSL_CTX_new( meth );
-	if( conn->ssl_ctx == NULL )
-	{
-		conn->fd = -1;
-		return( NULL );
-	}
-	
-	conn->ssl = SSL_new( conn->ssl_ctx );
-	if( conn->ssl == NULL )
-	{
-		conn->fd = -1;
-		return( NULL );
-	}
-	
-	return( conn );
-}
-
-static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond );
-
-static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond )
-{
-	struct scd *conn = data;
-	
-	if( source == -1 )
-		return ssl_handshake( data, -1, cond );
-	
-	/* We can do at least the handshake with non-blocking I/O */
-	sock_make_nonblocking( conn->fd );
-	SSL_set_fd( conn->ssl, conn->fd );
-	
-	return ssl_handshake( data, source, cond );
-}	
-
-static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond )
-{
-	struct scd *conn = data;
-	int st;
-	
-	if( ( st = SSL_connect( conn->ssl ) ) < 0 )
-	{
-		conn->lasterr = SSL_get_error( conn->ssl, st );
-		if( conn->lasterr != SSL_ERROR_WANT_READ && conn->lasterr != SSL_ERROR_WANT_WRITE )
-			goto ssl_connected_failure;
-		
-		conn->inpa = b_input_add( conn->fd, ssl_getdirection( conn ), ssl_handshake, data );
-		return FALSE;
-	}
-	
-	conn->established = TRUE;
-	sock_make_blocking( conn->fd );		/* For now... */
-	conn->func( conn->data, conn, cond );
-	return FALSE;
-	
-ssl_connected_failure:
-	conn->func( conn->data, NULL, cond );
-	
-	if( conn->ssl )
-	{
-		SSL_shutdown( conn->ssl );
-		SSL_free( conn->ssl );
-	}
-	if( conn->ssl_ctx )
-	{
-		SSL_CTX_free( conn->ssl_ctx );
-	}
-	if( source >= 0 ) closesocket( source );
-	g_free( conn );
-	
-	return FALSE;
-}
-
-int ssl_read( void *conn, char *buf, int len )
-{
-	int st;
-	
-	if( !((struct scd*)conn)->established )
-	{
-		ssl_errno = SSL_NOHANDSHAKE;
-		return -1;
-	}
-	
-	st = SSL_read( ((struct scd*)conn)->ssl, buf, len );
-	
-	ssl_errno = SSL_OK;
-	if( st <= 0 )
-	{
-		((struct scd*)conn)->lasterr = SSL_get_error( ((struct scd*)conn)->ssl, st );
-		if( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_READ || ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE )
-			ssl_errno = SSL_AGAIN;
-	}
-	
-	return st;
-}
-
-int ssl_write( void *conn, const char *buf, int len )
-{
-	int st;
-	
-	if( !((struct scd*)conn)->established )
-	{
-		ssl_errno = SSL_NOHANDSHAKE;
-		return -1;
-	}
-	
-	st = SSL_write( ((struct scd*)conn)->ssl, buf, len );
-	
-	ssl_errno = SSL_OK;
-	if( st <= 0 )
-	{
-		((struct scd*)conn)->lasterr = SSL_get_error( ((struct scd*)conn)->ssl, st );
-		if( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_READ || ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE )
-			ssl_errno = SSL_AGAIN;
-	}
-	
-	return st;
-}
-
-void ssl_disconnect( void *conn_ )
-{
-	struct scd *conn = conn_;
-	
-	if( conn->inpa != -1 )
-		b_event_remove( conn->inpa );
-	
-	if( conn->established )
-		SSL_shutdown( conn->ssl );
-	
-	closesocket( conn->fd );
-	
-	SSL_free( conn->ssl );
-	SSL_CTX_free( conn->ssl_ctx );
-	g_free( conn );
-}
-
-int ssl_getfd( void *conn )
-{
-	return( ((struct scd*)conn)->fd );
-}
-
-b_input_condition ssl_getdirection( void *conn )
-{
-	return( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ? GAIM_INPUT_WRITE : GAIM_INPUT_READ );
-}
Index: l.c
===================================================================
--- url.c	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,107 +1,0 @@
-  /********************************************************************\
-  * BitlBee -- An IRC to other IM-networks gateway                     *
-  *                                                                    *
-  * Copyright 2001-2005 Wilmer van der Gaast and others                *
-  \********************************************************************/
-
-/* URL/mirror stuff - Stolen from Axel                                  */
-
-/*
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program 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 General Public License for more details.
-
-  You should have received a copy of the GNU General Public License with
-  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
-  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
-  Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include "url.h"
-
-/* Convert an URL to a url_t structure					*/
-int url_set( url_t *url, char *set_url )
-{
-	char s[MAX_STRING];
-	char *i;
-	
-	/* protocol://							*/
-	if( ( i = strstr( set_url, "://" ) ) == NULL )
-	{
-		url->proto = PROTO_DEFAULT;
-		strncpy( s, set_url, MAX_STRING );
-	}
-	else
-	{
-		if( g_strncasecmp( set_url, "http", i - set_url ) == 0 )
-			url->proto = PROTO_HTTP;
-		else if( g_strncasecmp( set_url, "https", i - set_url ) == 0 )
-			url->proto = PROTO_HTTPS;
-		else if( g_strncasecmp( set_url, "socks4", i - set_url ) == 0 )
-			url->proto = PROTO_SOCKS4;
-		else if( g_strncasecmp( set_url, "socks5", i - set_url ) == 0 )
-			url->proto = PROTO_SOCKS5;
-		else
-		{
-			return( 0 );
-		}
-		strncpy( s, i + 3, MAX_STRING );
-	}
-	
-	/* Split							*/
-	if( ( i = strchr( s, '/' ) ) == NULL )
-	{
-		strcpy( url->file, "/" );
-	}
-	else
-	{
-		strncpy( url->file, i, MAX_STRING );
-		*i = 0;
-	}
-	strncpy( url->host, s, MAX_STRING );
-	
-	/* Check for username in host field				*/
-	if( strrchr( url->host, '@' ) != NULL )
-	{
-		strncpy( url->user, url->host, MAX_STRING );
-		i = strrchr( url->user, '@' );
-		*i = 0;
-		strcpy( url->host, i + 1 );
-		*url->pass = 0;
-	}
-	/* If not: Fill in defaults					*/
-	else
-	{
-		*url->user = *url->pass = 0;
-	}
-	
-	/* Password?							*/
-	if( ( i = strchr( url->user, ':' ) ) != NULL )
-	{
-		*i = 0;
-		strcpy( url->pass, i + 1 );
-	}
-	/* Port number?							*/
-	if( ( i = strchr( url->host, ':' ) ) != NULL )
-	{
-		*i = 0;
-		sscanf( i + 1, "%d", &url->port );
-	}
-	else
-	{
-		if( url->proto == PROTO_HTTP )
-			url->port = 80;
-		else if( url->proto == PROTO_HTTPS )
-			url->port = 443;
-		else if( url->proto == PROTO_SOCKS4 || url->proto == PROTO_SOCKS4 )
-			url->port = 1080;
-	}
-	
-	return( url->port > 0 );
-}
Index: l.h
===================================================================
--- url.h	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,44 +1,0 @@
-  /********************************************************************\
-  * BitlBee -- An IRC to other IM-networks gateway                     *
-  *                                                                    *
-  * Copyright 2001-2004 Wilmer van der Gaast and others                *
-  \********************************************************************/
-
-/* URL/mirror stuff - Stolen from Axel                                  */
-
-/*
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program 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 General Public License for more details.
-
-  You should have received a copy of the GNU General Public License with
-  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
-  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
-  Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include "bitlbee.h"
-
-#define PROTO_HTTP		2
-#define PROTO_HTTPS		5
-#define PROTO_SOCKS4	3
-#define PROTO_SOCKS5	4
-#define PROTO_DEFAULT	PROTO_HTTP
-
-typedef struct url
-{
-	int proto;
-	int port;
-	char host[MAX_STRING];
-	char file[MAX_STRING];
-	char user[MAX_STRING];
-	char pass[MAX_STRING];
-} url_t;
-
-int url_set( url_t *url, char *set_url );
Index: il.c
===================================================================
--- util.c	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,481 +1,0 @@
-  /********************************************************************\
-  * BitlBee -- An IRC to other IM-networks gateway                     *
-  *                                                                    *
-  * Copyright 2002-2004 Wilmer van der Gaast and others                *
-  \********************************************************************/
-
-/*
- * Various utility functions. Some are copied from Gaim to support the
- * IM-modules, most are from BitlBee.
- *
- * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
- *                          (and possibly other members of the Gaim team)
- * Copyright 2002-2005 Wilmer van der Gaast <wilmer@gaast.net>
- */
-
-/*
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program 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 General Public License for more details.
-
-  You should have received a copy of the GNU General Public License with
-  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
-  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
-  Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#define BITLBEE_CORE
-#include "nogaim.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <glib.h>
-#include <time.h>
-
-void strip_linefeed(gchar *text)
-{
-	int i, j;
-	gchar *text2 = g_malloc(strlen(text) + 1);
-
-	for (i = 0, j = 0; text[i]; i++)
-		if (text[i] != '\r')
-			text2[j++] = text[i];
-	text2[j] = '\0';
-
-	strcpy(text, text2);
-	g_free(text2);
-}
-
-char *add_cr(char *text)
-{
-	char *ret = NULL;
-	int count = 0, j;
-	unsigned int i;
-
-	if (text[0] == '\n')
-		count++;
-	for (i = 1; i < strlen(text); i++)
-		if (text[i] == '\n' && text[i - 1] != '\r')
-			count++;
-
-	if (count == 0)
-		return g_strdup(text);
-
-	ret = g_malloc0(strlen(text) + count + 1);
-
-	i = 0; j = 0;
-	if (text[i] == '\n')
-		ret[j++] = '\r';
-	ret[j++] = text[i++];
-	for (; i < strlen(text); i++) {
-		if (text[i] == '\n' && text[i - 1] != '\r')
-			ret[j++] = '\r';
-		ret[j++] = text[i];
-	}
-
-	return ret;
-}
-
-char *tobase64(const char *text)
-{
-	char *out;
-	int len;
-	
-	len = strlen(text);
-	out = g_malloc((len + 2)    /* the == padding */
-	                    / 3     /* every 3-byte block */
-	                    * 4     /* becomes a 4-byte one */
-	                    + 1);   /* and of course, ASCIIZ! */
-	
-	base64_encode_real(text, len, out, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=");
-	
-	return out;
-}
-
-void base64_encode_real(const unsigned char *in, int inlen, unsigned char *out, char *b64digits)
-{
-	for (; inlen >= 3; inlen -= 3)
-	{
-		*out++ = b64digits[in[0] >> 2];
-		*out++ = b64digits[((in[0]<<4) & 0x30) | (in[1]>>4)];
-		*out++ = b64digits[((in[1]<<2) & 0x3c) | (in[2]>>6)];
-		*out++ = b64digits[in[2] & 0x3f];
-		in += 3;
-	}
-	if (inlen > 0)
-	{
-		*out++ = b64digits[in[0] >> 2];
-		if (inlen > 1)
-		{
-			*out++ = b64digits[((in[0]<<4) & 0x30) | (in[1]>>4)];
-			*out++ = b64digits[((in[1]<<2) & 0x3c)];
-		}
-		else
-		{
-			*out++ = b64digits[((in[0]<<4) & 0x30) | (in[1]>>4)];
-			*out++ = b64digits[64];
-		}
-		*out++ = b64digits[64];
-	}
-	*out = '\0';
-}
-
-char *normalize(const char *s)
-{
-	static char buf[BUF_LEN];
-	char *t, *u;
-	int x = 0;
-
-	g_return_val_if_fail((s != NULL), NULL);
-
-	u = t = g_strdup(s);
-
-	strcpy(t, s);
-	g_strdown(t);
-
-	while (*t && (x < BUF_LEN - 1)) {
-		if (*t != ' ') {
-			buf[x] = *t;
-			x++;
-		}
-		t++;
-	}
-	buf[x] = '\0';
-	g_free(u);
-	return buf;
-}
-
-time_t get_time(int year, int month, int day, int hour, int min, int sec)
-{
-	struct tm tm;
-
-	tm.tm_year = year - 1900;
-	tm.tm_mon = month - 1;
-	tm.tm_mday = day;
-	tm.tm_hour = hour;
-	tm.tm_min = min;
-	tm.tm_sec = sec >= 0 ? sec : time(NULL) % 60;
-	return mktime(&tm);
-}
-
-typedef struct htmlentity
-{
-	char code[8];
-	char is[4];
-} htmlentity_t;
-
-/* FIXME: This is ISO8859-1(5) centric, so might cause problems with other charsets. */
-
-static const htmlentity_t ent[] =
-{
-	{ "lt",     "<" },
-	{ "gt",     ">" },
-	{ "amp",    "&" },
-	{ "quot",   "\"" },
-	{ "aacute", "á" },
-	{ "eacute", "é" },
-	{ "iacute", "é" },
-	{ "oacute", "ó" },
-	{ "uacute", "ú" },
-	{ "agrave", "à" },
-	{ "egrave", "è" },
-	{ "igrave", "ì" },
-	{ "ograve", "ò" },
-	{ "ugrave", "ù" },
-	{ "acirc",  "â" },
-	{ "ecirc",  "ê" },
-	{ "icirc",  "î" },
-	{ "ocirc",  "ô" },
-	{ "ucirc",  "û" },
-	{ "auml",   "ä" },
-	{ "euml",   "ë" },
-	{ "iuml",   "ï" },
-	{ "ouml",   "ö" },
-	{ "uuml",   "ü" },
-	{ "nbsp",   " " },
-	{ "",        ""  }
-};
-
-void strip_html( char *in )
-{
-	char *start = in;
-	char *out = g_malloc( strlen( in ) + 1 );
-	char *s = out, *cs;
-	int i, matched;
-	
-	memset( out, 0, strlen( in ) + 1 );
-	
-	while( *in )
-	{
-		if( *in == '<' && ( isalpha( *(in+1) ) || *(in+1) == '/' ) )
-		{
-			/* If in points at a < and in+1 points at a letter or a slash, this is probably
-			   a HTML-tag. Try to find a closing > and continue there. If the > can't be
-			   found, assume that it wasn't a HTML-tag after all. */
-			
-			cs = in;
-			
-			while( *in && *in != '>' )
-				in ++;
-			
-			if( *in )
-			{
-				if( g_strncasecmp( cs+1, "br", 2) == 0 )
-					*(s++) = '\n';
-				in ++;
-			}
-			else
-			{
-				in = cs;
-				*(s++) = *(in++);
-			}
-		}
-		else if( *in == '&' )
-		{
-			cs = ++in;
-			while( *in && isalpha( *in ) )
-				in ++;
-			
-			if( *in == ';' ) in ++;
-			matched = 0;
-			
-			for( i = 0; *ent[i].code; i ++ )
-				if( g_strncasecmp( ent[i].code, cs, strlen( ent[i].code ) ) == 0 )
-				{
-					int j;
-					
-					for( j = 0; ent[i].is[j]; j ++ )
-						*(s++) = ent[i].is[j];
-					
-					matched = 1;
-					break;
-				}
-
-			/* None of the entities were matched, so return the string */
-			if( !matched )
-			{
-				in = cs - 1;
-				*(s++) = *(in++);
-			}
-		}
-		else
-		{
-			*(s++) = *(in++);
-		}
-	}
-	
-	strcpy( start, out );
-	g_free( out );
-}
-
-char *escape_html( const char *html )
-{
-	const char *c = html;
-	GString *ret;
-	char *str;
-	
-	if( html == NULL )
-		return( NULL );
-	
-	ret = g_string_new( "" );
-	
-	while( *c )
-	{
-		switch( *c )
-		{
-			case '&':
-				ret = g_string_append( ret, "&amp;" );
-				break;
-			case '<':
-				ret = g_string_append( ret, "&lt;" );
-				break;
-			case '>':
-				ret = g_string_append( ret, "&gt;" );
-				break;
-			case '"':
-				ret = g_string_append( ret, "&quot;" );
-				break;
-			default:
-				ret = g_string_append_c( ret, *c );
-		}
-		c ++;
-	}
-	
-	str = ret->str;
-	g_string_free( ret, FALSE );
-	return( str );
-}
-
-void info_string_append(GString *str, char *newline, char *name, char *value)
-{
-	if( value && value[0] )
-		g_string_sprintfa( str, "%s%s: %s", newline, name, value );
-}
-
-/* Decode%20a%20file%20name						*/
-void http_decode( char *s )
-{
-	char *t;
-	int i, j, k;
-	
-	t = g_new( char, strlen( s ) + 1 );
-	
-	for( i = j = 0; s[i]; i ++, j ++ )
-	{
-		if( s[i] == '%' )
-		{
-			if( sscanf( s + i + 1, "%2x", &k ) )
-			{
-				t[j] = k;
-				i += 2;
-			}
-			else
-			{
-				*t = 0;
-				break;
-			}
-		}
-		else
-		{
-			t[j] = s[i];
-		}
-	}
-	t[j] = 0;
-	
-	strcpy( s, t );
-	g_free( t );
-}
-
-/* Warning: This one explodes the string. Worst-cases can make the string 3x its original size! */
-/* This fuction is safe, but make sure you call it safely as well! */
-void http_encode( char *s )
-{
-	char *t;
-	int i, j;
-	
-	t = g_strdup( s );
-	
-	for( i = j = 0; t[i]; i ++, j ++ )
-	{
-		/* if( t[i] <= ' ' || ((unsigned char *)t)[i] >= 128 || t[i] == '%' ) */
-		if( !isalnum( t[i] ) )
-		{
-			sprintf( s + j, "%%%02X", ((unsigned char*)t)[i] );
-			j += 2;
-		}
-		else
-		{
-			s[j] = t[i];
-		}
-	}
-	s[j] = 0;
-	
-	g_free( t );
-}
-
-/* Strip newlines from a string. Modifies the string passed to it. */ 
-char *strip_newlines( char *source )
-{
-	int i;	
-
-	for( i = 0; source[i] != '\0'; i ++ )
-		if( source[i] == '\n' || source[i] == '\r' )
-			source[i] = ' ';
-	
-	return source;
-}
-
-#ifdef IPV6
-/* Wrap an IPv4 address into IPv6 space. Not thread-safe... */
-char *ipv6_wrap( char *src )
-{
-	static char dst[64];
-	int i;
-	
-	for( i = 0; src[i]; i ++ )
-		if( ( src[i] < '0' || src[i] > '9' ) && src[i] != '.' )
-			break;
-	
-	/* Hmm, it's not even an IP... */
-	if( src[i] )
-		return src;
-	
-	g_snprintf( dst, sizeof( dst ), "::ffff:%s", src );
-	
-	return dst;
-}
-
-/* Unwrap an IPv4 address into IPv6 space. Thread-safe, because it's very simple. :-) */
-char *ipv6_unwrap( char *src )
-{
-	int i;
-	
-	if( g_strncasecmp( src, "::ffff:", 7 ) != 0 )
-		return src;
-	
-	for( i = 7; src[i]; i ++ )
-		if( ( src[i] < '0' || src[i] > '9' ) && src[i] != '.' )
-			break;
-	
-	/* Hmm, it's not even an IP... */
-	if( src[i] )
-		return src;
-	
-	return ( src + 7 );
-}
-#endif
-
-/* Convert from one charset to another.
-   
-   from_cs, to_cs: Source and destination charsets
-   src, dst: Source and destination strings
-   size: Size if src. 0 == use strlen(). strlen() is not reliable for UNICODE/UTF16 strings though.
-   maxbuf: Maximum number of bytes to write to dst
-   
-   Returns the number of bytes written to maxbuf or -1 on an error.
-*/
-signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf )
-{
-	GIConv cd;
-	size_t res;
-	size_t inbytesleft, outbytesleft;
-	char *inbuf = src;
-	char *outbuf = dst;
-	
-	cd = g_iconv_open( to_cs, from_cs );
-	if( cd == (GIConv) -1 )
-		return( -1 );
-	
-	inbytesleft = size ? size : strlen( src );
-	outbytesleft = maxbuf - 1;
-	res = g_iconv( cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft );
-	*outbuf = '\0';
-	g_iconv_close( cd );
-	
-	if( res == (size_t) -1 )
-		return( -1 );
-	else
-		return( outbuf - dst );
-}
-
-char *set_eval_charset( irc_t *irc, set_t *set, char *value )
-{
-	GIConv cd;
-
-	if ( g_strncasecmp( value, "none", 4 ) == 0 )
-		return( value );
-
-	cd = g_iconv_open( "UTF-8", value );
-	if( cd == (GIConv) -1 )
-		return( NULL );
-
-	g_iconv_close( cd );
-	return( value );
-}
Index: il.h
===================================================================
--- util.h	(revision 812a41362a9316da1734fdaa8b1aad36bde9cb5c)
+++ 	(revision )
@@ -1,51 +1,0 @@
-  /********************************************************************\
-  * BitlBee -- An IRC to other IM-networks gateway                     *
-  *                                                                    *
-  * Copyright 2002-2004 Wilmer van der Gaast and others                *
-  \********************************************************************/
-
-/* Misc. functions                                                      */
-
-/*
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program 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 General Public License for more details.
-
-  You should have received a copy of the GNU General Public License with
-  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
-  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
-  Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#ifndef _UTIL_H
-#define _UTIL_H
-
-G_MODULE_EXPORT void strip_linefeed( gchar *text );
-G_MODULE_EXPORT char *add_cr( char *text );
-G_MODULE_EXPORT char *strip_newlines(char *source);
-G_MODULE_EXPORT char *tobase64( const char *text );
-G_MODULE_EXPORT void base64_encode_real( const unsigned char *in, int inlen, unsigned char *out, char *b64digits );
-G_MODULE_EXPORT char *normalize( const char *s );
-G_MODULE_EXPORT void info_string_append( GString *str, char *newline, char *name, char *value );
-
-G_MODULE_EXPORT time_t get_time( int year, int month, int day, int hour, int min, int sec );
-double gettime( void );
-
-G_MODULE_EXPORT void strip_html( char *msg );
-G_MODULE_EXPORT char *escape_html( const char *html );
-G_MODULE_EXPORT void http_decode( char *s );
-G_MODULE_EXPORT void http_encode( char *s );
-
-G_MODULE_EXPORT char *ipv6_wrap( char *src );
-G_MODULE_EXPORT char *ipv6_unwrap( char *src );
-
-G_MODULE_EXPORT signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf );
-char *set_eval_charset( irc_t *irc, set_t *set, char *value );
-
-#endif
