Index: Makefile
===================================================================
--- Makefile	(revision c821e8ad0d1cf9ab71e6e34c685d0adea2dde923)
+++ Makefile	(revision de8e584d7f4fea214934af094a4df2672d7e0be8)
@@ -10,6 +10,6 @@
 
 # Program variables
-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_OBJS) unix.o user.o dcc.o
-headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h dcc.h lib/events.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/nogaim.h protocols/ft.h
+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_OBJS) unix.o user.o
+headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/nogaim.h
 subdirs = lib protocols
 
Index: conf.c
===================================================================
--- conf.c	(revision c821e8ad0d1cf9ab71e6e34c685d0adea2dde923)
+++ conf.c	(revision de8e584d7f4fea214934af094a4df2672d7e0be8)
@@ -63,5 +63,4 @@
 	conf->ping_timeout = 300;
 	conf->user = NULL;
-	conf->max_filetransfer_size = G_MAXUINT;
 	proxytype = 0;
 	
Index: conf.h
===================================================================
--- conf.h	(revision c821e8ad0d1cf9ab71e6e34c685d0adea2dde923)
+++ conf.h	(revision de8e584d7f4fea214934af094a4df2672d7e0be8)
@@ -50,5 +50,4 @@
 	int ping_timeout;
 	char *user;
-	size_t max_filetransfer_size;
 } conf_t;
 
