Index: protocols/jabber/jabber.c
===================================================================
--- protocols/jabber/jabber.c	(revision 3355a82eae40c89024233ccafc5f0c25dee2dc5c)
+++ protocols/jabber/jabber.c	(revision 8a90001ab2cde971abc64b8d5e4174dc4c4b0ae2)
@@ -62,4 +62,6 @@
 	s = set_add( &acc->set, "xmlconsole", "false", set_eval_bool, acc );
 	s->flags |= ACC_SET_OFFLINE_ONLY;
+
+	s = set_add( &acc->set, "proxy", "<local>;<auto>", NULL, acc );
 }
 
Index: protocols/jabber/s5bytestream.c
===================================================================
--- protocols/jabber/s5bytestream.c	(revision 3355a82eae40c89024233ccafc5f0c25dee2dc5c)
+++ protocols/jabber/s5bytestream.c	(revision 8a90001ab2cde971abc64b8d5e4174dc4c4b0ae2)
@@ -362,5 +362,5 @@
 	tf->ft->free = jabber_bs_free_transfer;
 
-	jabber_bs_recv_handshake( bt, 0, 0 ); 
+	jabber_bs_recv_handshake( bt, -1, 0 ); 
 
 	return XT_HANDLED;
@@ -381,5 +381,5 @@
 	int gret;
 
-	if ( ( fd != 0 ) && !jabber_bs_poll( bt, fd, &revents ) )
+	if ( ( fd != -1 ) && !jabber_bs_poll( bt, fd, &revents ) )
 		return FALSE;
 	
@@ -554,5 +554,5 @@
 	{
 		bt->sh = shlist->next->data;
-		return jabber_bs_recv_handshake( bt, 0, 0 );
+		return jabber_bs_recv_handshake( bt, -1, 0 );
 	}
 
@@ -620,5 +620,5 @@
 	struct jabber_transfer *tf = bt->tf;
 
-	if( fd != 0 ) /* called via event thread */
+	if( fd != -1 ) /* called via event thread */
 	{
 		tf->watch_in = 0;
@@ -666,5 +666,5 @@
 	}
 	
-	jabber_bs_recv_read( tf->streamhandle, 0 , 0 );
+	jabber_bs_recv_read( tf->streamhandle, -1 , 0 );
 
 	return TRUE;
@@ -776,5 +776,5 @@
 		/* using a proxy, abort listen */
 
-		if ( tf->watch_in )
+		if( tf->watch_in )
 		{
 			b_event_remove( tf->watch_in );
@@ -782,6 +782,8 @@
 		}
 		
-		closesocket( tf->fd );
-		tf->fd = 0;
+		if( tf->fd != -1 ) {
+			closesocket( tf->fd );
+			tf->fd = -1;
+		}
 
 		if ( bt->connect_timeout )
@@ -798,5 +800,5 @@
 			{
 				bt->sh = sh;
-				jabber_bs_recv_handshake( bt, 0, 0 );
+				jabber_bs_recv_handshake( bt, -1, 0 );
 				return XT_HANDLED;
 			}
@@ -872,4 +874,68 @@
 }
 