Index: c.c
===================================================================
--- dcc.c	(revision c821e8ad0d1cf9ab71e6e34c685d0adea2dde923)
+++ 	(revision )
@@ -1,718 +1,0 @@
-/********************************************************************\
-* BitlBee -- An IRC to other IM-networks gateway                     *
-*                                                                    *
-* Copyright 2007 Uli Meis <a.sporto+bee@gmail.com>                   *
-\********************************************************************/
-
-/*
-  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"
-#include "ft.h"
-#include "dcc.h"
-#include <poll.h>
-#include <netinet/tcp.h>
-#include <regex.h>
-
-/* Some ifdefs for ulibc (Thanks to Whoopie) */
-#ifndef HOST_NAME_MAX
-#include <sys/param.h>
-#ifdef MAXHOSTNAMELEN
-#define HOST_NAME_MAX MAXHOSTNAMELEN
-#else
-#define HOST_NAME_MAX 255
-#endif
-#endif
-
-#ifndef AI_NUMERICSERV
-#define AI_NUMERICSERV 0x0400   /* Don't use name resolution.  */
-#endif
-
-/* 
- * Since that might be confusing a note on naming:
- *
- * Generic dcc functions start with 
- *
- * 	dcc_
- *
- * ,methods specific to DCC SEND start with
- *
- * 	dccs_
- *
- * . Since we can be on both ends of a DCC SEND,
- * functions specific to one end are called
- *
- * 	dccs_send and dccs_recv
- *
- * ,respectively.
- */
-
-
-/* 
- * used to generate a unique local transfer id the user
- * can use to reject/cancel transfers
- */
-unsigned int local_transfer_id=1;
-
-/* 
- * just for debugging the nr. of chunks we received from im-protocols and the total data
- */
-unsigned int receivedchunks=0, receiveddata=0;
-
-int max_packet_size = 0;
-
-static void dcc_finish( file_transfer_t *file );
-static void dcc_close( file_transfer_t *file );
-gboolean dccs_send_proto( gpointer data, gint fd, b_input_condition cond );
-gboolean dcc_listen( dcc_file_transfer_t *df, struct sockaddr_storage **saddr_ptr );
-int dccs_send_request( struct dcc_file_transfer *df, char *user_nick, struct sockaddr_storage *saddr );
-gboolean dccs_recv_start( file_transfer_t *ft );
-gboolean dccs_recv_proto( gpointer data, gint fd, b_input_condition cond);
-gboolean dccs_recv_write_request( file_transfer_t *ft );
-gboolean dcc_progress( gpointer data, gint fd, b_input_condition cond );
-
-/* As defined in ft.h */
-file_transfer_t *imcb_file_send_start( struct im_connection *ic, char *handle, char *file_name, size_t file_size )
-{
-	user_t *u = user_findhandle( ic, handle );
-	/* one could handle this more intelligent like imcb_buddy_msg.
-	 * can't call it directly though cause it does some wrapping.
-	 * Maybe give imcb_buddy_msg a parameter NO_WRAPPING? */
-	if (!u) return NULL;
-
-	return dccs_send_start( ic, u->nick, file_name, file_size );
-};
-
-/* As defined in ft.h */
-void imcb_file_canceled( file_transfer_t *file, char *reason )
-{
-	if( file->canceled )
-		file->canceled( file, reason );
-
-	dcc_close( file );
-}
-
-/* As defined in ft.h */
-gboolean imcb_file_recv_start( file_transfer_t *ft )
-{
-	return dccs_recv_start( ft );
-}
-
-dcc_file_transfer_t *dcc_alloc_transfer( char *file_name, size_t file_size, struct im_connection *ic )
-{
-	file_transfer_t *file = g_new0( file_transfer_t, 1 );
-	dcc_file_transfer_t *df = file->priv = g_new0( dcc_file_transfer_t, 1);
-	file->file_size = file_size;
-	file->file_name = g_strdup( file_name );
-	file->local_id = local_transfer_id++;
-	df->ic = ic;
-	df->ft = file;
-	
-	return df;
-}
-
-/* This is where the sending magic starts... */
-file_transfer_t *dccs_send_start( struct im_connection *ic, char *user_nick, char *file_name, size_t file_size )
-{
-	file_transfer_t *file;
-	dcc_file_transfer_t *df;
-	struct sockaddr_storage *saddr;
-
-	if( file_size > global.conf->max_filetransfer_size )
-		return NULL;
-	
-	df = dcc_alloc_transfer( file_name, file_size, ic );
-	file = df->ft;
-	file->write = dccs_send_write;
-
-	/* listen and request */
-	if( !dcc_listen( df, &saddr ) ||
-	    !dccs_send_request( df, user_nick, saddr ) )
-		return NULL;
-
-	g_free( saddr );
-
-	/* watch */
-	df->watch_in = b_input_add( df->fd, GAIM_INPUT_READ, dccs_send_proto, df );
-
-	df->ic->irc->file_transfers = g_slist_prepend( df->ic->irc->file_transfers, file );
-
-	df->progress_timeout = b_timeout_add( DCC_MAX_STALL * 1000, dcc_progress, df );
-
-	return file;
-}
-
-/* Used pretty much everywhere in the code to abort a transfer */
-gboolean dcc_abort( dcc_file_transfer_t *df, char *reason, ... )
-{
-	file_transfer_t *file = df->ft;
-	va_list params;
-	va_start( params, reason );
-	char *msg = g_strdup_vprintf( reason, params );
-	va_end( params );
-	
-	file->status |= FT_STATUS_CANCELED;
-	
-	if( file->canceled )
-		file->canceled( file, msg );
-
-	imcb_log( df->ic, "File %s: DCC transfer aborted: %s", file->file_name, msg );
-
-	g_free( msg );
-
-	dcc_close( df->ft );
-
-	return FALSE;
-}
-
-gboolean dcc_progress( gpointer data, gint fd, b_input_condition cond )
-{
-	struct dcc_file_transfer *df = data;
-
-	if( df->bytes_sent == df->progress_bytes_last )
-	{
-		/* no progress. cancel */
-		if( df->bytes_sent == 0 )
-			return dcc_abort( df, "Couldnt establish transfer within %d seconds", DCC_MAX_STALL );
-		else 
-			return dcc_abort( df, "Transfer stalled for %d seconds at %d kb", DCC_MAX_STALL, df->bytes_sent / 1024 );
-
-	}
-
-	df->progress_bytes_last = df->bytes_sent;
-
-	return TRUE;
-}
-
-/* used extensively for socket operations */
-#define ASSERTSOCKOP(op, msg) \
-	if( (op) == -1 ) \
-		return dcc_abort( df , msg ": %s", strerror( errno ) );
-
-/* Creates the "DCC SEND" line and sends it to the server */
-int dccs_send_request( struct dcc_file_transfer *df, char *user_nick, struct sockaddr_storage *saddr )
-{
-	char ipaddr[INET6_ADDRSTRLEN]; 
-	const void *netaddr;
-	int port;
-	char *cmd;
-
-	if( saddr->ss_family == AF_INET )
-	{
-		struct sockaddr_in *saddr_ipv4 = ( struct sockaddr_in *) saddr;
-
-		sprintf( ipaddr, "%d", 
-			 ntohl( saddr_ipv4->sin_addr.s_addr ) );
-		port = saddr_ipv4->sin_port;
-	} else 
-	{
-		struct sockaddr_in6 *saddr_ipv6 = ( struct sockaddr_in6 *) saddr;
-
-		netaddr = &saddr_ipv6->sin6_addr.s6_addr;
-		port = saddr_ipv6->sin6_port;
-
-		/* 
-		 * Didn't find docs about this, but it seems that's the way irssi does it
-		 */
-		if( !inet_ntop( saddr->ss_family, netaddr, ipaddr, sizeof( ipaddr ) ) )
-			return dcc_abort( df, "inet_ntop failed: %s", strerror( errno ) );
-	}
-
-	port = ntohs( port );
-
-	cmd = g_strdup_printf( "\001DCC SEND %s %s %u %zu\001",
-				df->ft->file_name, ipaddr, port, df->ft->file_size );
-	
-	if ( !irc_msgfrom( df->ic->irc, user_nick, cmd ) )
-		return dcc_abort( df, "couldn't send 'DCC SEND' message to %s", user_nick );
-
-	g_free( cmd );
-
-	return TRUE;
-}
-
-/*
- * Creates a listening socket and returns it in saddr_ptr.
- */
-gboolean dcc_listen( dcc_file_transfer_t *df, struct sockaddr_storage **saddr_ptr )
-{
-	file_transfer_t *file = df->ft;
-	struct sockaddr_storage *saddr;
-	int fd,gret;
-	char hostname[ HOST_NAME_MAX + 1 ];
-	struct addrinfo hints, *rp;
-	socklen_t ssize = sizeof( struct sockaddr_storage );
-
-	/* won't be long till someone asks for this to be configurable :) */
-
-	ASSERTSOCKOP( gethostname( hostname, sizeof( hostname ) ), "gethostname()" );
-
-	memset( &hints, 0, sizeof( struct addrinfo ) );
-	hints.ai_socktype = SOCK_STREAM;
-	hints.ai_flags = AI_NUMERICSERV;
-
-	if ( ( gret = getaddrinfo( hostname, "0", &hints, &rp ) != 0 ) )
-		return dcc_abort( df, "getaddrinfo(): %s", gai_strerror( gret ) );
-
-	saddr = g_new( struct sockaddr_storage, 1 );
-
-	*saddr_ptr = saddr;
-
-	memcpy( saddr, rp->ai_addr, rp->ai_addrlen );
-
-	ASSERTSOCKOP( fd = df->fd = socket( saddr->ss_family, SOCK_STREAM, 0 ), "Opening socket" );
-
-	ASSERTSOCKOP( bind( fd, ( struct sockaddr *)saddr, rp->ai_addrlen ), "Binding socket" );
-	
-	freeaddrinfo( rp );
-
-	ASSERTSOCKOP( getsockname( fd, ( struct sockaddr *)saddr, &ssize ), "Getting socket name" );
-
-	ASSERTSOCKOP( listen( fd, 1 ), "Making socket listen" );
-
-	file->status = FT_STATUS_LISTENING;
-
-	return TRUE;
-}
-
-/*
- * Checks poll(), same for receiving and sending
- */
-gboolean dcc_poll( dcc_file_transfer_t *df, int fd, short *revents )
-{
-	struct pollfd pfd = { .fd = fd, .events = POLLHUP|POLLERR|POLLIN|POLLOUT };
-
-	ASSERTSOCKOP( poll( &pfd, 1, 0 ), "poll()" )
-
-	if( pfd.revents & POLLERR )
-	{
-		int sockerror;
-		socklen_t errlen = sizeof( sockerror );
-
-		if ( getsockopt( fd, SOL_SOCKET, SO_ERROR, &sockerror, &errlen ) )
-			return dcc_abort( df, "getsockopt() failed, unknown socket error (weird!)" );
-
-		return dcc_abort( df, "Socket error: %s", strerror( sockerror ) );
-	}
-	
-	if( pfd.revents & POLLHUP ) 
-		return dcc_abort( df, "Remote end closed connection" );
-	
-	*revents = pfd.revents;
-
-	return TRUE;
-}
-
-/*
- * fills max_packet_size with twice the TCP maximum segment size
- */
-gboolean  dcc_check_maxseg( dcc_file_transfer_t *df, int fd )
-{
-	/* 
-	 * use twice the maximum segment size as a maximum for calls to send().
-	 */
-	if( max_packet_size == 0 )
-	{
-		unsigned int mpslen = sizeof( max_packet_size );
-		if( getsockopt( fd, IPPROTO_TCP, TCP_MAXSEG, &max_packet_size, &mpslen ) )
-			return dcc_abort( df, "getsockopt() failed" );
-		max_packet_size *= 2;
-	}
-	return TRUE;
-}
-
-/*
- * After setup, the transfer itself is handled entirely by this function.
- * There are basically four things to handle: connect, receive, send, and error.
- */
-gboolean dccs_send_proto( gpointer data, gint fd, b_input_condition cond )
-{
-	dcc_file_transfer_t *df = data;
-	file_transfer_t *file = df->ft;
-	short revents;
-	
-	if( !dcc_poll( df, fd, &revents) )
-		return FALSE;
-
-	if( ( revents & POLLIN ) &&
-	    ( file->status & FT_STATUS_LISTENING ) )
-	{ 	
-		struct sockaddr *clt_addr;
-		socklen_t ssize = sizeof( clt_addr );
-
-		/* Connect */
-
-		ASSERTSOCKOP( df->fd = accept( fd, (struct sockaddr *) &clt_addr, &ssize ), "Accepting connection" );
-
-		closesocket( fd );
-		fd = df->fd;
-		file->status = FT_STATUS_TRANSFERRING;
-		sock_make_nonblocking( fd );
-
-		if ( !dcc_check_maxseg( df, fd ) )
-			return FALSE;
-
-		/* IM protocol callback */
-		if( file->accept )
-			file->accept( file );
-
-		/* reschedule for reading on new fd */
-		df->watch_in = b_input_add( fd, GAIM_INPUT_READ, dccs_send_proto, df );
-
-		return FALSE;
-	}
-
-	if( revents & POLLIN ) 
-	{
-		int bytes_received;
-		int ret;
-		
-		ASSERTSOCKOP( ret = recv( fd, &bytes_received, sizeof( bytes_received  ), MSG_PEEK ), "Receiving" );
-
-		if( ret == 0 )
-			return dcc_abort( df, "Remote end closed connection" );
-			
-		if( ret < 4 )
-		{
-			imcb_log( df->ic, "WARNING: DCC SEND: receiver sent only 2 bytes instead of 4, shouldn't happen too often!" );
-			return TRUE;
-		}
-
-		ASSERTSOCKOP( ret = recv( fd, &bytes_received, sizeof( bytes_received  ), 0 ), "Receiving" );
-		if( ret != 4 )
-			return dcc_abort( df, "MSG_PEEK'ed 4, but can only dequeue %d bytes", ret );
-
-		bytes_received = ntohl( bytes_received );
-
-		/* If any of this is actually happening, the receiver should buy a new IRC client */
-
-		if ( bytes_received > df->bytes_sent )
-			return dcc_abort( df, "Receiver magically received more bytes than sent ( %d > %d ) (BUG at receiver?)", bytes_received, df->bytes_sent );
-
-		if ( bytes_received < file->bytes_transferred )
-			return dcc_abort( df, "Receiver lost bytes? ( has %d, had %d ) (BUG at receiver?)", bytes_received, file->bytes_transferred );
-		
-		file->bytes_transferred = bytes_received;
-	
-		if( file->bytes_transferred >= file->file_size ) {
-			dcc_finish( file );
-			return FALSE;
-		}
-	
-		return TRUE;
-	}
-
-	return TRUE;
-}
-
-gboolean dccs_recv_start( file_transfer_t *ft )
-{
-	dcc_file_transfer_t *df = ft->priv;
-	struct sockaddr_storage *saddr = &df->saddr;
-	int fd;
-	char ipaddr[INET6_ADDRSTRLEN]; 
-	socklen_t sa_len = saddr->ss_family == AF_INET ? 
-		sizeof( struct sockaddr_in ) : sizeof( struct sockaddr_in6 );
-	
-	if( !ft->write )
-		return dcc_abort( df, "BUG: protocol didn't register write()" );
-	
-	ASSERTSOCKOP( fd = df->fd = socket( saddr->ss_family, SOCK_STREAM, 0 ) , "Opening Socket" );
-
-	sock_make_nonblocking( fd );
-
-	if( ( connect( fd, (struct sockaddr *)saddr, sa_len ) == -1 ) &&
-	    ( errno != EINPROGRESS ) )
-		return dcc_abort( df, "Connecting to %s:%d : %s", 
-			inet_ntop( saddr->ss_family, 
-				saddr->ss_family == AF_INET ? 
-				    ( void* ) &( ( struct sockaddr_in *) saddr )->sin_addr.s_addr :
-				    ( void* ) &( ( struct sockaddr_in6 *) saddr )->sin6_addr.s6_addr,
-				ipaddr, 
-				sizeof( ipaddr ) ),
-			ntohs( saddr->ss_family == AF_INET ?
-			    ( ( struct sockaddr_in *) saddr )->sin_port :
-			    ( ( struct sockaddr_in6 *) saddr )->sin6_port ),
-			strerror( errno ) );
-
-	ft->status = FT_STATUS_CONNECTING;
-
-	/* watch */
-	df->watch_out = b_input_add( df->fd, GAIM_INPUT_WRITE, dccs_recv_proto, df );
-	ft->write_request = dccs_recv_write_request;
-
-	df->progress_timeout = b_timeout_add( DCC_MAX_STALL * 1000, dcc_progress, df );
-
-	return TRUE;
-}
-
-gboolean dccs_recv_proto( gpointer data, gint fd, b_input_condition cond)
-{
-	dcc_file_transfer_t *df = data;
-	file_transfer_t *ft = df->ft;
-	short revents;
-
-	if( !dcc_poll( df, fd, &revents ) )
-		return FALSE;
-	
-	if( ( revents & POLLOUT ) &&
-	    ( ft->status & FT_STATUS_CONNECTING ) )
-	{
-		ft->status = FT_STATUS_TRANSFERRING;
-		if ( !dcc_check_maxseg( df, fd ) )
-			return FALSE;
-
-		//df->watch_in = b_input_add( df->fd, GAIM_INPUT_READ, dccs_recv_proto, df );
-
-		df->watch_out = 0;
-		return FALSE;
-	}
-
-	if( revents & POLLIN )
-	{
-		int ret, done;
-
-		ASSERTSOCKOP( ret = recv( fd, ft->buffer, sizeof( ft->buffer ), 0 ), "Receiving" );
-
-		if( ret == 0 )
-			return dcc_abort( df, "Remote end closed connection" );
-
-		df->bytes_sent += ret;
-
-		done = df->bytes_sent >= ft->file_size;
-
-		if( ( ( df->bytes_sent - ft->bytes_transferred ) > DCC_PACKET_SIZE ) ||
-		    done )
-		{
-			int ack, ackret;
-			ack = htonl( ft->bytes_transferred = df->bytes_sent );
-
-			ASSERTSOCKOP( ackret = send( fd, &ack, 4, 0 ), "Sending DCC ACK" );
-			
-			if ( ackret != 4 )
-				return dcc_abort( df, "Error sending DCC ACK, sent %d instead of 4 bytes", ackret );
-		}
-		
-		if( !ft->write( df->ft, ft->buffer, ret ) )
-			return FALSE;
-
-		if( done )
-		{
-			closesocket( fd );
-			dcc_finish( ft );
-
-			df->watch_in = 0;
-			return FALSE;
-		}
-
-		df->watch_in = 0;
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-gboolean dccs_recv_write_request( file_transfer_t *ft )
-{
-	dcc_file_transfer_t *df = ft->priv;
-
-	if( df->watch_in )
-		return dcc_abort( df, "BUG: write_request() called while watching" );
-
-	df->watch_in = b_input_add( df->fd, GAIM_INPUT_READ, dccs_recv_proto, df );
-
-	return TRUE;
-}
-
-gboolean dccs_send_can_write( gpointer data, gint fd, b_input_condition cond )
-{
-	struct dcc_file_transfer *df = data;
-	df->watch_out = 0;
-
-	df->ft->write_request( df->ft );
-	return FALSE;
-}
-
-/* 
- * Incoming data.
- * 
- */
-gboolean dccs_send_write( file_transfer_t *file, char *data, unsigned int data_len )
-{
-	dcc_file_transfer_t *df = file->priv;
-	int ret;
-
-	receivedchunks++; receiveddata += data_len;
-
-	if( df->watch_out )
-		return dcc_abort( df, "BUG: write() called while watching" );
-
-	ASSERTSOCKOP( ret = send( df->fd, data, data_len, 0 ), "Sending data" );
-
-	if( ret == 0 )
-		return dcc_abort( df, "Remote end closed connection" );
-
-	/* TODO: this should really not be fatal */
-	if( ret < data_len )
-		return dcc_abort( df, "send() sent %d instead of %d", ret, data_len );
-
-	df->bytes_sent += ret;
-
-	if( df->bytes_sent < df->ft->file_size )
-		df->watch_out = b_input_add( df->fd, GAIM_INPUT_WRITE, dccs_send_can_write, df );
-
-	return TRUE;
-}
-
-/*
- * Cleans up after a transfer.
- */
-static void dcc_close( file_transfer_t *file )
-{
-	dcc_file_transfer_t *df = file->priv;
-
-	if( file->free )
-		file->free( file );
-	
-	closesocket( df->fd );
-
-	if( df->watch_in )
-		b_event_remove( df->watch_in );
-
-	if( df->watch_out )
-		b_event_remove( df->watch_out );
-	
-	if( df->progress_timeout )
-		b_event_remove( df->progress_timeout );
-	
-	df->ic->irc->file_transfers = g_slist_remove( df->ic->irc->file_transfers, file );
-	
-	g_free( df );
-	g_free( file->file_name );
-	g_free( file );
-}
-
-void dcc_finish( file_transfer_t *file )
-{
-	file->status |= FT_STATUS_FINISHED;
-	
-	if( file->finished )
-		file->finished( file );
-
-	dcc_close( file );
-}
-
-/* 
- * DCC SEND <filename> <IP> <port> <filesize>
- *
- * filename can be in "" or not. If it is, " can probably be escaped...
- * IP can be an unsigned int (IPV4) or something else (IPV6)
- * 
- */
-file_transfer_t *dcc_request( struct im_connection *ic, char *line )
-{
-	char *pattern = "SEND"
-		" (([^\"][^ ]*)|\"([^\"]|\\\")*\")"
-		" (([0-9]*)|([^ ]*))"
-		" ([0-9]*)"
-		" ([0-9]*)\001";
-	regmatch_t pmatch[9];
-	regex_t re;
-	file_transfer_t *ft;
-	dcc_file_transfer_t *df;
-	char errbuf[256];
-	int regerrcode, gret;
-
-	if( ( regerrcode = regcomp( &re, pattern, REG_EXTENDED ) ) ||
-	    ( regerrcode = regexec( &re, line, 9, pmatch, 0 ) ) ) {
-		regerror( regerrcode,&re,errbuf,sizeof( errbuf ) );
-		imcb_log( ic, 
-			  "DCC: error parsing 'DCC SEND': %s, line: %s", 
-			  errbuf, line );
-		return NULL;
-	}
-
-	if( ( pmatch[1].rm_so > 0 ) &&
-	    ( pmatch[4].rm_so > 0 ) &&
-	    ( pmatch[7].rm_so > 0 ) &&
-	    ( pmatch[8].rm_so > 0 ) )
-	{
-		char *input = g_strdup( line );
-		char *filename, *host, *port;
-		size_t filesize;
-		struct addrinfo hints, *rp;
-
-		/* "filename" or filename */
-		if ( pmatch[2].rm_so > 0 )
-		{
-			input[pmatch[2].rm_eo] = '\0';
-			filename = input + pmatch[2].rm_so;
-		} else
-		{
-			input[pmatch[3].rm_eo] = '\0';
-			filename = input + pmatch[3].rm_so;
-		}
-			
-		input[pmatch[4].rm_eo] = '\0';
-
-		/* number means ipv4, something else means ipv6 */
-		if ( pmatch[5].rm_so > 0 )
-		{
-			struct in_addr ipaddr = { .s_addr = htonl( atoi( input + pmatch[5].rm_so ) ) };
-			host = inet_ntoa( ipaddr );
-		} else
-		{
-			/* Contains non-numbers, hopefully an IPV6 address */
-			host = input + pmatch[6].rm_so;
-		}
-
-		input[pmatch[7].rm_eo] = '\0';
-		input[pmatch[8].rm_eo] = '\0';
-
-		port = input + pmatch[7].rm_so;
-		filesize = atoll( input + pmatch[8].rm_so );
-
-		memset( &hints, 0, sizeof ( struct addrinfo ) );
-		if ( ( gret = getaddrinfo( host, port, &hints, &rp ) ) )
-		{
-			g_free( input );
-			imcb_log( ic, "DCC: getaddrinfo() failed with %s "
-				  "when parsing incoming 'DCC SEND': "
-				  "host %s, port %s", 
-				  gai_strerror( gret ), host, port );
-			return NULL;
-		}
-
-		df = dcc_alloc_transfer( filename, filesize, ic );
-		ft = df->ft;
-		ft->sending = TRUE;
-		memcpy( &df->saddr, rp->ai_addr, rp->ai_addrlen );
-
-		freeaddrinfo( rp );
-		g_free( input );
-
-		df->ic->irc->file_transfers = g_slist_prepend( df->ic->irc->file_transfers, ft );
-
-		return ft;
-	}
-
-	imcb_log( ic, "DCC: couldnt parse 'DCC SEND' line: %s", line );
-
-	return NULL;
-}
-
Index: c.h
===================================================================
--- dcc.h	(revision c821e8ad0d1cf9ab71e6e34c685d0adea2dde923)
+++ 	(revision )
@@ -1,94 +1,0 @@
-/********************************************************************\
-* BitlBee -- An IRC to other IM-networks gateway                     *
-*                                                                    *
-* Copyright 2006 Marijn Kruisselbrink and others                     *
-* Copyright 2007 Uli Meis <a.sporto+bee@gmail.com>                   *
-\********************************************************************/
-
-/*
-  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
-*/
-
-/* 
- * DCC SEND
- *
- * Historically, DCC means send 1024 Bytes and wait for a 4 byte reply
- * acknowledging all transferred data. This is ridiculous for two reasons.  The
- * first being that TCP is a stream oriented protocol that doesn't care much
- * about your idea of a packet. The second reason being that TCP is a reliable
- * transfer protocol with its own sophisticated ACK mechanism, making DCCs ACK
- * mechanism look like a joke. For these reasons, DCCs requirements have
- * (hopefully) been relaxed in most implementations and this implementation
- * depends upon at least the following: The 1024 bytes need not be transferred
- * at once, i.e. packets can be smaller. A second relaxation has apparently
- * gotten the name "DCC SEND ahead" which basically means to not give a damn
- * about those DCC ACKs and just send data as you please. This behaviour is
- * enabled by default. Note that this also means that packets may be as large
- * as the maximum segment size.
- */ 
-
-#ifndef _DCC_H
-#define _DCC_H
-
-/* Send an ACK after receiving this amount of data */
-#define DCC_PACKET_SIZE 1024
-
-/* Time in seconds that a DCC transfer can be stalled before being aborted.
- * By handling this here individual protocols don't have to think about this. */
-#define DCC_MAX_STALL 120
-
-typedef struct dcc_file_transfer {
-
-	struct im_connection *ic;
-
-	/*
-	 * Depending in the status of the file transfer, this is either the socket that is
-	 * being listened on for connections, or the socket over which the file transfer is
-	 * taking place.
-	 */
-	int fd;
-	
-	/*
-	 * IDs returned by b_input_add for watch_ing over the above socket.
-	 */
-	gint watch_in;   /* readable */
-	gint watch_out;  /* writable */
-	
-	/* the progress watcher cancels any file transfer if nothing happens within DCC_MAX_STALL */
-	gint progress_timeout;
-	size_t progress_bytes_last;
-
-	/*
-	 * The total amount of bytes that have been sent to the irc client.
-	 */
-	size_t bytes_sent;
-	
-	/* imc's handle */
-	file_transfer_t *ft;
-
-	/* if we're receiving, this is the sender's socket address */
-	struct sockaddr_storage saddr;
-
-} dcc_file_transfer_t;
-
-file_transfer_t *dccs_send_start( struct im_connection *ic, char *user_nick, char *file_name, size_t file_size );
-
-void dcc_canceled( file_transfer_t *file, char *reason );
-
-gboolean dccs_send_write( file_transfer_t *file, char *data, unsigned int data_size );
-
-file_transfer_t *dcc_request( struct im_connection *ic, char *line );
-#endif
Index: doc/user-guide/commands.xml
===================================================================
--- doc/user-guide/commands.xml	(revision c821e8ad0d1cf9ab71e6e34c685d0adea2dde923)
+++ doc/user-guide/commands.xml	(revision de8e584d7f4fea214934af094a4df2672d7e0be8)
@@ -874,46 +874,3 @@
 
 	</bitlbee-command>
-	
-	<bitlbee-command name="transfers">
-		<short-description>Monitor, cancel, or reject file transfers</short-description>
-		<syntax>transfers [&lt;cancel&gt; id | &lt;reject&gt;]</syntax>
-		
-		<description>
-			<para>
-				Without parameters the currently pending file transfers and their status will be listed. Available actions are <emphasis>cancel</emphasis> and <emphasis>reject</emphasis>. See <emphasis>help transfers &lt;action&gt;</emphasis> for more information.
-			</para>
-
-			<ircexample>
-				<ircline nick="ulim">transfers</ircline>
-			</ircexample>
-		</description>
-		
-		<bitlbee-command name="cancel">
-			<short-description>Cancels the file transfer with the given id</short-description>
-			<syntax>transfers &lt;cancel&gt; id</syntax>
-
-			<description>
-				<para>Cancels the file transfer with the given id</para>
-			</description>
-
-			<ircexample>
-				<ircline nick="ulim">transfers cancel 1</ircline>
-				<ircline nick="root">Canceling file transfer for test</ircline>
-			</ircexample>
-		</bitlbee-command>
-
-		<bitlbee-command name="reject">
-			<short-description>Rejects all incoming transfers</short-description>
-			<syntax>transfers &lt;reject&gt;</syntax>
-
-			<description>
-				<para>Rejects all incoming (not already transferring) file transfers. Since you probably have only one incoming transfer at a time, no id is neccessary. Or is it?</para>
-			</description>
-
-			<ircexample>
-				<ircline nick="ulim">transfers reject</ircline>
-			</ircexample>
-		</bitlbee-command>
-	</bitlbee-command>
-	
 </chapter>
Index: irc.c
===================================================================
--- irc.c	(revision c821e8ad0d1cf9ab71e6e34c685d0adea2dde923)
+++ irc.c	(revision de8e584d7f4fea214934af094a4df2672d7e0be8)
@@ -28,5 +28,4 @@
 #include "crypting.h"
 #include "ipc.h"
-#include "dcc.h"
 
 static gboolean irc_userping( gpointer _irc, int fd, b_input_condition cond );
@@ -1071,17 +1070,7 @@
 			return( 1 );
 		}
-		else if( g_strncasecmp( s + 1, "DCC", 3 ) == 0 )
-		{
-			if( u && u->ic && u->ic->acc->prpl->transfer_request )
-			{
-				file_transfer_t *ft = dcc_request( u->ic, s + 5 );
-				if ( ft )
-					u->ic->acc->prpl->transfer_request( u->ic, ft, u->handle );
-			}
-			return( 1 );
-		}		
 		else
 		{
-			irc_usermsg( irc, "Supported CTCPs are ACTION, VERSION, PING, TYPING, DCC" );
+			irc_usermsg( irc, "Non-ACTION CTCP's aren't supported" );
 			return( 0 );
 		}
Index: irc.h
===================================================================
--- irc.h	(revision c821e8ad0d1cf9ab71e6e34c685d0adea2dde923)
+++ irc.h	(revision de8e584d7f4fea214934af094a4df2672d7e0be8)
@@ -87,5 +87,4 @@
 	struct query *queries;
 	struct account *accounts;
-	GSList *file_transfers;
 	
 	struct __USER *users;
Index: otocols/ft.h
===================================================================
--- protocols/ft.h	(revision c821e8ad0d1cf9ab71e6e34c685d0adea2dde923)
+++ 	(revision )
@@ -1,173 +1,0 @@
-/********************************************************************\
-* BitlBee -- An IRC to other IM-networks gateway                     *
-*                                                                    *
-* Copyright 2006 Marijn Kruisselbrink and others                     *
-\********************************************************************/
-
-/* Generic file transfer header                                     */
-
-/*
-  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 _FT_H
-#define _FT_H
-
-/*
- * One buffer is needed for each transfer. The receiver stores a message
- * in it and gives it to the sender. The sender will stall the receiver
- * till the buffer has been sent out.
- */
-#define FT_BUFFER_SIZE 2048
-
-typedef enum {
-	FT_STATUS_LISTENING	= 1,
-	FT_STATUS_TRANSFERRING	= 2,
-	FT_STATUS_FINISHED	= 4,
-	FT_STATUS_CANCELED	= 8,
-	FT_STATUS_CONNECTING	= 16
-} file_status_t;
-
-/*
- * This structure holds all irc specific information regarding an incoming (from the point of view of
- * the irc client) file transfer. New instances of this struct should only be created by calling the
- * imcb_file_send_start() method, which will initialize most of the fields. The data field and the various
- * methods are zero-initialized. Instances will automatically be deleted once the transfer is completed,
- * canceled, or the connection to the irc client has been lost (note that also if only the irc connection
- * and not the file transfer connection is lost, the file transfer will still be canceled and freed).
- *
- * The following (poor ascii-art) diagram illustrates what methods are called for which status-changes:
- *
- *	                        /-----------\                    /----------\
- *	               -------> | LISTENING | -----------------> | CANCELED |
- *	                        \-----------/  [canceled,]free   \----------/
- *	                              |
- *	                              | accept
- *	                              V
- *	               /------ /-------------\                    /------------------------\
- *	   out_of_data |       | TRANSFERING | -----------------> | TRANSFERING | CANCELED |
- *	               \-----> \-------------/  [canceled,]free   \------------------------/
- *	                              |
- *	                              | finished,free
- *	                              V
- *	                 /------------------------\
- *	                 | TRANSFERING | FINISHED |
- *	                 \------------------------/
- */
-typedef struct file_transfer {
-
-	/* Are we sending something? */
-	int sending;
-
-	/*
-	 * The current status of this file transfer.
-	 */ 
-	file_status_t status;
-	
-	/*
-	 * file size
-	 */
-	size_t file_size;
-	
-	/*
-	 * Number of bytes that have been successfully transferred.
-	 */
-	size_t bytes_transferred;
-
-	/*
-	 * Time started. Used to calculate kb/s.
-	 */
-	time_t started;
-
-	/*
-	 * file name
-	 */
-	char *file_name;
-
-	/*
-	 * A unique local ID for this file transfer.
-	 */
-	unsigned int local_id;
-
-	/*
-	 * IM-protocol specific data associated with this file transfer.
-	 */
-	gpointer data;
-	
-	/*
-	 * Private data.
-	 */
-	gpointer priv;
-	
-	/*
-	 * If set, called after succesful connection setup.
-	 */
-	void (*accept) ( struct file_transfer *file );
-	
-	/*
-	 * If set, called when the transfer is canceled or finished.
-	 * Subsequently, this structure will be freed.
-	 *
-	 */
-	void (*free) ( struct file_transfer *file );
-	
-	/*
-	 * If set, called when the transfer is finished and successful.
-	 */
-	void (*finished) ( struct file_transfer *file );
-	
-	/*
-	 * If set, called when the transfer is canceled.
-	 * ( canceled either by the transfer implementation or by
-	 *  a call to imcb_file_canceled )
-	 */
-	void (*canceled) ( struct file_transfer *file, char *reason );
-	
-	/*
-	 * called by the sending side to indicate that it is writable.
-	 * The callee should check if data is available and call the 
-	 * function(as seen below) if that is the case.
-	 */
-	gboolean (*write_request) ( struct file_transfer *file );
-
-	/*
-	 * When sending files, protocols register this function to receive data.
-	 * This should only be called once after write_request is called. The caller
-	 * should not read more data until write_request is called again. This technique
-	 * avoids buffering.
-	 */
-	gboolean (*write) (struct file_transfer *file, char *buffer, unsigned int len );
-
-	/* The send buffer associated with this transfer.
-	 * Since receivers always wait for a write_request call one is enough.
-	 */
-	char buffer[FT_BUFFER_SIZE];
-
-} file_transfer_t;
-
-/*
- * This starts a file transfer from bitlbee to the user.
- */
-file_transfer_t *imcb_file_send_start( struct im_connection *ic, char *user_nick, char *file_name, size_t file_size );
-
-/*
- * This should be called by a protocol when the transfer is canceled. Note that
- * the canceled() and free() callbacks given in file will be called by this function.
- */
-void imcb_file_canceled( file_transfer_t *file, char *reason );
-
-gboolean imcb_file_recv_start( file_transfer_t *ft );
-#endif
Index: protocols/jabber/Makefile
===================================================================
--- protocols/jabber/Makefile	(revision c821e8ad0d1cf9ab71e6e34c685d0adea2dde923)
+++ protocols/jabber/Makefile	(revision de8e584d7f4fea214934af094a4df2672d7e0be8)
@@ -10,5 +10,5 @@
 
 # [SH] Program variables
-objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o si.o s5bytestream.o
+objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o
 
 CFLAGS += -Wall
Index: protocols/jabber/iq.c
===================================================================
--- protocols/jabber/iq.c	(revision c821e8ad0d1cf9ab71e6e34c685d0adea2dde923)
+++ protocols/jabber/iq.c	(revision de8e584d7f4fea214934af094a4df2672d7e0be8)
@@ -90,7 +90,7 @@
 			pack = 0;
 		}
-		else if( strcmp( s, XMLNS_DISCO_INFO ) == 0 )
-		{
-			const char *features[] = { XMLNS_DISCO_INFO,
+		else if( strcmp( s, XMLNS_DISCOVER ) == 0 )
+		{
+			const char *features[] = { XMLNS_DISCOVER,
 			                           XMLNS_VERSION,
 			                           XMLNS_TIME,
@@ -98,7 +98,4 @@
 			                           XMLNS_MUC,
 			                           XMLNS_PING,
-						   XMLNS_SI,
-						   XMLNS_BYTESTREAMS,
-						   XMLNS_FILETRANSFER,
 			                           NULL };
 			const char **f;
@@ -120,5 +117,5 @@
 		{
 			xt_free_node( reply );
-			reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel", NULL );
+			reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" );
 			pack = 0;
 		}
@@ -126,18 +123,16 @@
 	else if( strcmp( type, "set" ) == 0 )
 	{
-		if(  ( c = xt_find_node( node->children, "si" ) ) &&
-		     ( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_SI ) == 0 ) )
-		{
-			return jabber_si_handle_request( ic, node, c );
-		} else if( !( c = xt_find_node( node->children, "query" ) ) ||
+		if( !( c = xt_find_node( node->children, "query" ) ) ||
 		    !( s = xt_find_attr( c, "xmlns" ) ) )
 		{
 			imcb_log( ic, "Warning: Received incomplete IQ-%s packet", type );
 			return XT_HANDLED;
-		} else if( strcmp( s, XMLNS_ROSTER ) == 0 )
-		{
+		}
+		
 		/* This is a roster push. XMPP servers send this when someone
 		   was added to (or removed from) the buddy list. AFAIK they're
 		   sent even if we added this buddy in our own session. */
+		if( strcmp( s, XMLNS_ROSTER ) == 0 )
+		{
 			int bare_len = strlen( ic->acc->user );
 			
@@ -156,15 +151,12 @@
 				
 				xt_free_node( reply );
-				reply = jabber_make_error_packet( node, "not-allowed", "cancel", NULL );
+				reply = jabber_make_error_packet( node, "not-allowed", "cancel" );
 				pack = 0;
 			}
-		} else if( strcmp( s, XMLNS_BYTESTREAMS ) == 0 )
-		{
-		     	/* Bytestream Request (stage 2 of file transfer) */
-			return jabber_bs_recv_request( ic, node, c );
-		} else
+		}
+		else
 		{
 			xt_free_node( reply );
-			reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel", NULL );
+			reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" );
 			pack = 0;
 		}
@@ -601,163 +593,2 @@
 	return st;
 }
-
-xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
-
-xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid )
-{
-	struct xt_node *node, *query;
-	struct jabber_buddy *bud;
-	
-	if( ( bud = jabber_buddy_by_jid( ic, bare_jid , 0 ) ) == NULL )
-	{
-		/* Who cares about the unknown... */
-		imcb_log( ic, "Couldn't find buddy: %s", bare_jid);
-		return 0;
-	}
-	
-	if( bud->features ) /* been here already */
-		return XT_HANDLED;
-	
-	node = xt_new_node( "query", NULL, NULL );
-	xt_add_attr( node, "xmlns", XMLNS_DISCO_INFO );
-	
-	if( !( query = jabber_make_packet( "iq", "get", bare_jid, node ) ) )
-	{
-		imcb_log( ic, "WARNING: Couldn't generate feature query" );
-		xt_free_node( node );
-		return 0;
-	}
-
-	jabber_cache_add( ic, query, jabber_iq_parse_features );
-
-	return jabber_write_packet( ic, query );
-}
-
-xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
-{
-	struct xt_node *c;
-	struct jabber_buddy *bud;
-	char *feature;
-
-	if( !( c = xt_find_node( node->children, "query" ) ) ||
-	    !( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_DISCO_INFO ) == 0 ) )
-	{
-		imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" );
-		return XT_HANDLED;
-	}
-	if( ( bud = jabber_buddy_by_jid( ic, xt_find_attr( node, "from") , 0 ) ) == NULL )
-	{
-		/* Who cares about the unknown... */
-		imcb_log( ic, "Couldn't find buddy: %s", xt_find_attr( node, "from"));
-		return 0;
-	}
-	
-	c = c->children;
-	while( ( c = xt_find_node( c, "feature" ) ) ) {
-		feature = xt_find_attr( c, "var" );
-		bud->features = g_slist_append(bud->features, g_strdup(feature) );
-		c = c->next;
-	}
-
-	return XT_HANDLED;
-}
-
-xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
-
-xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns )
-{
-	struct xt_node *node, *query;
-	struct jabber_data *jd = ic->proto_data;
-	
-	node = xt_new_node( "query", NULL, NULL );
-	xt_add_attr( node, "xmlns", xmlns );
-	
-	if( !( query = jabber_make_packet( "iq", "get", jid, node ) ) )
-	{
-		imcb_log( ic, "WARNING: Couldn't generate server query" );
-		xt_free_node( node );
-	}
-
-	jd->have_streamhosts--;
-	jabber_cache_add( ic, query, jabber_iq_parse_server_features );
-
-	return jabber_write_packet( ic, query );
-}
-
-/*
- * Query the server for "items", query each "item" for identities, query each "item" that's a proxy for it's bytestream info
- */
-xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
-{
-	struct xt_node *c;
-	struct jabber_data *jd = ic->proto_data;
-
-	if( !( c = xt_find_node( node->children, "query" ) ) ||
-	    !xt_find_attr( node, "from" ) )
-	{
-		imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" );
-		return XT_HANDLED;
-	}
-
-	jd->have_streamhosts++;
-
-	if( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_DISCO_ITEMS ) == 0 )
-	{
-		char *item, *itemjid;
-
-		/* answer from server */
-	
-		c = c->children;
-		while( ( c = xt_find_node( c, "item" ) ) )
-		{
-			item = xt_find_attr( c, "name" );
-			itemjid = xt_find_attr( c, "jid" );
-
-			jabber_iq_query_server( ic, itemjid, XMLNS_DISCO_INFO );
-
-			c = c->next;
-		}
-	} else if( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_DISCO_INFO ) == 0 )
-	{
-		char *category, *type;
-
-		/* answer from potential proxy */
-
-		c = c->children;
-		while( ( c = xt_find_node( c, "identity" ) ) )
-		{
-			category = xt_find_attr( c, "category" );
-			type = xt_find_attr( c, "type" );
-
-			if( type && ( strcmp( type, "bytestreams" ) == 0 ) &&
-			    category && ( strcmp( category, "proxy" ) == 0 ) )
-				jabber_iq_query_server( ic, xt_find_attr( node, "from" ), XMLNS_BYTESTREAMS );
-
-			c = c->next;
-		}
-	} else if( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_BYTESTREAMS ) == 0 )
-	{
-		char *host, *jid;
-		int port;
-
-		/* answer from proxy */
-
-		if( ( c = xt_find_node( c->children, "streamhost" ) ) &&
-		    ( host = xt_find_attr( c, "host" ) ) &&
-		    ( port = atoi( xt_find_attr( c, "port" ) ) ) &&
-		    ( jid = xt_find_attr( c, "jid" ) ) )
-		{
-			jabber_streamhost_t *sh = g_new0( jabber_streamhost_t, 1 );
-			sh->jid = g_strdup( jid );
-			sh->host = g_strdup( host );
-			sprintf( sh->port, "%u", port );
-
-			imcb_log( ic, "Proxy found: jid %s host %s port %u", jid, host, port );
-			jd->streamhosts = g_slist_append( jd->streamhosts, sh );
-		}
-	}
-
-	if( jd->have_streamhosts == 0 )
-		jd->have_streamhosts++;
-	return XT_HANDLED;
-}
Index: protocols/jabber/jabber.c
===================================================================
--- protocols/jabber/jabber.c	(revision c821e8ad0d1cf9ab71e6e34c685d0adea2dde923)
+++ protocols/jabber/jabber.c	(revision de8e584d7f4fea214934af094a4df2672d7e0be8)
@@ -530,5 +530,4 @@
 	ret->send_typing = jabber_send_typing;
 	ret->handle_cmp = g_strcasecmp;