+jabber_streamhost_t *jabber_si_parse_proxy( struct im_connection *ic, char *proxy )
+{
+	char *host, *port, *jid;
+	jabber_streamhost_t *sh;
+
+	if( ( ( host = strchr( proxy, ',' ) ) == 0 ) ||
+	     ( ( port = strchr( host+1, ',' ) ) == 0 ) ) {
+		imcb_log( ic, "Error parsing proxy setting: \"%s\" (ignored)", proxy );
+		return NULL;
+	}
+	
+	jid = proxy;
+	*host++ = '\0';
+	*port++ = '\0';
+
+	sh = g_new0( jabber_streamhost_t, 1 );
+	sh->jid = g_strdup( jid );
+	sh->host = g_strdup( host );
+	strcpy( sh->port, port );
+
+	return sh;
+}
+
+void jabber_si_set_proxies( struct bs_transfer *bt )
+{
+	struct jabber_transfer *tf = bt->tf;
+	struct jabber_data *jd = tf->ic->proto_data;
+	char *proxysetting = g_strdup ( set_getstr( &tf->ic->acc->set, "proxy" ) );
+	char *proxy,*next;
+	char port[6];
+	char host[INET6_ADDRSTRLEN];
+	jabber_streamhost_t *sh, *sh2;
+	GSList *streamhosts = jd->streamhosts;
+
+	proxy = proxysetting;
+	while ( proxy && ( *proxy!='\0' ) ) {
+		if( ( next = strchr( proxy, ';' ) ) )
+			*next++ = '\0';	
+		
+		if( ( strcmp( proxy, "<local>" ) == 0 ) && jabber_bs_send_listen( bt, &tf->saddr, host, port ) ) {
+			sh = g_new0( jabber_streamhost_t, 1 );
+			sh->jid = g_strdup( tf->ini_jid );
+			sh->host = g_strdup( host );
+			strcpy( sh->port, port );
+			bt->streamhosts = g_slist_append( bt->streamhosts, sh );
+
+			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 );
+		} else if( strcmp( proxy, "<auto>" ) == 0 ) {
+			while ( streamhosts ) {
+				sh = g_new0( jabber_streamhost_t, 1 );
+				sh2 = streamhosts->data;
+				sh->jid = g_strdup( sh2->jid );
+				sh->host = g_strdup( sh2->host );
+				strcpy( sh->port, sh2->port );
+				bt->streamhosts = g_slist_append( bt->streamhosts, sh );
+				streamhosts = g_slist_next( streamhosts );
+			}
+		} else if( ( sh = jabber_si_parse_proxy( tf->ic, proxy ) ) )
+			bt->streamhosts = g_slist_append( bt->streamhosts, sh );
+		proxy = next;
+	}
+}
+
 /*
  * Starts a bytestream.
@@ -877,5 +943,4 @@
 gboolean jabber_bs_send_start( struct jabber_transfer *tf )
 {
-	char host[INET6_ADDRSTRLEN];
 	struct bs_transfer *bt;
 	sha1_state_t sha;
@@ -883,7 +948,4 @@
 	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 */
@@ -905,16 +967,7 @@
 	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 );
+	jabber_si_set_proxies( bt );
+
+	ret = jabber_bs_send_request( tf, bt->streamhosts);
 
 	return ret;
Index: protocols/jabber/si.c
===================================================================
--- protocols/jabber/si.c	(revision 3355a82eae40c89024233ccafc5f0c25dee2dc5c)
+++ protocols/jabber/si.c	(revision 8a90001ab2cde971abc64b8d5e4174dc4c4b0ae2)
@@ -39,8 +39,8 @@
 	jd->filetransfers = g_slist_remove( jd->filetransfers, tf );
 
-	if( tf->fd )
+	if( tf->fd != -1 )
 	{
 		close( tf->fd );
-		tf->fd = 0;
+		tf->fd = -1;
 	}
 
@@ -129,6 +129,6 @@
 
 	if( tf->bud->features && jd->have_streamhosts==1 ) {
+		tf->disco_timeout = 0;
 		jabber_si_transfer_start( tf );
-		tf->disco_timeout = 0;
 		return FALSE;
 	}
@@ -139,11 +139,12 @@
 	
 	if( !tf->bud->features && jd->have_streamhosts!=1 )
-		imcb_file_canceled( tf->ft, "Couldn't get buddy's features or the server's" );
+		imcb_log( tf->ic, "Couldn't get buddy's features nor discover all services of the server" );
 	else if( !tf->bud->features )
-		imcb_file_canceled( tf->ft, "Couldn't get buddy's features" );
+		imcb_log( tf->ic, "Couldn't get buddy's features" );
 	else
-		imcb_file_canceled( tf->ft, "Couldn't get server's features" );
+		imcb_log( tf->ic, "Couldn't discover some of the server's services" );
 	
 	tf->disco_timeout = 0;
+	jabber_si_transfer_start( tf );
 	return FALSE;
 }
@@ -173,4 +174,5 @@
 	tf->ic = ic;
 	tf->ft = ft;
+	tf->fd = -1;
 	tf->ft->data = tf;
 	tf->ft->free = jabber_si_free_transfer;
@@ -186,8 +188,11 @@
 		jabber_iq_query_features( ic, bud->full_jid );
 
-	if( jd->have_streamhosts!=1 ) {
+	/* If <auto> is not set don't check for proxies */
+	if( ( jd->have_streamhosts!=1 ) && ( jd->streamhosts==NULL ) &&
+	    ( strstr( set_getstr( &ic->acc->set, "proxy" ), "<auto>" ) != NULL ) ) {
 		jd->have_streamhosts = 0;
 		jabber_iq_query_server( ic, server, XMLNS_DISCO_ITEMS );
-	}
+	} else if ( jd->streamhosts!=NULL )
+		jd->have_streamhosts = 1;
 
 	/* if we had to do a query, wait for the result. 
@@ -309,4 +314,5 @@
 	tf->ic = ic;
 	tf->ft = ft;
+	tf->fd = -1;
 	tf->ft->data = tf;
 	tf->ft->accept = jabber_si_answer_request;