-	ret->transfer_request = jabber_si_transfer_request;
 
 	register_protocol( ret );
Index: protocols/jabber/jabber.h
===================================================================
--- protocols/jabber/jabber.h	(revision c821e8ad0d1cf9ab71e6e34c685d0adea2dde923)
+++ protocols/jabber/jabber.h	(revision de8e584d7f4fea214934af094a4df2672d7e0be8)
@@ -59,12 +59,4 @@
 } jabber_buddy_flags_t;
 
-/* Stores a streamhost's(a.k.a. proxy) data */
-typedef struct
-{
-	char *jid;
-	char *host;
-	char port[6];
-} jabber_streamhost_t;
-
 typedef enum
 {
@@ -97,8 +89,4 @@
 	GHashTable *node_cache;
 	GHashTable *buddies;
-
-	GSList *filetransfers;
-	GSList *streamhosts;
-	int have_streamhosts;
 };
 
@@ -130,5 +118,4 @@
 	struct jabber_away_state *away_state;
 	char *away_message;
-	GSList *features;
 	
 	time_t last_act;
@@ -144,34 +131,4 @@
 	char *my_full_jid; /* Separate copy because of case sensitivity. */
 	struct jabber_buddy *me;
-};
-
-struct jabber_transfer
-{
-	/* bitlbee's handle for this transfer */
-	file_transfer_t *ft;
-
-	/* the stream's private handle */
-	gpointer streamhandle;
-
-	/* timeout for discover queries */
-	gint disco_timeout;
-	gint disco_timeout_fired;
-
-	struct im_connection *ic;
-
-	struct jabber_buddy *bud;
-
-	int watch_in;
-	int watch_out;
-
-	char *ini_jid;
-	char *tgt_jid;
-	char *iq_id;
-	char *sid;
-	int accepted;
-
-	size_t bytesread, byteswritten;
-	int fd;
-	struct sockaddr_storage saddr;
 };
 
@@ -205,22 +162,15 @@
 
 /* Some supported extensions/legacy stuff */
-#define XMLNS_AUTH         "jabber:iq:auth"                                      /* XEP-0078 */
-#define XMLNS_VERSION      "jabber:iq:version"                                   /* XEP-0092 */
-#define XMLNS_TIME         "jabber:iq:time"                                      /* XEP-0090 */
-#define XMLNS_PING         "urn:xmpp:ping"                                       /* XEP-0199 */
-#define XMLNS_VCARD        "vcard-temp"                                          /* XEP-0054 */
-#define XMLNS_DELAY        "jabber:x:delay"                                      /* XEP-0091 */
-#define XMLNS_XDATA        "jabber:x:data"                                       /* XEP-0004 */
-#define XMLNS_CHATSTATES   "http://jabber.org/protocol/chatstates"               /* XEP-0085 */
-#define XMLNS_DISCO_INFO   "http://jabber.org/protocol/disco#info"               /* XEP-0030 */
-#define XMLNS_DISCO_ITEMS  "http://jabber.org/protocol/disco#items"              /* XEP-0030 */
-#define XMLNS_MUC          "http://jabber.org/protocol/muc"                      /* XEP-0045 */
-#define XMLNS_MUC_USER     "http://jabber.org/protocol/muc#user"                 /* XEP-0045 */
-#define XMLNS_CAPS         "http://jabber.org/protocol/caps"                     /* XEP-0115 */
-#define XMLNS_FEATURE      "http://jabber.org/protocol/feature-neg"              /* XEP-0020 */
-#define XMLNS_SI           "http://jabber.org/protocol/si"                       /* XEP-0095 */
-#define XMLNS_FILETRANSFER "http://jabber.org/protocol/si/profile/file-transfer" /* XEP-0096 */
-#define XMLNS_BYTESTREAMS  "http://jabber.org/protocol/bytestreams"              /* XEP-0065 */
-#define XMLNS_IBB          "http://jabber.org/protocol/ibb"                      /* XEP-0047 */
+#define XMLNS_AUTH         "jabber:iq:auth"                     /* XEP-0078 */
+#define XMLNS_VERSION      "jabber:iq:version"                  /* XEP-0092 */
+#define XMLNS_TIME         "jabber:iq:time"                     /* XEP-0090 */
+#define XMLNS_PING         "urn:xmpp:ping"                      /* XEP-0199 */
+#define XMLNS_VCARD        "vcard-temp"                         /* XEP-0054 */
+#define XMLNS_DELAY        "jabber:x:delay"                     /* XEP-0091 */
+#define XMLNS_CHATSTATES   "http://jabber.org/protocol/chatstates"  /* 0085 */
+#define XMLNS_DISCOVER     "http://jabber.org/protocol/disco#info"  /* 0030 */
+#define XMLNS_MUC          "http://jabber.org/protocol/muc"     /* XEP-0045 */
+#define XMLNS_MUC_USER     "http://jabber.org/protocol/muc#user"/* XEP-0045 */
+#define XMLNS_CAPS         "http://jabber.org/protocol/caps"    /* XEP-0115 */
 
 /* iq.c */
@@ -232,16 +182,4 @@
 int jabber_add_to_roster( struct im_connection *ic, char *handle, char *name );
 int jabber_remove_from_roster( struct im_connection *ic, char *handle );
-xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid );
-xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns );
-
-/* si.c */
-int jabber_si_handle_request( struct im_connection *ic, struct xt_node *node, struct xt_node *sinode );
-void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who );
-void jabber_si_free_transfer( file_transfer_t *ft);
-
-/* s5bytestream.c */
-int jabber_bs_recv_request( struct im_connection *ic, struct xt_node *node, struct xt_node *qnode);
-gboolean jabber_bs_send_start( struct jabber_transfer *tf );
-gboolean jabber_bs_send_write( file_transfer_t *ft, char *buffer, unsigned int len );
 
 /* message.c */
@@ -257,5 +195,5 @@
 char *set_eval_tls( set_t *set, char *value );
 struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children );
-struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type, char *err_code );
+struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type );
 void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func );
 struct xt_node *jabber_cache_get( struct im_connection *ic, char *id );
Index: protocols/jabber/jabber_util.c
===================================================================
--- protocols/jabber/jabber_util.c	(revision c821e8ad0d1cf9ab71e6e34c685d0adea2dde923)
+++ protocols/jabber/jabber_util.c	(revision de8e584d7f4fea214934af094a4df2672d7e0be8)
@@ -97,5 +97,5 @@
 }
 
-struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type, char *err_code )
+struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type )
 {
 	struct xt_node *node, *c;
@@ -109,8 +109,4 @@
 	c = xt_new_node( "error", NULL, c );
 	xt_add_attr( c, "type", err_type );
-	
-	/* Add the error code, if present */
-	if (err_code)
-		xt_add_attr( c, "code", err_code );
 	
 	/* To make the actual error packet, we copy the original packet and
@@ -295,12 +291,5 @@
 	new = g_new( char, len + 1 );
 	for( i = 0; i < len; i ++ )
-	{
-		/* don't normalize the resource */
-		if( orig[i] == '/' )
-			break;
 		new[i] = tolower( orig[i] );
-	}
-	for( ; i < len; i ++ )
-		new[i] = orig[i];
 	
 	new[i] = 0;
Index: otocols/jabber/s5bytestream.c
===================================================================
--- protocols/jabber/s5bytestream.c	(revision c821e8ad0d1cf9ab71e6e34c685d0adea2dde923)
+++ 	(revision )
@@ -1,1139 +1,0 @@
-/***************************************************************************\
-*                                                                           *
-*  BitlBee - An IRC to IM gateway                                           *
-*  Jabber module - SOCKS5 Bytestreams ( XEP-0065 )                          *
-*                                                                           *
-*  Copyright 2007 Uli Meis <a.sporto+bee@gmail.com>                         *
-*                                                                           *
-*  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.              *
-*                                                                           *
-\***************************************************************************/
-
-#include "jabber.h"
-#include "sha1.h"
-#include <poll.h>
-
-/* Some ifdefs for ulibc (Thanks to Whoopie) */
-#ifndef HOST_NAME_MAX
-#include <sys/param.h>
-#ifdef MAXHOSTNAMELEN
-#define HOST_NAME_MAX MAXHOSTNAMELEN
-#else
-#define HOST_NAME_MAX 255
-#endif
-#endif
-
-struct bs_transfer {
-
-	struct jabber_transfer *tf;
-
-	jabber_streamhost_t *sh;
-	GSList *streamhosts;
-
-	enum 
-	{ 
-		BS_PHASE_CONNECT, 
-		BS_PHASE_CONNECTED, 
-		BS_PHASE_REQUEST, 
-		BS_PHASE_REPLY
-	} phase;
-
-	/* SHA1( SID + Initiator JID + Target JID) */
-	char *pseudoadr;
-
-	gint connect_timeout;
-};
-
-struct socks5_message
-{
-	unsigned char ver;
-	union
-	{
-		unsigned char cmd;
-		unsigned char rep;
-	} cmdrep;
-	unsigned char rsv;
-	unsigned char atyp;
-	unsigned char addrlen;
-	unsigned char address[40];
-	in_port_t port;
-} __attribute__ ((packed)); 
-
-char *socks5_reply_code[] = {
-	"succeeded",
-	"general SOCKS server failure",
-	"connection not allowed by ruleset",
-	"Network unreachable",
-	"Host unreachable",
-	"Connection refused",
-	"TTL expired",
-	"Command not supported",
-	"Address type not supported",
-	"unassigned"};
-
-/* connect() timeout in seconds. */
-#define JABBER_BS_CONTIMEOUT 15
-/* listen timeout */
-#define JABBER_BS_LISTEN_TIMEOUT  90
-
-/* very useful */
-#define ASSERTSOCKOP(op, msg) \
-	if( (op) == -1 ) \
-		return jabber_bs_abort( bt , msg ": %s", strerror( errno ) );
-
-gboolean jabber_bs_abort( struct bs_transfer *bt, char *format, ... );
-void jabber_bs_canceled( file_transfer_t *ft , char *reason );
-void jabber_bs_free_transfer( file_transfer_t *ft );
-gboolean jabber_bs_connect_timeout( gpointer data, gint fd, b_input_condition cond );
-gboolean jabber_bs_poll( struct bs_transfer *bt, int fd, short *revents );
-gboolean jabber_bs_peek( struct bs_transfer *bt, void *buffer, int buflen );
-
-void jabber_bs_recv_answer_request( struct bs_transfer *bt );
-gboolean jabber_bs_recv_read( gpointer data, gint fd, b_input_condition cond );
-gboolean jabber_bs_recv_write_request( file_transfer_t *ft );
-gboolean jabber_bs_recv_handshake( gpointer data, gint fd, b_input_condition cond );
-gboolean jabber_bs_recv_handshake_abort( struct bs_transfer *bt, char *error );
-int jabber_bs_recv_request( struct im_connection *ic, struct xt_node *node, struct xt_node *qnode );
-
-gboolean jabber_bs_send_handshake_abort( struct bs_transfer *bt, char *error );
-gboolean jabber_bs_send_request( struct jabber_transfer *tf, GSList *streamhosts );
-gboolean jabber_bs_send_handshake( gpointer data, gint fd, b_input_condition cond );
-gboolean jabber_bs_send_listen( struct bs_transfer *bt, struct sockaddr_storage *saddr, char *host, char *port );
-static xt_status jabber_bs_send_handle_activate( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
-void jabber_bs_send_activate( struct bs_transfer *bt );
-
-/*
- * Frees a bs_transfer struct and calls the SI free function
- */
-void jabber_bs_free_transfer( file_transfer_t *ft) {
-	struct jabber_transfer *tf = ft->data;
-	struct bs_transfer *bt = tf->streamhandle;
-	jabber_streamhost_t *sh;
-
-	if ( bt->connect_timeout )
-	{
-		b_event_remove( bt->connect_timeout );
-		bt->connect_timeout = 0;
-	}
-
-	if ( tf->watch_in )
-		b_event_remove( tf->watch_in );
-	
-	if( tf->watch_out )
-		b_event_remove( tf->watch_out );
-	
-	g_free( bt->pseudoadr );
-
-	while( bt->streamhosts )
-	{
-		sh = bt->streamhosts->data;
-		bt->streamhosts = g_slist_remove( bt->streamhosts, sh );
-		g_free( sh->jid );
-		g_free( sh->host );
-		g_free( sh );
-	}
-	
-	g_free( bt );
-
-	jabber_si_free_transfer( ft );
-}
-
-/*
- * Checks if buflen data is available on the socket and
- * writes it to buffer if that's the case.
- */
-gboolean jabber_bs_peek( struct bs_transfer *bt, void *buffer, int buflen )
-{
-	int ret;
-	int fd = bt->tf->fd;
-
-	ASSERTSOCKOP( ret = recv( fd, buffer, buflen, MSG_PEEK ), "MSG_PEEK'ing" );
-
-	if( ret == 0 )
-		return jabber_bs_abort( bt, "Remote end closed connection" );
-		
-	if( ret < buflen )
-		return ret;
-
-	ASSERTSOCKOP( ret = recv( fd, buffer, buflen, 0 ), "Dequeuing after MSG_PEEK" );
-
-	if( ret != buflen )
-		return jabber_bs_abort( bt, "recv returned less than previous recv with MSG_PEEK" );
-	
-	return ret;
-}
-
-
-/* 
- * This function is scheduled in bs_handshake via b_timeout_add after a (non-blocking) connect().
- */
-gboolean jabber_bs_connect_timeout( gpointer data, gint fd, b_input_condition cond )
-{
-	struct bs_transfer *bt = data;
-
-	bt->connect_timeout = 0;
-
-	jabber_bs_abort( bt, "no connection after %d seconds", bt->tf->ft->sending ? JABBER_BS_LISTEN_TIMEOUT : JABBER_BS_CONTIMEOUT );
-
-	return FALSE;
-}
-
-/* 
- * Polls the socket, checks for errors and removes a connect timer
- * if there is one.
- */
-gboolean jabber_bs_poll( struct bs_transfer *bt, int fd, short *revents )
-{
-	struct pollfd pfd = { .fd = fd, .events = POLLHUP|POLLERR };
-	
-	if ( bt->connect_timeout )
-	{
-		b_event_remove( bt->connect_timeout );
-		bt->connect_timeout = 0;
-	}
-
-	ASSERTSOCKOP( poll( &pfd, 1, 0 ), "poll()" )
-
-	if( pfd.revents & POLLERR )
-	{
-		int sockerror;
-		socklen_t errlen = sizeof( sockerror );
-
-		if ( getsockopt( fd, SOL_SOCKET, SO_ERROR, &sockerror, &errlen ) )
-			return jabber_bs_abort( bt, "getsockopt() failed, unknown socket error during SOCKS5 handshake (weird!)" );
-
-		if ( bt->phase == BS_PHASE_CONNECTED )
-			return jabber_bs_abort( bt, "connect failed: %s", strerror( sockerror ) );
-
-		return jabber_bs_abort( bt, "Socket error during SOCKS5 handshake(weird!): %s", strerror( sockerror ) );
-	}
-
-	if( pfd.revents & POLLHUP )
-		return jabber_bs_abort( bt, "Remote end closed connection" );
-	
-	*revents = pfd.revents;
-	
-	return TRUE;
-}
-
-/*
- * Used for receive and send path.
- */
-gboolean jabber_bs_abort( struct bs_transfer *bt, char *format, ... )
-{
-	va_list params;
-	va_start( params, format );
-	char error[128];
-
-	if( vsnprintf( error, 128, format, params ) < 0 )
-		sprintf( error, "internal error parsing error string (BUG)" );
-	va_end( params );
-	if( bt->tf->ft->sending )
-		return jabber_bs_send_handshake_abort( bt, error );
-	else
-		return jabber_bs_recv_handshake_abort( bt, error );
-}
-
-/* Bad luck */
-void jabber_bs_canceled( file_transfer_t *ft , char *reason )
-{
-	struct jabber_transfer *tf = ft->data;
-
-	imcb_log( tf->ic, "File transfer aborted: %s", reason );
-}
-
-/*
- * Parses an incoming bytestream request and calls jabber_bs_handshake on success.
- */
-int jabber_bs_recv_request( struct im_connection *ic, struct xt_node *node, struct xt_node *qnode)
-{
-	char *sid, *ini_jid, *tgt_jid, *mode, *iq_id;
-	struct jabber_data *jd = ic->proto_data;
-	struct jabber_transfer *tf = NULL;
-	GSList *tflist;
-	struct bs_transfer *bt;
-	GSList *shlist=NULL;
-	struct xt_node *shnode;
-
-	sha1_state_t sha;
-	char hash_hex[41];
-	unsigned char hash[20];
-	int i;
-	
-	if( !(iq_id   = xt_find_attr( node, "id" ) ) ||
-	    !(ini_jid = xt_find_attr( node, "from" ) ) ||
-	    !(tgt_jid = xt_find_attr( node, "to" ) ) ||
-	    !(sid     = xt_find_attr( qnode, "sid" ) ) )
-	{
-		imcb_log( ic, "WARNING: Received incomplete SI bytestream request");
-		return XT_HANDLED;
-	}
-
-	if( ( mode = xt_find_attr( qnode, "mode" ) ) &&
-	      ( strcmp( mode, "tcp" ) != 0 ) ) 
-	{
-		imcb_log( ic, "WARNING: Received SI Request for unsupported bytestream mode %s", xt_find_attr( qnode, "mode" ) );
-		return XT_HANDLED;
-	}
-
-	shnode = qnode->children;
-	while( ( shnode = xt_find_node( shnode, "streamhost" ) ) )
-	{
-		char *jid, *host;
-		int port;
-		if( ( jid = xt_find_attr( shnode, "jid" ) ) &&
-		    ( host = xt_find_attr( shnode, "host" ) ) &&
-		    ( ( port = atoi( xt_find_attr( shnode, "port" ) ) ) ) )
-		{
-			jabber_streamhost_t *sh = g_new0( jabber_streamhost_t, 1 );
-			sh->jid = g_strdup(jid);
-			sh->host = g_strdup(host);
-			sprintf( sh->port, "%u", port );
-			shlist = g_slist_append( shlist, sh );
-		}
-		shnode = shnode->next;
-	}
-	
-	if( !shlist )
-	{
-		imcb_log( ic, "WARNING: Received incomplete SI bytestream request, no parseable streamhost entries");
-		return XT_HANDLED;
-	}
-
-	/* Let's see if we can find out what this bytestream should be for... */
-
-	for( tflist = jd->filetransfers ; tflist; tflist = g_slist_next(tflist) )
-	{
-		struct jabber_transfer *tft = tflist->data;
-		if( ( strcmp( tft->sid, sid ) == 0 ) &&
-		    ( strcmp( tft->ini_jid, ini_jid ) == 0 ) &&
-		    ( strcmp( tft->tgt_jid, tgt_jid ) == 0 ) )
-		{
-		    	tf = tft;
-			break;
-		}
-	}
-
-	if (!tf) 
-	{
-		imcb_log( ic, "WARNING: Received bytestream request from %s that doesn't match an SI request", ini_jid );
-		return XT_HANDLED;
-	}
-
-	/* iq_id and canceled can be reused since SI is done */
-	g_free( tf->iq_id );
-	tf->iq_id = g_strdup( iq_id );
-
-	tf->ft->canceled = jabber_bs_canceled;
-
-	/* SHA1( SID + Initiator JID + Target JID ) is given to the streamhost which it will match against the initiator's value */
-	sha1_init( &sha );
-	sha1_append( &sha, (unsigned char*) sid, strlen( sid ) );
-	sha1_append( &sha, (unsigned char*) ini_jid, strlen( ini_jid ) );
-	sha1_append( &sha, (unsigned char*) tgt_jid, strlen( tgt_jid ) );
-	sha1_finish( &sha, hash );
-	
-	for( i = 0; i < 20; i ++ )
-		sprintf( hash_hex + i * 2, "%02x", hash[i] );
-		
-	bt = g_new0( struct bs_transfer, 1 );
-	bt->tf = tf;
-	bt->streamhosts = shlist;
-	bt->sh = shlist->data;
-	bt->phase = BS_PHASE_CONNECT;
-	bt->pseudoadr = g_strdup( hash_hex );
-	tf->streamhandle = bt;
-	tf->ft->free = jabber_bs_free_transfer;
-
-	jabber_bs_recv_handshake( bt, 0, 0 ); 
-
-	return XT_HANDLED;
-}
-
-/*
- * This is what a protocol handshake can look like in cooperative multitasking :)
- * Might be confusing at first because it's called from different places and is recursing.
- * (places being the event thread, bs_request, bs_handshake_abort, and itself)
- *
- * All in all, it turned out quite nice :)
- */
-gboolean jabber_bs_recv_handshake( gpointer data, gint fd, b_input_condition cond )
-{
-
-	struct bs_transfer *bt = data;
-	short revents;
-	int gret;
-
-	if ( ( fd != 0 ) && !jabber_bs_poll( bt, fd, &revents ) )
-		return FALSE;
-	
-	switch( bt->phase ) 
-	{
-	case BS_PHASE_CONNECT:
-		{
-			struct addrinfo hints, *rp;
-
-			memset( &hints, 0, sizeof( struct addrinfo ) );
-			hints.ai_socktype = SOCK_STREAM;
-
-			if ( ( gret = getaddrinfo( bt->sh->host, bt->sh->port, &hints, &rp ) ) != 0 )
-				return jabber_bs_abort( bt, "getaddrinfo() failed: %s", gai_strerror( gret ) );
-
-			ASSERTSOCKOP( bt->tf->fd = fd = socket( rp->ai_family, rp->ai_socktype, 0 ), "Opening socket" );
-
-			sock_make_nonblocking( fd );
-
-			imcb_log( bt->tf->ic, "File %s: Connecting to streamhost %s:%s", bt->tf->ft->file_name, bt->sh->host, bt->sh->port );
-
-			if( ( connect( fd, rp->ai_addr, rp->ai_addrlen ) == -1 ) &&
-			    ( errno != EINPROGRESS ) )
-				return jabber_bs_abort( bt , "connect() failed: %s", strerror( errno ) );
-
-			freeaddrinfo( rp );
-
-			bt->phase = BS_PHASE_CONNECTED;
-			
-			bt->tf->watch_out = b_input_add( fd, GAIM_INPUT_WRITE, jabber_bs_recv_handshake, bt );
-
-			/* since it takes forever(3mins?) till connect() fails on itself we schedule a timeout */
-			bt->connect_timeout = b_timeout_add( JABBER_BS_CONTIMEOUT * 1000, jabber_bs_connect_timeout, bt );
-
-			bt->tf->watch_in = 0;
-			return FALSE;
-		}
-	case BS_PHASE_CONNECTED:
-		{
-			struct {
-				unsigned char ver;
-				unsigned char nmethods;
-				unsigned char method;
-			} socks5_hello = {
-				.ver = 5,
-				.nmethods = 1,
-				.method = 0x00 /* no auth */
-				/* one could also implement username/password. If you know
-				 * a jabber client or proxy that actually does it, tell me.
-				 */
-			};
-			
-			ASSERTSOCKOP( send( fd, &socks5_hello, sizeof( socks5_hello ) , 0 ), "Sending auth request" );
-
-			bt->phase = BS_PHASE_REQUEST;
-
-			bt->tf->watch_in = b_input_add( fd, GAIM_INPUT_READ, jabber_bs_recv_handshake, bt );
-
-			bt->tf->watch_out = 0;
-			return FALSE;
-		}
-	case BS_PHASE_REQUEST:
-		{
-			struct socks5_message socks5_connect = 
-			{
-				.ver = 5,
-				.cmdrep.cmd = 0x01,
-				.rsv = 0,
-				.atyp = 0x03,
-				.addrlen = strlen( bt->pseudoadr ),
-				.port = 0
-			};
-			int ret;
-			char buf[2];
-
-			/* If someone's trying to be funny and sends only one byte at a time we'll fail :) */
-			ASSERTSOCKOP( ret = recv( fd, buf, 2, 0 ) , "Receiving auth reply" );
-
-			if( !( ret == 2 ) ||
-			    !( buf[0] == 5 ) ||
-			    !( buf[1] == 0 ) )
-				return jabber_bs_abort( bt, "Auth not accepted by streamhost (reply: len=%d, ver=%d, status=%d)",
-									ret, buf[0], buf[1] );
-
-			/* copy hash into connect message */
-			memcpy( socks5_connect.address, bt->pseudoadr, socks5_connect.addrlen );
-
-			ASSERTSOCKOP( send( fd, &socks5_connect, sizeof( struct socks5_message ), 0 ) , "Sending SOCKS5 Connect" );
-
-			bt->phase = BS_PHASE_REPLY;
-
-			return TRUE;
-		}
-	case BS_PHASE_REPLY:
-		{
-			struct socks5_message socks5_reply;
-			int ret;
-
-			if ( !( ret = jabber_bs_peek( bt, &socks5_reply, sizeof( struct socks5_message ) ) ) )
-				return FALSE;
-
-			if ( ret < 5 ) /* header up to address length */
-				return TRUE;
-			else if( ret < sizeof( struct socks5_message ) )
-			{
-				/* Either a buggy proxy or just one that doesnt regard the SHOULD in XEP-0065
-				 * saying the reply SHOULD contain the address */
-
-				ASSERTSOCKOP( ret = recv( fd, &socks5_reply, ret, 0 ), "Dequeuing after MSG_PEEK" );
-			}
-
-			if( !( socks5_reply.ver == 5 ) ||
-			    !( socks5_reply.cmdrep.rep == 0 ) ) {
-			    	char errstr[128] = "";
-				if( ( socks5_reply.ver == 5 ) && ( socks5_reply.cmdrep.rep < 
-				    ( sizeof( socks5_reply_code ) / sizeof( socks5_reply_code[0] ) ) ) ) {
-					sprintf( errstr, "with \"%s\" ", socks5_reply_code[ socks5_reply.cmdrep.rep ] );
-				}
-				return jabber_bs_abort( bt, "SOCKS5 CONNECT failed %s(reply: ver=%d, rep=%d, atyp=%d, addrlen=%d)", 
-					errstr,
-					socks5_reply.ver,
-					socks5_reply.cmdrep.rep,
-					socks5_reply.atyp,
-					socks5_reply.addrlen);
-			}
-			
-			/* usually a proxy sends back the 40 bytes address but I encountered at least one (of jabber.cz) 
-			 * that sends atyp=0 addrlen=0 and only 6 bytes (one less than one would expect).
-			 * Therefore I removed the wait for more bytes. Since we don't care about what else the proxy
-			 * is sending, it shouldnt matter */
-
-			if( bt->tf->ft->sending )
-				jabber_bs_send_activate( bt );
-			else
-				jabber_bs_recv_answer_request( bt );
-
-			return FALSE;
-		}
-	default:
-		/* BUG */
-		imcb_log( bt->tf->ic, "BUG in file transfer code: undefined handshake phase" );
-
-		bt->tf->watch_in = 0;
-		return FALSE;
-	}
-}
-
-/*
- * If the handshake failed we can try the next streamhost, if there is one.
- * An intelligent sender would probably specify himself as the first streamhost and
- * a proxy as the second (Kopete and PSI are examples here). That way, a (potentially) 
- * slow proxy is only used if neccessary. This of course also means, that the timeout
- * per streamhost should be kept short. If one or two firewalled adresses are specified,
- * they have to timeout first before a proxy is tried.
- */
-gboolean jabber_bs_recv_handshake_abort( struct bs_transfer *bt, char *error )
-{
-	struct jabber_transfer *tf = bt->tf;
-	struct xt_node *reply, *iqnode;
-	GSList *shlist;
-
-	imcb_log( tf->ic, "Transferring file %s: connection to streamhost %s:%s failed (%s)", 
-		  tf->ft->file_name, 
-		  bt->sh->host,
-		  bt->sh->port,
-		  error );
-
-	/* Alright, this streamhost failed, let's try the next... */
-	bt->phase = BS_PHASE_CONNECT;
-	shlist = g_slist_find( bt->streamhosts, bt->sh );
-	if( shlist && shlist->next )
-	{
-		bt->sh = shlist->next->data;
-		return jabber_bs_recv_handshake( bt, 0, 0 );
-	}
-
-
-	/* out of stream hosts */
-
-	iqnode = jabber_make_packet( "iq", "result", tf->ini_jid, NULL );
-	reply = jabber_make_error_packet( iqnode, "item-not-found", "cancel" , "404" );
-	xt_free_node( iqnode );
-
-	xt_add_attr( reply, "id", tf->iq_id );
-		
-	if( !jabber_write_packet( tf->ic, reply ) )
-		imcb_log( tf->ic, "WARNING: Error transmitting bytestream response" );
-	xt_free_node( reply );
-
-	imcb_file_canceled( tf->ft, "couldn't connect to any streamhosts" );
-
-	bt->tf->watch_in = 0;
-	return FALSE;
-}
-
-/* 
- * After the SOCKS5 handshake succeeds we need to inform the initiator which streamhost we chose.
- * If he is the streamhost himself, he might already know that. However, if it's a proxy,
- * the initiator will have to make a connection himself.
- */
-void jabber_bs_recv_answer_request( struct bs_transfer *bt )
-{
-	struct jabber_transfer *tf = bt->tf;
-	struct xt_node *reply;
-
-	imcb_log( tf->ic, "File %s: established SOCKS5 connection to %s:%s", 
-		  tf->ft->file_name, 
-		  bt->sh->host,
-		  bt->sh->port );
-
-	tf->ft->data = tf;
-	tf->watch_in = b_input_add( tf->fd, GAIM_INPUT_READ, jabber_bs_recv_read, bt );
-	tf->ft->write_request = jabber_bs_recv_write_request;
-
-	reply = xt_new_node( "streamhost-used", NULL, NULL );
-	xt_add_attr( reply, "jid", bt->sh->jid );
-
-	reply = xt_new_node( "query", NULL, reply );
-	xt_add_attr( reply, "xmlns", XMLNS_BYTESTREAMS );
-
-	reply = jabber_make_packet( "iq", "result", tf->ini_jid, reply );
-
-	xt_add_attr( reply, "id", tf->iq_id );
-		
-	if( !jabber_write_packet( tf->ic, reply ) )
-		imcb_file_canceled( tf->ft, "Error transmitting bytestream response" );
-	xt_free_node( reply );
-}
-
-/* 
- * This function is called from write_request directly. If no data is available, it will install itself
- * as a watcher for input on fd and once that happens, deliver the data and unschedule itself again.
- */
-gboolean jabber_bs_recv_read( gpointer data, gint fd, b_input_condition cond )
-{
-	int ret;
-	struct bs_transfer *bt = data;
-	struct jabber_transfer *tf = bt->tf;
-
-	if( fd != 0 ) /* called via event thread */
-	{
-		tf->watch_in = 0;
-		ASSERTSOCKOP( ret = recv( fd, tf->ft->buffer, sizeof( tf->ft->buffer ), 0 ) , "Receiving" );
-	}
-	else
-	{
-		/* called directly. There might not be any data available. */
-		if( ( ( ret = recv( tf->fd, tf->ft->buffer, sizeof( tf->ft->buffer ), 0 ) ) == -1 ) &&
-		    ( errno != EAGAIN ) )
-		    return jabber_bs_abort( bt, "Receiving: %s", strerror( errno ) );
-
-		if( ( ret == -1 ) && ( errno == EAGAIN ) )
-		{
-			tf->watch_in = b_input_add( tf->fd, GAIM_INPUT_READ, jabber_bs_recv_read, bt );
-			return FALSE;
-		}
-	}
-
-	/* shouldn't happen since we know the file size */
-	if( ret == 0 )
-		return jabber_bs_abort( bt, "Remote end closed connection" );
-	
-	if( tf->bytesread == 0 )
-		tf->ft->started = time( NULL );
-
-	tf->bytesread += ret;
-
-	tf->ft->write( tf->ft, tf->ft->buffer, ret );	
-
-	return FALSE;
-}
-
-/* 
- * imc callback that is invoked when it is ready to receive some data.
- */
-gboolean jabber_bs_recv_write_request( file_transfer_t *ft )
-{
-	struct jabber_transfer *tf = ft->data;
-
-	if( tf->watch_in )
-	{
-		imcb_file_canceled( ft, "BUG in jabber file transfer: write_request called when already watching for input" );
-		return FALSE;
-	}
-	
-	jabber_bs_recv_read( tf->streamhandle, 0 , 0 );
-
-	return TRUE;
-}
-
-/* 
- * Issues a write_request to imc.
- * */
-gboolean jabber_bs_send_can_write( gpointer data, gint fd, b_input_condition cond )
-{
-	struct bs_transfer *bt = data;
-
-	bt->tf->watch_out = 0;
-
-	bt->tf->ft->write_request( bt->tf->ft );
-
-	return FALSE;
-}
-
-/*
- * This should only be called if we can write, so just do it.
- * Add a write watch so we can write more during the next cycle (if possible).
- */
-gboolean jabber_bs_send_write( file_transfer_t *ft, char *buffer, unsigned int len )
-{
-	struct jabber_transfer *tf = ft->data;
-	struct bs_transfer *bt = tf->streamhandle;
-	int ret;
-
-	if( tf->watch_out )
-		return jabber_bs_abort( bt, "BUG: write() called while watching " );
-	
-	/* TODO: catch broken pipe */
-	ASSERTSOCKOP( ret = send( tf->fd, buffer, len, 0 ), "Sending" );
-
-	if( tf->byteswritten == 0 )
-		tf->ft->started = time( NULL );
-
-	tf->byteswritten += ret;
-	
-	/* TODO: this should really not be fatal */
-	if( ret < len )
-		return jabber_bs_abort( bt, "send() sent %d instead of %d (send buffer too big!)", ret, len );
-
-	bt->tf->watch_out = b_input_add( tf->fd, GAIM_INPUT_WRITE, jabber_bs_send_can_write, bt );
-		
-	return TRUE;
-}
-
-/*
- * Handles the reply by the receiver containing the used streamhost.
- */
-static xt_status jabber_bs_send_handle_reply(struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) {
-	struct jabber_transfer *tf = NULL;
-	struct jabber_data *jd = ic->proto_data;
-	struct bs_transfer *bt;
-	GSList *tflist;
-	struct xt_node *c;
-	char *sid, *jid;
-
-	if( !( c = xt_find_node( node->children, "query" ) ) ||
-	    !( c = xt_find_node( c->children, "streamhost-used" ) ) ||
-	    !( jid = xt_find_attr( c, "jid" ) ) )
-
-	{
-		imcb_log( ic, "WARNING: Received incomplete bytestream reply" );
-		return XT_HANDLED;
-	}
-	
-	if( !( c = xt_find_node( orig->children, "query" ) ) ||
-	    !( sid = xt_find_attr( c, "sid" ) ) )
-	{
-		imcb_log( ic, "WARNING: Error parsing request corresponding to the incoming bytestream reply" );
-		return XT_HANDLED;
-	}
-
-	/* Let's see if we can find out what this bytestream should be for... */
-
-	for( tflist = jd->filetransfers ; tflist; tflist = g_slist_next(tflist) )
-	{
-		struct jabber_transfer *tft = tflist->data;
-		if( ( strcmp( tft->sid, sid ) == 0 ) )
-		{
-		    	tf = tft;
-			break;
-		}
-	}
-
-	if( !tf )
-	{
-		imcb_log( ic, "WARNING: Received SOCKS5 bytestream reply to unknown request" );
-		return XT_HANDLED;
-	}
-
-	bt = tf->streamhandle;
-
-	tf->accepted = TRUE;
-
-	if( strcmp( jid, tf->ini_jid ) == 0 )
-	{
-		/* we're streamhost and target */
-		if( bt->phase == BS_PHASE_REPLY )
-		{
-			/* handshake went through, let's start transferring */
-			tf->ft->write_request( tf->ft );
-		}
-	} else
-	{
-		/* using a proxy, abort listen */
-
-		if ( tf->watch_in )
-		{
-			b_event_remove( tf->watch_in );
-			tf->watch_in = 0;
-		}
-		
-		closesocket( tf->fd );
-		tf->fd = 0;
-
-		if ( bt->connect_timeout )
-		{
-			b_event_remove( bt->connect_timeout );
-			bt->connect_timeout = 0;
-		}
-
-		GSList *shlist;
-		for( shlist = jd->streamhosts ; shlist ; shlist = g_slist_next( shlist ) )
-		{
-			jabber_streamhost_t *sh = shlist->data;
-			if( strcmp( sh->jid, jid ) == 0 )
-			{
-				bt->sh = sh;
-				jabber_bs_recv_handshake( bt, 0, 0 );
-				return XT_HANDLED;
-			}
-		}
-
-		imcb_log( ic, "WARNING: Received SOCKS5 bytestream reply with unknown streamhost %s", jid );
-	}
-
-	return XT_HANDLED;
-}
-
-/* 
- * Tell the proxy to activate the stream. Looks like this:
- *
- * <iq type=set>
- * 	<query xmlns=bs sid=sid>
- * 		<activate>tgt_jid</activate>
- * 	</query>
- * </iq>
- */
-void jabber_bs_send_activate( struct bs_transfer *bt )
-{
-	struct xt_node *node;
-
-	node = xt_new_node( "activate", bt->tf->tgt_jid, NULL );
-	node = xt_new_node( "query", NULL, node );
-	xt_add_attr( node, "xmlns", XMLNS_BYTESTREAMS );
-	xt_add_attr( node, "sid", bt->tf->sid );
-	node = jabber_make_packet( "iq", "set", bt->sh->jid, node );
-
-	jabber_cache_add( bt->tf->ic, node, jabber_bs_send_handle_activate );
-
-	jabber_write_packet( bt->tf->ic, node );
-}
-
-/*
- * The proxy has activated the bytestream.
- * We can finally start pushing some data out.
- */
-static xt_status jabber_bs_send_handle_activate( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
-{
-	char *sid;
-	GSList *tflist;
-	struct jabber_transfer *tf;
-	struct xt_node *query;
-	struct jabber_data *jd = ic->proto_data;
-
-	query = xt_find_node( orig->children, "query" );
-	sid = xt_find_attr( query, "sid" );
-
-	for( tflist = jd->filetransfers ; tflist; tflist = g_slist_next(tflist) )
-	{
-		struct jabber_transfer *tft = tflist->data;
-		if( ( strcmp( tft->sid, sid ) == 0 ) )
-		{
-		    	tf = tft;
-			break;
-		}
-	}
-
-	if( !tf )
-	{
-		imcb_log( ic, "WARNING: Received SOCKS5 bytestream activation for unknown stream" );
-		return XT_HANDLED;
-	}
-
-	imcb_log( tf->ic, "File %s: SOCKS5 handshake and activation successful! Transfer about to start...", tf->ft->file_name );
-
-	/* handshake went through, let's start transferring */
-	tf->ft->write_request( tf->ft );
-
-	return XT_HANDLED;
-}
-
-/*
- * Starts a bytestream.
- */
-gboolean jabber_bs_send_start( struct jabber_transfer *tf )
-{
-	char host[INET6_ADDRSTRLEN];
-	struct bs_transfer *bt;
-	sha1_state_t sha;
-	char hash_hex[41];
-	unsigned char hash[20];
-	int i,ret;
-	struct jabber_data *jd = tf->ic->proto_data;
-	jabber_streamhost_t sh;
-	GSList *streamhosts = jd->streamhosts;
-
-	/* SHA1( SID + Initiator JID + Target JID ) is given to the streamhost which it will match against the initiator's value */
-	sha1_init( &sha );
-	sha1_append( &sha, (unsigned char*) tf->sid, strlen( tf->sid ) );
-	sha1_append( &sha, (unsigned char*) tf->ini_jid, strlen( tf->ini_jid ) );
-	sha1_append( &sha, (unsigned char*) tf->tgt_jid, strlen( tf->tgt_jid ) );
-	sha1_finish( &sha, hash );
-	
-	for( i = 0; i < 20; i ++ )
-		sprintf( hash_hex + i * 2, "%02x", hash[i] );
-		
-	bt = g_new0( struct bs_transfer, 1 );
-	bt->tf = tf;
-	bt->phase = BS_PHASE_CONNECT;
-	bt->pseudoadr = g_strdup( hash_hex );
-	tf->streamhandle = bt;
-	tf->ft->free = jabber_bs_free_transfer;
-	tf->ft->canceled = jabber_bs_canceled;
-
-	if ( !jabber_bs_send_listen( bt, &tf->saddr, sh.host = host, sh.port ) )
-		return FALSE;
-
-	bt->tf->watch_in = b_input_add( tf->fd, GAIM_INPUT_READ, jabber_bs_send_handshake, bt );
-	bt->connect_timeout = b_timeout_add( JABBER_BS_LISTEN_TIMEOUT * 1000, jabber_bs_connect_timeout, bt );
-
-	sh.jid = tf->ini_jid;
-
-	/* temporarily add listen address to streamhosts, send the request and remove it */
-	streamhosts = g_slist_prepend( streamhosts, &sh );
-	ret = jabber_bs_send_request( tf, streamhosts);
-	streamhosts = g_slist_remove( streamhosts, &sh );
-
-	return ret;
-}
-
-gboolean jabber_bs_send_request( struct jabber_transfer *tf, GSList *streamhosts )
-{
-	struct xt_node *shnode, *query, *iq;
-
-	query = xt_new_node( "query", NULL, NULL );
-	xt_add_attr( query, "xmlns", XMLNS_BYTESTREAMS );
-	xt_add_attr( query, "sid", tf->sid );
-	xt_add_attr( query, "mode", "tcp" );
-
-	while( streamhosts ) {
-		jabber_streamhost_t *sh = streamhosts->data;
-		shnode = xt_new_node( "streamhost", NULL, NULL );
-		xt_add_attr( shnode, "jid", sh->jid );
-		xt_add_attr( shnode, "host", sh->host );
-		xt_add_attr( shnode, "port", sh->port );
-
-		xt_add_child( query, shnode );
-
-		streamhosts = g_slist_next( streamhosts );
-	}
-
-
-	iq = jabber_make_packet( "iq", "set", tf->tgt_jid, query );
-	xt_add_attr( iq, "from", tf->ini_jid );
-
-	jabber_cache_add( tf->ic, iq, jabber_bs_send_handle_reply );
-
-	if( !jabber_write_packet( tf->ic, iq ) )
-		imcb_file_canceled( tf->ft, "Error transmitting bytestream request" );
-	return TRUE;
-}
-
-gboolean jabber_bs_send_handshake_abort(struct bs_transfer *bt, char *error )
-{
-	struct jabber_transfer *tf = bt->tf;
-	struct jabber_data *jd = tf->ic->proto_data;
-
-	/* TODO: did the receiver get here somehow??? */
-	imcb_log( tf->ic, "Transferring file %s: SOCKS5 handshake failed: %s", 
-		  tf->ft->file_name, 
-		  error );
-
-	if( jd->streamhosts==NULL ) /* we're done here unless we have a proxy to try */
-		imcb_file_canceled( tf->ft, error );
-
-	return FALSE;
-}
-
-/*
- * Creates a listening socket and returns it in saddr_ptr.
- */
-gboolean jabber_bs_send_listen( struct bs_transfer *bt, struct sockaddr_storage *saddr, char *host, char *port )
-{
-	struct jabber_transfer *tf = bt->tf;
-	int fd,gret;
-	char hostname[ HOST_NAME_MAX + 1 ];
-	struct addrinfo hints, *rp;
-	socklen_t ssize = sizeof( struct sockaddr_storage );
-
-	/* won't be long till someone asks for this to be configurable :) */
-
-	ASSERTSOCKOP( gethostname( hostname, sizeof( hostname ) ), "gethostname()" );
-
-	memset( &hints, 0, sizeof( struct addrinfo ) );
-	hints.ai_socktype = SOCK_STREAM;
-	hints.ai_flags = AI_NUMERICSERV;
-
-	if ( ( gret = getaddrinfo( hostname, "0", &hints, &rp ) ) != 0 )
-		return jabber_bs_abort( bt, "getaddrinfo() failed: %s", gai_strerror( gret ) );
-
-	memcpy( saddr, rp->ai_addr, rp->ai_addrlen );
-
-	ASSERTSOCKOP( fd = tf->fd = socket( saddr->ss_family, SOCK_STREAM, 0 ), "Opening socket" );
-
-	ASSERTSOCKOP( bind( fd, ( struct sockaddr *)saddr, rp->ai_addrlen ), "Binding socket" );
-	
-	freeaddrinfo( rp );
-
-	ASSERTSOCKOP( listen( fd, 1 ), "Making socket listen" );
-
-	if ( !inet_ntop( saddr->ss_family, saddr->ss_family == AF_INET ?
-			( void * )&( ( struct sockaddr_in * ) saddr )->sin_addr.s_addr : ( void * )&( ( struct sockaddr_in6 * ) saddr )->sin6_addr.s6_addr
-			, host, INET6_ADDRSTRLEN ) )
-		return jabber_bs_abort( bt, "inet_ntop failed on listening socket" );
-
-	ASSERTSOCKOP( getsockname( fd, ( struct sockaddr *)saddr, &ssize ), "Getting socket name" );
-
-	if( saddr->ss_family == AF_INET )
-		sprintf( port, "%d", ntohs( ( ( struct sockaddr_in *) saddr )->sin_port ) );
-	else
-		sprintf( port, "%d", ntohs( ( ( struct sockaddr_in6 *) saddr )->sin6_port ) );
-
-	return TRUE;
-}
-
-/*
- * SOCKS5BYTESTREAM protocol for the sender
- */
-gboolean jabber_bs_send_handshake( gpointer data, gint fd, b_input_condition cond )
-{
-	struct bs_transfer *bt = data;
-	struct jabber_transfer *tf = bt->tf;
-	short revents;
-
-	if ( !jabber_bs_poll( bt, fd, &revents ) )
-		return FALSE;
-	
-	switch( bt->phase ) 
-	{
-	case BS_PHASE_CONNECT:
-		{
-			struct sockaddr_storage clt_addr;
-			socklen_t ssize = sizeof( clt_addr );
-			
-			/* Connect */
-
-			ASSERTSOCKOP( tf->fd = accept( fd, (struct sockaddr *) &clt_addr, &ssize ), "Accepting connection" );
-
-			closesocket( fd );
-			fd = tf->fd;
-			sock_make_nonblocking( fd );
-			
-			bt->phase = BS_PHASE_CONNECTED;
-
-			bt->tf->watch_in = b_input_add( fd, GAIM_INPUT_READ, jabber_bs_send_handshake, bt );
-			return FALSE;
-		}
-	case BS_PHASE_CONNECTED:
-		{
-			int ret, have_noauth=FALSE;
-			struct {
-				unsigned char ver;
-				unsigned char method;
-			} socks5_auth_reply = { .ver = 5, .method = 0 };
-			struct {
-				unsigned char ver;
-				unsigned char nmethods;
-				unsigned char method;
-			} socks5_hello;
-
-			if( !( ret = jabber_bs_peek( bt, &socks5_hello, sizeof( socks5_hello ) ) ) )
-				return FALSE;
-
-			if( ret < sizeof( socks5_hello ) )
-				return TRUE;
-
-			if( !( socks5_hello.ver == 5 ) ||
-			    !( socks5_hello.nmethods >= 1 ) ||
-			    !( socks5_hello.nmethods < 32 ) )
-				return jabber_bs_abort( bt, "Invalid auth request ver=%d nmethods=%d method=%d", socks5_hello.ver, socks5_hello.nmethods, socks5_hello.method );
-
-			have_noauth = socks5_hello.method == 0;
-
-			if( socks5_hello.nmethods > 1 )
-			{
-				char mbuf[32];
-				int i;
-				ASSERTSOCKOP( ret = recv( fd, mbuf, socks5_hello.nmethods - 1, 0 ) , "Receiving auth methods" );
-				if( ret < ( socks5_hello.nmethods - 1 ) )
-					return jabber_bs_abort( bt, "Partial auth request");
-				for( i = 0 ; !have_noauth && ( i < socks5_hello.nmethods - 1 ) ; i ++ )
-					if( mbuf[i] == 0 )
-						have_noauth = TRUE;
-			}
-			
-			if( !have_noauth )
-				return jabber_bs_abort( bt, "Auth request didn't include no authentication" );
-
-			ASSERTSOCKOP( send( fd, &socks5_auth_reply, sizeof( socks5_auth_reply ) , 0 ), "Sending auth reply" );
-
-			bt->phase = BS_PHASE_REQUEST;
-
-			return TRUE;
-		}
-	case BS_PHASE_REQUEST:
-		{
-			struct socks5_message socks5_connect;
-			int msgsize = sizeof( struct socks5_message );
-			int ret;
-
-			if( !( ret = jabber_bs_peek( bt, &socks5_connect, msgsize ) ) )
-				return FALSE;
-
-			if( ret < msgsize )
-				return TRUE;
-
-			if( !( socks5_connect.ver == 5) ||
-			    !( socks5_connect.cmdrep.cmd == 1 ) ||
-			    !( socks5_connect.atyp == 3 ) ||
-			    !(socks5_connect.addrlen == 40 ) )
-				return jabber_bs_abort( bt, "Invalid SOCKS5 Connect message (addrlen=%d, ver=%d, cmd=%d, atyp=%d)", socks5_connect.addrlen, socks5_connect.ver, socks5_connect.cmdrep.cmd, socks5_connect.atyp );
-			if( !( memcmp( socks5_connect.address, bt->pseudoadr, 40 ) == 0 ) )
-				return jabber_bs_abort( bt, "SOCKS5 Connect message contained wrong digest");
-
-			socks5_connect.cmdrep.rep = 0;
-
-			ASSERTSOCKOP( send( fd, &socks5_connect, msgsize, 0 ), "Sending connect reply" );
-
-			bt->phase = BS_PHASE_REPLY;
-
-			imcb_log( tf->ic, "File %s: SOCKS5 handshake successful! Transfer about to start...", tf->ft->file_name );
-
-			if( tf->accepted )
-			{
-				/* streamhost-used message came already in(possible?), let's start sending */
-				tf->ft->write_request( tf->ft );
-			}
-
-			tf->watch_in = 0;
-			return FALSE;
-
-		}
-	default:
-		/* BUG */
-		imcb_log( bt->tf->ic, "BUG in file transfer code: undefined handshake phase" );
-
-		bt->tf->watch_in = 0;
-		return FALSE;
-	}
-}
-#undef ASSERTSOCKOP
Index: otocols/jabber/si.c
===================================================================
--- protocols/jabber/si.c	(revision c821e8ad0d1cf9ab71e6e34c685d0adea2dde923)
+++ 	(revision )
@@ -1,525 +1,0 @@
-/***************************************************************************\
-*                                                                           *
-*  BitlBee - An IRC to IM gateway                                           *
-*  Jabber module - SI packets                                               *
-*                                                                           *
-*  Copyright 2007 Uli Meis <a.sporto+bee@gmail.com>                         *
-*                                                                           *
-*  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.              *
-*                                                                           *
-\***************************************************************************/
-
-#include "jabber.h"
-#include "sha1.h"
-
-void jabber_si_answer_request( file_transfer_t *ft );
-int jabber_si_send_request(struct im_connection *ic, char *who, struct jabber_transfer *tf );
-
-/* file_transfer free() callback */
-void jabber_si_free_transfer( file_transfer_t *ft)
-{
-	struct jabber_transfer *tf = ft->data;
-	struct jabber_data *jd = tf->ic->proto_data;
-
-	if ( tf->watch_in )
-		b_event_remove( tf->watch_in );
-
-	jd->filetransfers = g_slist_remove( jd->filetransfers, tf );
-
-	if( tf->fd )
-	{
-		close( tf->fd );
-		tf->fd = 0;
-	}
-
-	if( tf->disco_timeout )
-		b_event_remove( tf->disco_timeout );
-	
-	g_free( tf->ini_jid );
-	g_free( tf->tgt_jid );
-	g_free( tf->iq_id );
-	g_free( tf->sid );
-}
-
-/* file_transfer finished() callback */
-void jabber_si_finished( file_transfer_t *ft )
-{
-	struct jabber_transfer *tf = ft->data;
-	time_t diff = time( NULL ) - ft->started ? : 1;
-
-	imcb_log( tf->ic, "File %s transferred successfully at %d kb/s!" , ft->file_name, (int) ( ft->bytes_transferred / 1024 / diff ) );
-}
-
-/* file_transfer canceled() callback */
-void jabber_si_canceled( file_transfer_t *ft, char *reason )
-{
-	struct jabber_transfer *tf = ft->data;
-	struct xt_node *reply, *iqnode;
-
-	if( tf->accepted )
-		return;
-	
-	iqnode = jabber_make_packet( "iq", "error", tf->ini_jid, NULL );
-	xt_add_attr( iqnode, "id", tf->iq_id );
-	reply = jabber_make_error_packet( iqnode, "forbidden", "cancel", "403" );
-	xt_free_node( iqnode );
-	
-	if( !jabber_write_packet( tf->ic, reply ) )
-		imcb_log( tf->ic, "WARNING: Error generating reply to file transfer request" );
-	xt_free_node( reply );
-
-}
-
-int jabber_si_check_features( struct jabber_transfer *tf, GSList *features ) {
-	int foundft = FALSE, foundbt = FALSE, foundsi = FALSE;
-
-	while ( features )
-	{
-		if( !strcmp( features->data, XMLNS_FILETRANSFER ) )
-			foundft = TRUE;
-		if( !strcmp( features->data, XMLNS_BYTESTREAMS ) )
-			foundbt = TRUE;
-		if( !strcmp( features->data, XMLNS_SI ) )
-			foundsi = TRUE;
-
-		features = g_slist_next(features);
-	}
-
-	if( !foundft )
-		imcb_file_canceled( tf->ft, "Buddy's client doesn't feature file transfers" );
-	else if( !foundbt )
-		imcb_file_canceled( tf->ft, "Buddy's client doesn't feature byte streams (required)" );
-	else if( !foundsi )
-		imcb_file_canceled( tf->ft, "Buddy's client doesn't feature stream initiation (required)" );
-		
-	return foundft && foundbt && foundsi;
-}
-
-void jabber_si_transfer_start( struct jabber_transfer *tf ) {
-
-	if( !jabber_si_check_features( tf, tf->bud->features ) )
-		return;
-		
-	/* send the request to our buddy */
-	jabber_si_send_request( tf->ic, tf->bud->full_jid, tf );
-
-	/* and start the receive logic */
-	imcb_file_recv_start( tf->ft );
-
-}
-
-gboolean jabber_si_waitfor_disco( gpointer data, gint fd, b_input_condition cond )
-{
-	struct jabber_transfer *tf = data;
-	struct jabber_data *jd = tf->ic->proto_data;
-
-	tf->disco_timeout_fired++;
-
-	if( tf->bud->features && jd->have_streamhosts==1 ) {
-		jabber_si_transfer_start( tf );
-		tf->disco_timeout = 0;
-		return FALSE;
-	}
-
-	/* 8 seconds should be enough for server and buddy to respond */
-	if ( tf->disco_timeout_fired < 16 )
-		return TRUE;
-	
-	if( !tf->bud->features && jd->have_streamhosts!=1 )
-		imcb_file_canceled( tf->ft, "Couldn't get buddy's features or the server's" );
-	else if( !tf->bud->features )
-		imcb_file_canceled( tf->ft, "Couldn't get buddy's features" );
-	else
-		imcb_file_canceled( tf->ft, "Couldn't get server's features" );
-	
-	tf->disco_timeout = 0;
-	return FALSE;
-}
-
-void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who ) 
-{
-	struct jabber_transfer *tf;
-	struct jabber_data *jd = ic->proto_data;
-	struct jabber_buddy *bud;
-	char *server = jd->server, *s;
-
-	if( ( s = strchr( who, '=' ) ) && jabber_chat_by_jid( ic, s + 1 ) )
-		bud = jabber_buddy_by_ext_jid( ic, who, 0 );
-	else
-		bud = jabber_buddy_by_jid( ic, who, 0 );
-
-	if( bud == NULL )
-	{
-		imcb_file_canceled( tf->ft, "Couldn't find buddy (BUG?)" );
-		return;
-	}
-		
-	imcb_log( ic, "Trying to send %s(%zd bytes) to %s", ft->file_name, ft->file_size, who );
-
-	tf = g_new0( struct jabber_transfer, 1 );
-
-	tf->ic = ic;
-	tf->ft = ft;
-	tf->ft->data = tf;
-	tf->ft->free = jabber_si_free_transfer;
-	tf->ft->finished = jabber_si_finished;
-	tf->bud = bud;
-	ft->write = jabber_bs_send_write;
-
-	jd->filetransfers = g_slist_prepend( jd->filetransfers, tf );
-
-	/* query buddy's features and server's streaming proxies if neccessary */
-
-	if( !tf->bud->features )
-		jabber_iq_query_features( ic, bud->full_jid );
-
-	if( jd->have_streamhosts!=1 ) {
-		jd->have_streamhosts = 0;
-		jabber_iq_query_server( ic, server, XMLNS_DISCO_ITEMS );
-	}
-
-	/* if we had to do a query, wait for the result. 
-	 * Otherwise fire away. */
-	if( !tf->bud->features || jd->have_streamhosts!=1 )
-		tf->disco_timeout = b_timeout_add( 500, jabber_si_waitfor_disco, tf );
-	else
-		jabber_si_transfer_start( tf );
-}
-
-/*
- * First function that gets called when a file transfer request comes in.
- * A lot to parse.
- *
- * We choose a stream type from the options given by the initiator.
- * Then we wait for imcb to call the accept or cancel callbacks.
- */
-int jabber_si_handle_request( struct im_connection *ic, struct xt_node *node, struct xt_node *sinode)
-{
-	struct xt_node *c, *d, *reply;
-	char *sid, *ini_jid, *tgt_jid, *iq_id, *s, *ext_jid;
-	struct jabber_buddy *bud;
-	int requestok = FALSE;
-	char *name;
-	size_t size;
-	struct jabber_transfer *tf;
-	struct jabber_data *jd = ic->proto_data;
-	file_transfer_t *ft;
-	
-	/* All this means we expect something like this: ( I think )
-	 * <iq from=... to=... id=...>
-	 * 	<si id=id xmlns=si profile=ft>
-	 * 		<file xmlns=ft/>
-	 * 		<feature xmlns=feature>
-	 * 			<x xmlns=xdata type=submit>
-	 * 				<field var=stream-method>
-	 *
-	 */
-	if( !( ini_jid 		= xt_find_attr(   node, "from" ) 			) ||
-	    !( tgt_jid 		= xt_find_attr(   node, "to" ) 				) ||
-	    !( iq_id 		= xt_find_attr(   node, "id" ) 				) ||
-	    !( sid 		= xt_find_attr( sinode, "id" ) 				) ||
-	    !( strcmp( xt_find_attr( sinode, "profile" ), XMLNS_FILETRANSFER ) == 0	) ||
-	    !( d 		= xt_find_node( sinode->children, "file" ) 		) ||
-	    !( strcmp( xt_find_attr( d, "xmlns" ), XMLNS_FILETRANSFER ) == 0 		) ||
-	    !( name 		= xt_find_attr( d, "name" ) 				) ||
-	    !( size 		= (size_t) atoll( xt_find_attr( d, "size" ) ) 		) ||
-	    !( d 		= xt_find_node( sinode->children, "feature" ) 		) ||
-	    !( strcmp( xt_find_attr( d, "xmlns" ), XMLNS_FEATURE ) == 0 		) ||
-	    !( d 		= xt_find_node( d->children, "x" ) 			) ||
-	    !( strcmp( xt_find_attr( d, "xmlns" ), XMLNS_XDATA ) == 0 			) ||
-	    !( strcmp( xt_find_attr( d, "type" ), "form" ) == 0 			) ||
-	    !( d 		= xt_find_node( d->children, "field" ) 			) ||
-	    !( strcmp( xt_find_attr( d, "var" ), "stream-method" ) == 0 		) )
-	{
-		imcb_log( ic, "WARNING: Received incomplete Stream Initiation request" );
-	} else
-	{
-		/* Check if we support one of the options */
-
-		c = d->children;
-		while( ( c = xt_find_node( c, "option" ) ) )
-			if( 	( d = xt_find_node( c->children, "value" ) ) &&
-				( strcmp( d->text, XMLNS_BYTESTREAMS ) == 0 ) )
-			{
-				requestok = TRUE;
-				break;
-			}
-
-		if ( !requestok )
-			imcb_log( ic, "WARNING: Unsupported file transfer request from %s", ini_jid);
-	}
-	
-	if ( requestok )
-	{
-		/* Figure out who the transfer should come frome... */
-
-		if( ( s = strchr( ini_jid, '/' ) ) )
-		{
-			if( ( bud = jabber_buddy_by_jid( ic, ini_jid, GET_BUDDY_EXACT ) ) )
-			{
-				bud->last_act = time( NULL );
-				ext_jid = bud->ext_jid ? : bud->bare_jid;
-			}
-			else
-				*s = 0; /* We need to generate a bare JID now. */
-		}
-
-		if( !( ft = imcb_file_send_start( ic, ext_jid, name, size ) ) )
-		{ 
-			imcb_log( ic, "WARNING: Error handling transfer request from %s", ini_jid);
-			requestok = FALSE;
-		}
-
-		*s = '/';
-	}
-
-	if ( !requestok )
-	{ 
-		reply = jabber_make_error_packet( node, "item-not-found", "cancel", NULL );
-		if (!jabber_write_packet( ic, reply ))
-			imcb_log( ic, "WARNING: Error generating reply to file transfer request" );
-		xt_free_node( reply );
-		return XT_HANDLED;
-	}
-
-	/* Request is fine. */
-
-	imcb_log( ic, "File transfer request from %s for %s (%zd kb). ", xt_find_attr( node, "from" ), name, size/1024 );
-
-	imcb_log( ic, "Accept the file transfer if you'd like the file. If you don't, issue the 'transfers reject' command.");
-
-	tf = g_new0( struct jabber_transfer, 1 );
-
-	tf->ini_jid = g_strdup( ini_jid );
-	tf->tgt_jid = g_strdup( tgt_jid );
-	tf->iq_id = g_strdup( iq_id );
-	tf->sid = g_strdup( sid );
-	tf->ic = ic;
-	tf->ft = ft;
-	tf->ft->data = tf;
-	tf->ft->accept = jabber_si_answer_request;
-	tf->ft->free = jabber_si_free_transfer;
-	tf->ft->finished = jabber_si_finished;
-	tf->ft->canceled = jabber_si_canceled;
-
-	jd->filetransfers = g_slist_prepend( jd->filetransfers, tf );
-
-	return XT_HANDLED;
-}
-
-/*
- * imc called the accept callback which probably means that the user accepted this file transfer.
- * We send our response to the initiator.
- * In the next step, the initiator will send us a request for the given stream type.
- * (currently that can only be a SOCKS5 bytestream)
- */
-void jabber_si_answer_request( file_transfer_t *ft ) {
-	struct jabber_transfer *tf = ft->data;
-	struct xt_node *node, *sinode, *reply;
-
-	/* generate response, start with the SI tag */
-	sinode = xt_new_node( "si", NULL, NULL );
-	xt_add_attr( sinode, "xmlns", XMLNS_SI );
-	xt_add_attr( sinode, "profile", XMLNS_FILETRANSFER );
-	xt_add_attr( sinode, "id", tf->sid );
-
-	/* now the file tag */
-	node = xt_new_node( "file", NULL, NULL );
-	xt_add_attr( node, "xmlns", XMLNS_FILETRANSFER );
-
-	xt_add_child( sinode, node );
-
-	/* and finally the feature tag */
-	node = xt_new_node( "field", NULL, NULL );
-	xt_add_attr( node, "var", "stream-method" );
-	xt_add_attr( node, "type", "list-single" );
-
-	/* Currently all we can do. One could also implement in-band (IBB) */
-	xt_add_child( node, xt_new_node( "value", XMLNS_BYTESTREAMS, NULL ) );
-
-	node = xt_new_node( "x", NULL, node );
-	xt_add_attr( node, "xmlns", XMLNS_XDATA );
-	xt_add_attr( node, "type", "submit" );
-
-	node = xt_new_node( "feature", NULL, node );
-	xt_add_attr( node, "xmlns", XMLNS_FEATURE );
-
-	xt_add_child( sinode, node );
-
-	reply = jabber_make_packet( "iq", "result", tf->ini_jid, sinode );
-	xt_add_attr( reply, "id", tf->iq_id );
-	
-	if( !jabber_write_packet( tf->ic, reply ) )
-		imcb_log( tf->ic, "WARNING: Error generating reply to file transfer request" );
-	else
-		tf->accepted = TRUE;
-	xt_free_node( reply );
-}
-
-static xt_status jabber_si_handle_response(struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
-{
-	struct xt_node *c, *d;
-	char *ini_jid, *tgt_jid, *iq_id;
-	GSList *tflist;
-	struct jabber_transfer *tf=NULL;
-	struct jabber_data *jd = ic->proto_data;
-
-	if( !( tgt_jid = xt_find_attr( node, "from" ) ) ||
-	    !( ini_jid = xt_find_attr( node, "to" ) ) )
-	{
-		imcb_log( ic, "Invalid SI response from=%s to=%s", tgt_jid, ini_jid );
-		return XT_HANDLED;
-	}
-	
-	/* All this means we expect something like this: ( I think )
-	 * <iq from=... to=... id=...>
-	 * 	<si xmlns=si>
-	 * 	[	<file xmlns=ft/>    ] <-- not neccessary
-	 * 		<feature xmlns=feature>
-	 * 			<x xmlns=xdata type=submit>
-	 * 				<field var=stream-method>
-	 * 					<value>
-	 */
-	if( !( tgt_jid = xt_find_attr( node, "from" ) ) ||
-	    !( ini_jid = xt_find_attr( node, "to" ) ) ||
-	    !( iq_id   = xt_find_attr( node, "id" ) ) ||
-	    !( c = xt_find_node( node->children, "si" ) ) ||
-	    !( strcmp( xt_find_attr( c, "xmlns" ), XMLNS_SI ) == 0 ) ||
-/*	    !( d = xt_find_node( c->children, "file" ) ) ||
-	    !( strcmp( xt_find_attr( d, "xmlns" ), XMLNS_FILETRANSFER ) == 0 ) || */
-	    !( d = xt_find_node( c->children, "feature" ) ) ||
-	    !( strcmp( xt_find_attr( d, "xmlns" ), XMLNS_FEATURE ) == 0 ) ||
-	    !( d = xt_find_node( d->children, "x" ) ) ||
-	    !( strcmp( xt_find_attr( d, "xmlns" ), XMLNS_XDATA ) == 0 ) ||
-	    !( strcmp( xt_find_attr( d, "type" ), "submit" ) == 0 ) ||
-	    !( d = xt_find_node( d->children, "field" ) ) ||
-	    !( strcmp( xt_find_attr( d, "var" ), "stream-method" ) == 0 ) ||
-	    !( d = xt_find_node( d->children, "value" ) ) )
-	{
-		imcb_log( ic, "WARNING: Received incomplete Stream Initiation response" );
-		return XT_HANDLED;
-	}
-
-	if( !( strcmp( d->text, XMLNS_BYTESTREAMS ) == 0 ) ) { 
-		/* since we should only have advertised what we can do and the peer should
-		 * only have chosen what we offered, this should never happen */
-		imcb_log( ic, "WARNING: Received invalid Stream Initiation response, method %s", d->text );
-			
-		return XT_HANDLED;
-	}
-	
-	/* Let's see if we can find out what this bytestream should be for... */
-
-	for( tflist = jd->filetransfers ; tflist; tflist = g_slist_next(tflist) )
-	{
-		struct jabber_transfer *tft = tflist->data;
-		if( ( strcmp( tft->iq_id, iq_id ) == 0 ) )
-		{
-		    	tf = tft;
-			break;
-		}
-	}
-
-	if (!tf) 
-	{
-		imcb_log( ic, "WARNING: Received bytestream request from %s that doesn't match an SI request", ini_jid );
-		return XT_HANDLED;
-	}
-
-	tf->ini_jid = g_strdup( ini_jid );
-	tf->tgt_jid = g_strdup( tgt_jid );
-
-	imcb_log( ic, "File %s: %s accepted the transfer!", tf->ft->file_name, tgt_jid );
-
-	jabber_bs_send_start( tf );
-
-	return XT_HANDLED;
-}
-
-int jabber_si_send_request(struct im_connection *ic, char *who, struct jabber_transfer *tf )
-{
-	struct xt_node *node, *sinode;
-	struct jabber_buddy *bud;
-
-	/* who knows how many bits the future holds :) */
-	char filesizestr[ 1 + ( int ) ( 0.301029995663981198f * sizeof( size_t ) * 8 ) ];
-
-	const char *methods[] = 
-	{  	
-		XMLNS_BYTESTREAMS,
-		//XMLNS_IBB,
-		NULL 
-	};
-	const char **m;
-	char *s;
-
-	/* Maybe we should hash this? */
-	tf->sid = g_strdup_printf( "BitlBeeJabberSID%d", tf->ft->local_id );
-	
-	if( ( s = strchr( who, '=' ) ) && jabber_chat_by_jid( ic, s + 1 ) )
-		bud = jabber_buddy_by_ext_jid( ic, who, 0 );
-	else
-		bud = jabber_buddy_by_jid( ic, who, 0 );
-
-	/* start with the SI tag */
-	sinode = xt_new_node( "si", NULL, NULL );
-	xt_add_attr( sinode, "xmlns", XMLNS_SI );
-	xt_add_attr( sinode, "profile", XMLNS_FILETRANSFER );
-	xt_add_attr( sinode, "id", tf->sid );
-
-/*	if( mimetype ) 
-		xt_add_attr( node, "mime-type", mimetype ); */
-
-	/* now the file tag */
-/*	if( desc )
- 		node = xt_new_node( "desc", descr, NULL ); */
-	node = xt_new_node( "range", NULL, NULL );
-
-	sprintf( filesizestr, "%zd", tf->ft->file_size );
-	node = xt_new_node( "file", NULL, node );
-	xt_add_attr( node, "xmlns", XMLNS_FILETRANSFER );
-	xt_add_attr( node, "name", tf->ft->file_name );
-	xt_add_attr( node, "size", filesizestr );
-/*	if (hash)
-		xt_add_attr( node, "hash", hash );
-	if (date)
-		xt_add_attr( node, "date", date ); */
-
-	xt_add_child( sinode, node );
-
-	/* and finally the feature tag */
-	node = xt_new_node( "field", NULL, NULL );
-	xt_add_attr( node, "var", "stream-method" );
-	xt_add_attr( node, "type", "list-single" );
-
-	for ( m = methods ; *m ; m ++ )
-		xt_add_child( node, xt_new_node( "option", NULL, xt_new_node( "value", (char *)*m, NULL ) ) );
-
-	node = xt_new_node( "x", NULL, node );
-	xt_add_attr( node, "xmlns", XMLNS_XDATA );
-	xt_add_attr( node, "type", "form" );
-
-	node = xt_new_node( "feature", NULL, node );
-	xt_add_attr( node, "xmlns", XMLNS_FEATURE );
-
-	xt_add_child( sinode, node );
-
-	/* and we are there... */
-	node = jabber_make_packet( "iq", "set", bud ? bud->full_jid : who, sinode );
-	jabber_cache_add( ic, node, jabber_si_handle_response );
-	tf->iq_id = g_strdup( xt_find_attr( node, "id" ) );
-	
-	return jabber_write_packet( ic, node );
-}
Index: protocols/nogaim.h
===================================================================
--- protocols/nogaim.h	(revision c821e8ad0d1cf9ab71e6e34c685d0adea2dde923)
+++ protocols/nogaim.h	(revision de8e584d7f4fea214934af094a4df2672d7e0be8)
@@ -44,5 +44,4 @@
 #include "query.h"
 #include "md5.h"
-#include "ft.h"
 
 #define BUF_LEN MSG_LEN
@@ -230,7 +229,4 @@
 	 * - Most protocols will just want to set this to g_strcasecmp().*/
 	int (* handle_cmp) (const char *who1, const char *who2);
-
-	/* Incoming transfer request */
-	void (* transfer_request) (struct im_connection *, file_transfer_t *ft, char *handle );
 };
 
Index: root_commands.c
===================================================================
--- root_commands.c	(revision c821e8ad0d1cf9ab71e6e34c685d0adea2dde923)
+++ root_commands.c	(revision de8e584d7f4fea214934af094a4df2672d7e0be8)
@@ -1041,69 +1041,4 @@
 		irc_usermsg( irc, "Tried to join chat, not sure if this was successful" );
 		g_free( channel );
-	}
-}
-
-static void cmd_transfers( irc_t *irc, char **cmd )
-{
-	GSList *files = irc->file_transfers;
-	enum { LIST, REJECT, CANCEL };
-	int subcmd = LIST;
-	int fid;
-
-	if( !files )
-	{
-		irc_usermsg( irc, "No pending transfers" );
-		return;
-	}
-
-	if( cmd[1] && 
-	    ( strcmp( cmd[1], "reject" ) == 0 ) )
-	{
-		subcmd = REJECT;
-	}
-	else if( cmd[1] && 
-		 ( strcmp( cmd[1], "cancel" ) == 0 ) && 
-		 cmd[2] &&
-		 ( fid = atoi( cmd[2] ) ) )
-	{
-		subcmd = CANCEL;
-	}
-
-	for( ; files; files = g_slist_next( files ) )
-	{
-		file_transfer_t *file = files->data;
-		
-		switch( subcmd ) {
-		case LIST:
-			if ( file->status == FT_STATUS_LISTENING )
-				irc_usermsg( irc, 
-					"Pending file(id %d): %s (Listening...)", file->local_id, file->file_name);
-			else 
-			{
-				int kb_per_s = 0;
-				time_t diff = time( NULL ) - file->started ? : 1;
-				if ( ( file->started > 0 ) && ( file->bytes_transferred > 0 ) )
-					kb_per_s = file->bytes_transferred / 1024 / diff;
-					
-				irc_usermsg( irc, 
-					"Pending file(id %d): %s (%10zd/%zd kb, %d kb/s)", file->local_id, file->file_name, 
-					file->bytes_transferred/1024, file->file_size/1024, kb_per_s);
-			}
-			break;
-		case REJECT:
-			if( file->status == FT_STATUS_LISTENING )
-			{
-				irc_usermsg( irc, "Rejecting file transfer for %s", file->file_name );
-				imcb_file_canceled( file, "Denied by user" );
-			}
-			break;
-		case CANCEL:
-			if( file->local_id == fid )
-			{
-				irc_usermsg( irc, "Canceling file transfer for %s", file->file_name );
-				imcb_file_canceled( file, "Canceled by user" );
-			}
-			break;
-		}
 	}
 }
@@ -1129,5 +1064,4 @@
 	{ "qlist",          0, cmd_qlist,          0 },
 	{ "join_chat",      2, cmd_join_chat,      0 },
-	{ "transfers",      0, cmd_transfers,      0 },
 	{ NULL }
 };
