Index: protocols/Makefile
===================================================================
--- protocols/Makefile	(revision b5a22e33a1aa2500093e783e79de2f44bf53c150)
+++ protocols/Makefile	(revision 7c0a4975a538ab75405e64919bbdfee51b898b2e)
@@ -10,5 +10,5 @@
 
 # [SH] Program variables
-objects = md5.o nogaim.o proxy.o sha.o util.o $(SSL_CLIENT)
+objects = http_client.o md5.o nogaim.o proxy.o sha.o $(SSL_CLIENT) util.o
 
 # [SH] The next two lines should contain the directory name (in $(subdirs))
Index: protocols/http_client.c
===================================================================
--- protocols/http_client.c	(revision 7c0a4975a538ab75405e64919bbdfee51b898b2e)
+++ protocols/http_client.c	(revision 7c0a4975a538ab75405e64919bbdfee51b898b2e)
@@ -0,0 +1,382 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2005 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/* HTTP(S) module                                                       */
+
+/*
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <string.h>
+#include <stdio.h>
+
+#include "sock.h"
+#include "http_client.h"
+#include "url.h"
+
+
+static void http_connected( gpointer data, int source, GaimInputCondition cond );
+static void http_ssl_connected( gpointer data, void *source, GaimInputCondition cond );
+static void http_incoming_data( gpointer data, int source, GaimInputCondition cond );
+
+
+void *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data )
+{
+	struct http_request *req;
+	int error = 0;
+	
+	req = g_new0( struct http_request, 1 );
+	
+	if( ssl )
+	{
+		req->ssl = ssl_connect( host, port, http_ssl_connected, req );
+		if( req->ssl == NULL )
+			error = 1;
+	}
+	else
+	{
+		req->fd = proxy_connect( host, port, http_connected, req );
+		if( req->fd < 0 )
+			error = 1;
+	}
+	
+	if( error )
+	{
+		g_free( req );
+		return( NULL );
+	}
+	
+	req->func = func;
+	req->data = data;
+	req->request = g_strdup( request );
+	req->request_length = strlen( request );
+	
+	return( req );
+}
+
+/* This one is actually pretty simple... Might get more calls if we can't write 
+   the whole request at once. */
+static void http_connected( gpointer data, int source, GaimInputCondition cond )
+{
+	struct http_request *req = data;
+	int st;
+	
+	if( source < 0 )
+		goto error;
+	
+	if( req->inpa > 0 )
+		gaim_input_remove( req->inpa );
+	
+	sock_make_nonblocking( req->fd );
+	
+	if( req->ssl )
+	{
+		st = ssl_write( req->ssl, req->request + req->bytes_written,
+		                req->request_length - req->bytes_written );
+		if( st < 0 )
+		{
+			if( ssl_errno != SSL_AGAIN )
+			{
+				ssl_disconnect( req->ssl );
+				goto error;
+			}
+		}
+	}
+	else
+	{
+		st = write( source, req->request + req->bytes_written,
+		                    req->request_length - req->bytes_written );
+		if( st < 0 )
+		{
+			if( !sockerr_again() )
+			{
+				closesocket( req->fd );
+				goto error;
+			}
+		}
+	}
+	
+	if( st > 0 )
+		req->bytes_written += st;
+	
+	if( req->bytes_written < req->request_length )
+		req->inpa = gaim_input_add( source,
+		                            req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_WRITE,
+	        	                    http_connected, req );
+	else
+		req->inpa = gaim_input_add( source, GAIM_INPUT_READ, http_incoming_data, req );
+	
+	return;
+	
+error:
+	req->func( req );
+	
+	g_free( req->request );
+	g_free( req );
+	
+	return;
+}
+
+static void http_ssl_connected( gpointer data, void *source, GaimInputCondition cond )
+{
+	struct http_request *req = data;
+	
+	if( source == NULL )
+		return http_connected( data, -1, cond );
+	
+	req->fd = ssl_getfd( source );
+	
+	return http_connected( data, req->fd, cond );
+}
+
+static void http_incoming_data( gpointer data, int source, GaimInputCondition cond )
+{
+	struct http_request *req = data;
+	int evil_server = 0;
+	char buffer[2048];
+	char *end1, *end2;
+	int st;
+	
+	if( req->inpa > 0 )
+		gaim_input_remove( req->inpa );
+	
+	if( req->ssl )
+	{
+		st = ssl_read( req->ssl, buffer, sizeof( buffer ) );
+		if( st < 0 )
+		{
+			if( ssl_errno != SSL_AGAIN )
+			{
+				/* goto cleanup; */
+				
+				/* YAY! We have to deal with crappy Microsoft
+				   servers that LOVE to send invalid TLS
+				   packets that abort connections! \o/ */
+				
+				goto got_reply;
+			}
+		}
+		else if( st == 0 )
+		{
+			goto got_reply;
+		}
+	}
+	else
+	{
+		st = read( req->fd, buffer, sizeof( buffer ) );
+		if( st < 0 )
+		{
+			if( !sockerr_again() )
+			{
+				goto cleanup;
+			}
+		}
+		else if( st == 0 )
+		{
+			goto got_reply;
+		}
+	}
+	
+	if( st > 0 )
+	{
+		req->reply_headers = g_realloc( req->reply_headers, req->bytes_read + st + 1 );
+		memcpy( req->reply_headers + req->bytes_read, buffer, st );
+		req->bytes_read += st;
+	}
+	
+	/* There will be more! */
+	req->inpa = gaim_input_add( req->fd,
+	                            req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_READ,
+	                            http_incoming_data, req );
+	
+	return;
+
+got_reply:
+	/* Zero termination is very convenient. */
+	req->reply_headers[req->bytes_read] = 0;
+	
+	/* Find the separation between headers and body, and keep stupid
+	   webservers in mind. */
+	end1 = strstr( req->reply_headers, "\r\n\r\n" );
+	end2 = strstr( req->reply_headers, "\n\n" );
+	
+	if( end2 && end2 < end1 )
+	{
+		end1 = end2 + 1;
+		evil_server = 1;
+	}
+	else
+	{
+		end1 += 2;
+	}
+	
+	if( end1 )
+	{
+		*end1 = 0;
+		
+		if( evil_server )
+			req->reply_body = end1 + 1;
+		else
+			req->reply_body = end1 + 2;
+	}
+	
+	if( ( end1 = strchr( req->reply_headers, ' ' ) ) != NULL )
+	{
+		if( sscanf( end1 + 1, "%d", &req->status_code ) != 1 )
+			req->status_code = -1;
+	}
+	else
+	{
+		req->status_code = -1;
+	}
+	
+	if( req->status_code == 301 || req->status_code == 302 )
+	{
+		char *loc, *new_request, *new_host;
+		int error = 0, new_port, new_proto;
+		
+		loc = strstr( req->reply_headers, "\nLocation: " );
+		if( loc == NULL ) /* We can't handle this redirect... */
+			goto cleanup;
+		
+		loc += 11;
+		while( *loc == ' ' )
+			loc ++;
+		
+		/* TODO/FIXME: Possibly have to handle relative redirections,
+		   and rewrite Host: headers. Not necessary for now, it's
+		   enough for passport authentication like this. */
+		
+		if( *loc == '/' )
+		{
+			/* Just a different pathname... */
+			
+			/* Since we don't cache the servername, and since we
+			   don't need this yet anyway, I won't implement it. */
+			
+			goto cleanup;
+		}
+		else
+		{
+			/* A whole URL */
+			url_t *url;
+			char *s;
+			
+			s = strstr( loc, "\r\n" );
+			if( s == NULL )
+				goto cleanup;
+			
+			url = g_new0( url_t, 1 );
+			*s = 0;
+			
+			if( !url_set( url, loc ) )
+			{
+				g_free( url );
+				goto cleanup;
+			}
+			
+			/* Okay, this isn't fun! We have to rebuild the request... :-( */
+			new_request = g_malloc( req->request_length + strlen( url->file ) );
+			
+			/* So, now I just allocated enough memory, so I'm
+			   going to use strcat(), whether you like it or not. :-) */
+			
+			/* First, find the GET/POST/whatever from the original request. */
+			s = strchr( req->request, ' ' );
+			if( s == NULL )
+			{
+				g_free( new_request );
+				g_free( url );
+				goto cleanup;
+			}
+			
+			*s = 0;
+			sprintf( new_request, "%s %s HTTP/1.0\r\n", req->request, url->file );
+			*s = ' ';
+			
+			s = strstr( req->request, "\r\n" );
+			if( s == NULL )
+			{
+				g_free( new_request );
+				g_free( url );
+				goto cleanup;
+			}
+			
+			strcat( new_request, s + 2 );
+			new_host = g_strdup( url->host );
+			new_port = url->port;
+			new_proto = url->proto;
+			
+			g_free( url );
+		}
+		
+		if( req->ssl )
+			ssl_disconnect( req->ssl );
+		else
+			closesocket( req->fd );
+		
+		req->fd = -1;
+		req->ssl = 0;
+		
+		if( new_proto == PROTO_HTTPS )
+		{
+			req->ssl = ssl_connect( new_host, new_port, http_ssl_connected, req );
+			if( req->ssl == NULL )
+				error = 1;
+		}
+		else
+		{
+			req->fd = proxy_connect( new_host, new_port, http_connected, req );
+			if( req->fd < 0 )
+				error = 1;
+		}
+		g_free( new_host );
+		
+		if( error )
+		{
+			g_free( new_request );
+			goto cleanup;
+		}
+		
+		g_free( req->request );
+		g_free( req->reply_headers );
+		req->request = new_request;
+		req->request_length = strlen( new_request );
+		req->bytes_read = req->bytes_written = req->inpa = 0;
+		req->reply_headers = req->reply_body = NULL;
+		
+		return;
+	}
+	
+	/* Assume that a closed connection means we're finished, this indeed
+	   breaks with keep-alive connections and faulty connections. */
+	req->finished = 1;
+
+cleanup:
+	if( req->ssl )
+		ssl_disconnect( req->ssl );
+	else
+		closesocket( req->fd );
+	
+	req->func( req );
+	
+	g_free( req->request );
+	g_free( req->reply_headers );
+	g_free( req );
+}
Index: protocols/http_client.h
===================================================================
--- protocols/http_client.h	(revision 7c0a4975a538ab75405e64919bbdfee51b898b2e)
+++ protocols/http_client.h	(revision 7c0a4975a538ab75405e64919bbdfee51b898b2e)
@@ -0,0 +1,54 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2005 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/* HTTP(S) module                                                       */
+
+/*
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <glib.h>
+
+#include "ssl_client.h"
+
+struct http_request;
+
+typedef void (*http_input_function)( struct http_request * );
+
+struct http_request
+{
+	char *request;
+	int request_length;
+	int status_code;
+	char *reply_headers;
+	char *reply_body;
+	int finished;
+	
+	void *ssl;
+	int fd;
+	
+	int inpa;
+	int bytes_written;
+	int bytes_read;
+	
+	http_input_function func;
+	gpointer data;
+};
+
+void *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data );
Index: protocols/msn/ns.c
===================================================================
--- protocols/msn/ns.c	(revision b5a22e33a1aa2500093e783e79de2f44bf53c150)
+++ protocols/msn/ns.c	(revision 7c0a4975a538ab75405e64919bbdfee51b898b2e)
@@ -208,5 +208,5 @@
 		{
 			/* Time for some Passport black magic... */
-			if( !passport_get_id( gc, gc->username, gc->password, cmd[4], msn_auth_got_passport_id ) )
+			if( !passport_get_id( msn_auth_got_passport_id, gc, gc->username, gc->password, cmd[4] ) )
 			{
 				hide_login_progress_error( gc, "Error while contacting Passport server" );
Index: protocols/msn/passport.c
===================================================================
--- protocols/msn/passport.c	(revision b5a22e33a1aa2500093e783e79de2f44bf53c150)
+++ protocols/msn/passport.c	(revision 7c0a4975a538ab75405e64919bbdfee51b898b2e)
@@ -20,5 +20,5 @@
  */
 
-#include "ssl_client.h"
+#include "http_client.h"
 #include "passport.h"
 #include "msn.h"
@@ -31,259 +31,72 @@
 static char *prd_cached = NULL;
 
-static char *passport_create_header( char *reply, char *email, char *pwd );
+static int passport_get_id_real( gpointer func, gpointer data, char *header );
+static void passport_get_id_ready( struct http_request *req );
+
 static int passport_retrieve_dalogin( gpointer data, gpointer func, char *header );
-static void passport_retrieve_dalogin_connected( gpointer data, void *ssl, GaimInputCondition cond );
-static int passport_get_id_from( gpointer data, gpointer func, char *header_i, char *url );
-static void passport_get_id_connected( gpointer data, void *ssl, GaimInputCondition cond );
+static void passport_retrieve_dalogin_ready( struct http_request *req );
+
+static char *passport_create_header( char *cookie, char *email, char *pwd );
 static void destroy_reply( struct passport_reply *rep );
 
-
-int passport_get_id( gpointer data, char *username, char *password, char *cookie, gpointer func )
+int passport_get_id( gpointer func, gpointer data, char *username, char *password, char *cookie )
 {
 	char *header = passport_create_header( cookie, username, password );
 	
-	if( prd_cached )
-	{
-		int st;
-		
-		st = passport_get_id_from( data, func, header, prd_cached );
-		g_free( header );
-		return( st );
-	}
+	if( prd_cached == NULL )
+		return passport_retrieve_dalogin( func, data, header );
 	else
-	{
-		return( passport_retrieve_dalogin( data, func, header ) );
-	}
-}
-
-
-static char *passport_create_header( char *reply, char *email, char *pwd )
-{
-	char *buffer = g_new0( char, 2048 );
-	char *currenttoken;
-	char *email_enc, *pwd_enc;
-	
-	email_enc = g_new0( char, strlen( email ) * 3 + 1 );
-	strcpy( email_enc, email );
-	http_encode( email_enc );
-	
-	pwd_enc = g_new0( char, strlen( pwd ) * 3 + 1 );
-	strcpy( pwd_enc, pwd );
-	http_encode( pwd_enc );
-	
-	currenttoken = strstr( reply, "lc=" );
-	if( currenttoken == NULL )
-		return( NULL );
-	
-	g_snprintf( buffer, 2048,
-	            "Authorization: Passport1.4 OrgVerb=GET,"
-	            "OrgURL=http%%3A%%2F%%2Fmessenger%%2Emsn%%2Ecom,"
-	            "sign-in=%s,pwd=%s,%s", email_enc, pwd_enc,
-	            currenttoken );
-	
-	g_free( email_enc );
-	g_free( pwd_enc );
-	
-	return( buffer );
-}
-
-
-static int passport_retrieve_dalogin( gpointer data, gpointer func, char *header )
-{
-	struct passport_reply *rep = g_new0( struct passport_reply, 1 );
-	void *ssl;
-	
+		return passport_get_id_real( func, data, header );
+}
+
+static int passport_get_id_real( gpointer func, gpointer data, char *header )
+{
+	struct passport_reply *rep;
+	char *server, *dummy, *reqs;
+	struct http_request *req;
+	
+	rep = g_new0( struct passport_reply, 1 );
 	rep->data = data;
 	rep->func = func;
-	rep->header = header;
-	
-	ssl = ssl_connect( "nexus.passport.com", 443, passport_retrieve_dalogin_connected, rep );
-	
-	if( !ssl )
-		destroy_reply( rep );
-	
-	return( ssl != NULL );
-}
-
-#define PPR_BUFFERSIZE 2048
-#define PPR_REQUEST "GET /rdr/pprdr.asp HTTP/1.0\r\n\r\n"
-static void passport_retrieve_dalogin_connected( gpointer data, void *ssl, GaimInputCondition cond )
-{
-	int ret;
-	char buffer[PPR_BUFFERSIZE+1];
-	struct passport_reply *rep = data;
+	
+	server = g_strdup( prd_cached );
+	dummy = strchr( server, '/' );
+	
+	if( dummy == NULL )
+	{
+		destroy_reply( rep );
+		return( 0 );
+	}
+	
+	reqs = g_malloc( strlen( header ) + strlen( dummy ) + 128 );
+	sprintf( reqs, "GET %s HTTP/1.0\r\n%s\r\n\r\n", dummy, header );
+	
+	*dummy = 0;
+	req = http_dorequest( server, 443, 1, reqs, passport_get_id_ready, rep );
+	
+	g_free( server );
+	g_free( reqs );
+	
+	if( req == NULL )
+		destroy_reply( rep );
+	
+	return( req != NULL );
+}
+
+static void passport_get_id_ready( struct http_request *req )
+{
+	struct passport_reply *rep = req->data;
 	
 	if( !g_slist_find( msn_connections, rep->data ) )
 	{
-		if( ssl ) ssl_disconnect( ssl );
 		destroy_reply( rep );
 		return;
 	}
 	
-	if( !ssl )
-	{
-		rep->func( rep );
-		destroy_reply( rep );
-		return;
-	}
-	
-	ssl_write( ssl, PPR_REQUEST, strlen( PPR_REQUEST ) );
-	
-	if( ( ret = ssl_read( ssl, buffer, PPR_BUFFERSIZE ) ) <= 0 )
-	{
-		goto failure;
-	}
-
-	{
-		char *dalogin = strstr( buffer, "DALogin=" );
-		char *urlend;
+	if( req->status_code == 200 )
+	{
+		char *dummy;
 		
-		if( !dalogin )
-			goto failure;
-		
-		dalogin += strlen( "DALogin=" );
-		urlend = strchr( dalogin, ',' );
-		if( urlend )
-			*urlend = 0;
-		
-		/* strip the http(s):// part from the url */
-		urlend = strstr( urlend, "://" );
-		if( urlend )
-			dalogin = urlend + strlen( "://" );
-		
-		if( prd_cached == NULL )
-			prd_cached = g_strdup( dalogin );
-	}
-	
-	if( passport_get_id_from( rep->data, rep->func, rep->header, prd_cached ) )
-	{
-		ssl_disconnect( ssl );
-		destroy_reply( rep );
-		return;
-	}
-	
-failure:	
-	ssl_disconnect( ssl );
-	rep->func( rep );
-	destroy_reply( rep );
-}
-
-
-static int passport_get_id_from( gpointer data, gpointer func, char *header_i, char *url )
-{
-	struct passport_reply *rep = g_new0( struct passport_reply, 1 );
-	char server[512], *dummy;
-	void *ssl;
-	
-	rep->data = data;
-	rep->func = func;
-	rep->redirects = 4;
-	
-	strncpy( server, url, 512 );
-	dummy = strchr( server, '/' );
-	if( dummy )
-		*dummy = 0;
-	
-	ssl = ssl_connect( server, 443, passport_get_id_connected, rep );
-	
-	if( ssl )
-	{
-		rep->header = g_strdup( header_i );
-		rep->url = g_strdup( url );
-	}
-	else
-	{
-		destroy_reply( rep );
-	}
-	
-	return( ssl != NULL );
-}
-
-#define PPG_BUFFERSIZE 4096
-static void passport_get_id_connected( gpointer data, void *ssl, GaimInputCondition cond )
-{
-	struct passport_reply *rep = data;
-	char server[512], buffer[PPG_BUFFERSIZE+1], *dummy;
-	int ret;
-	
-	if( !g_slist_find( msn_connections, rep->data ) )
-	{
-		if( ssl ) ssl_disconnect( ssl );
-		destroy_reply( rep );
-		return;
-	}
-	
-	if( !ssl )
-	{
-		rep->func( rep );
-		destroy_reply( rep );
-		return;
-	}
-	
-	memset( buffer, 0, PPG_BUFFERSIZE + 1 );
-	
-	strncpy( server, rep->url, 512 );
-	dummy = strchr( server, '/' );
-	if( dummy == NULL )
-		goto end;
-	
-	g_snprintf( buffer, PPG_BUFFERSIZE - 1, "GET %s HTTP/1.0\r\n"
-	            "%s\r\n\r\n", dummy, rep->header );
-	
-	ssl_write( ssl, buffer, strlen( buffer ) );
-	memset( buffer, 0, PPG_BUFFERSIZE + 1 );
-	
-	{
-		char *buffer2 = buffer;
-		
-		while( ( ( ret = ssl_read( ssl, buffer2, 512 ) ) > 0 ) &&
-		       ( buffer + PPG_BUFFERSIZE - buffer2 - ret - 512 >= 0 ) )
-		{
-			buffer2 += ret;
-		}
-	}
-	
-	if( *buffer == 0 )
-		goto end;
-	
-	if( ( dummy = strstr( buffer, "Location:" ) ) )
-	{
-		char *urlend;
-		
-		rep->redirects --;
-		if( rep->redirects == 0 )
-			goto end;
-		
-		dummy += strlen( "Location:" );
-		while( isspace( *dummy ) ) dummy ++;
-		urlend = dummy;
-		while( !isspace( *urlend ) ) urlend ++;
-		*urlend = 0;
-		if( ( urlend = strstr( dummy, "://" ) ) )
-			dummy = urlend + strlen( "://" );
-		
-		g_free( rep->url );
-		rep->url = g_strdup( dummy );
-		
-		strncpy( server, dummy, sizeof( server ) - 1 );
-		dummy = strchr( server, '/' );
-		if( dummy ) *dummy = 0;
-		
-		ssl_disconnect( ssl );
-		
-		if( ssl_connect( server, 443, passport_get_id_connected, rep ) )
-		{
-			return;
-		}
-		else
-		{
-			rep->func( rep );
-			destroy_reply( rep );
-			return;
-		}
-	}
-	else if( strstr( buffer, "200 OK" ) )
-	{
-		if( ( dummy = strstr( buffer, "from-PP='" ) ) )
+		if( ( dummy = strstr( req->reply_headers, "from-PP='" ) ) )
 		{
 			char *responseend;
@@ -298,16 +111,101 @@
 	}
 	
-end:
-	ssl_disconnect( ssl );
 	rep->func( rep );
 	destroy_reply( rep );
 }
 
+static char *passport_create_header( char *cookie, char *email, char *pwd )
+{
+	char *buffer = g_new0( char, 2048 );
+	char *currenttoken;
+	char *email_enc, *pwd_enc;
+	
+	email_enc = g_new0( char, strlen( email ) * 3 + 1 );
+	strcpy( email_enc, email );
+	http_encode( email_enc );
+	
+	pwd_enc = g_new0( char, strlen( pwd ) * 3 + 1 );
+	strcpy( pwd_enc, pwd );
+	http_encode( pwd_enc );
+	
+	currenttoken = strstr( cookie, "lc=" );
+	if( currenttoken == NULL )
+		return( NULL );
+	
+	g_snprintf( buffer, 2048,
+	            "Authorization: Passport1.4 OrgVerb=GET,"
+	            "OrgURL=http%%3A%%2F%%2Fmessenger%%2Emsn%%2Ecom,"
+	            "sign-in=%s,pwd=%s,%s", email_enc, pwd_enc,
+	            currenttoken );
+	
+	g_free( email_enc );
+	g_free( pwd_enc );
+	
+	return( buffer );
+}
+
+#define PPR_REQUEST "GET /rdr/pprdr.asp HTTP/1.0\r\n\r\n"
+static int passport_retrieve_dalogin( gpointer func, gpointer data, char *header )
+{
+	struct passport_reply *rep = g_new0( struct passport_reply, 1 );
+	struct http_request *req;
+	
+	rep->data = data;
+	rep->func = func;
+	rep->header = header;
+	
+	req = http_dorequest( "nexus.passport.com", 443, 1, PPR_REQUEST, passport_retrieve_dalogin_ready, rep );
+	
+	if( !req )
+		destroy_reply( rep );
+	
+	return( req != NULL );
+}
+
+static void passport_retrieve_dalogin_ready( struct http_request *req )
+{
+	struct passport_reply *rep = req->data;
+	char *dalogin;
+	char *urlend;
+	
+	if( !g_slist_find( msn_connections, rep->data ) )
+	{
+		destroy_reply( rep );
+		return;
+	}
+	
+	dalogin = strstr( req->reply_headers, "DALogin=" );	
+	
+	if( !dalogin )
+		goto failure;
+	
+	dalogin += strlen( "DALogin=" );
+	urlend = strchr( dalogin, ',' );
+	if( urlend )
+		*urlend = 0;
+	
+	/* strip the http(s):// part from the url */
+	urlend = strstr( urlend, "://" );
+	if( urlend )
+		dalogin = urlend + strlen( "://" );
+	
+	if( prd_cached == NULL )
+		prd_cached = g_strdup( dalogin );
+	
+	if( passport_get_id_real( rep->func, rep->data, rep->header ) )
+	{
+		destroy_reply( rep );
+		return;
+	}
+	
+failure:	
+	rep->func( rep );
+	destroy_reply( rep );
+}
 
 static void destroy_reply( struct passport_reply *rep )
 {
-	if( rep->result ) g_free( rep->result );
-	if( rep->url ) g_free( rep->url );
-	if( rep->header ) g_free( rep->header );
-	if( rep ) g_free( rep );
-}
+	g_free( rep->result );
+	g_free( rep->header );
+	g_free( rep );
+}
Index: protocols/msn/passport.h
===================================================================
--- protocols/msn/passport.h	(revision b5a22e33a1aa2500093e783e79de2f44bf53c150)
+++ protocols/msn/passport.h	(revision 7c0a4975a538ab75405e64919bbdfee51b898b2e)
@@ -35,13 +35,11 @@
 struct passport_reply
 {
+	void (*func)( struct passport_reply * );
 	void *data;
 	char *result;
-	void (*func)( struct passport_reply * );
-	char *url;
 	char *header;
-	int redirects;
 };
 
-int passport_get_id( gpointer data, char *username, char *password, char *cookie, gpointer func );
+int passport_get_id( gpointer func, gpointer data, char *username, char *password, char *cookie );
 
 #endif /* __PASSPORT_H__ */
Index: protocols/proxy.c
===================================================================
--- protocols/proxy.c	(revision b5a22e33a1aa2500093e783e79de2f44bf53c150)
+++ protocols/proxy.c	(revision 7c0a4975a538ab75405e64919bbdfee51b898b2e)
@@ -106,6 +106,4 @@
 	if (condition & GAIM_WRITE_COND)
 		gaim_cond |= GAIM_INPUT_WRITE;
-//	if (condition & GAIM_ERR_COND)
-//		fprintf( stderr, "ERROR! fd=%d\n", g_io_channel_unix_get_fd( source ) );
 
 	closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond);
Index: protocols/ssl_bogus.c
===================================================================
--- protocols/ssl_bogus.c	(revision b5a22e33a1aa2500093e783e79de2f44bf53c150)
+++ protocols/ssl_bogus.c	(revision 7c0a4975a538ab75405e64919bbdfee51b898b2e)
@@ -28,5 +28,5 @@
 int ssl_errno;
 
-void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data )
+void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
 {
 	return( NULL );
Index: protocols/ssl_client.h
===================================================================
--- protocols/ssl_client.h	(revision b5a22e33a1aa2500093e783e79de2f44bf53c150)
+++ protocols/ssl_client.h	(revision 7c0a4975a538ab75405e64919bbdfee51b898b2e)
@@ -33,9 +33,10 @@
 extern int ssl_errno;
 
-typedef void (*SslInputFunction)(gpointer, void*, GaimInputCondition);
+typedef void (*ssl_input_function)(gpointer, void*, GaimInputCondition);
 
-G_MODULE_EXPORT void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data );
+G_MODULE_EXPORT void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data );
 G_MODULE_EXPORT int ssl_read( void *conn, char *buf, int len );
 G_MODULE_EXPORT int ssl_write( void *conn, const char *buf, int len );
 G_MODULE_EXPORT void ssl_disconnect( void *conn_ );
 G_MODULE_EXPORT int ssl_getfd( void *conn );
+G_MODULE_EXPORT GaimInputCondition ssl_getdirection( void *conn );
Index: protocols/ssl_gnutls.c
===================================================================
--- protocols/ssl_gnutls.c	(revision b5a22e33a1aa2500093e783e79de2f44bf53c150)
+++ protocols/ssl_gnutls.c	(revision 7c0a4975a538ab75405e64919bbdfee51b898b2e)
@@ -38,5 +38,5 @@
 struct scd
 {
-	SslInputFunction func;
+	ssl_input_function func;
 	gpointer data;
 	int fd;
@@ -51,5 +51,5 @@
 
 
-void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data )
+void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
 {
 	struct scd *conn = g_new0( struct scd, 1 );
@@ -117,7 +117,5 @@
 		if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED )
 		{
-			conn->inpa = gaim_input_add( conn->fd,
-			                             gnutls_record_get_direction( conn->session ) ?
-			                                 GAIM_INPUT_WRITE : GAIM_INPUT_READ,
+			conn->inpa = gaim_input_add( conn->fd, ssl_getdirection( conn ),
 			                             ssl_handshake, data );
 		}
@@ -145,4 +143,6 @@
 int ssl_read( void *conn, char *buf, int len )
 {
+	int st;
+	
 	if( !((struct scd*)conn)->established )
 	{
@@ -151,10 +151,17 @@
 	}
 	
-	return( gnutls_record_recv( ((struct scd*)conn)->session, buf, len ) );
-	
+	st = gnutls_record_recv( ((struct scd*)conn)->session, buf, len );
+	
+	ssl_errno = SSL_OK;
+	if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED )
+		ssl_errno = SSL_AGAIN;
+	
+	return st;
 }
 
 int ssl_write( void *conn, const char *buf, int len )
 {
+	int st;
+	
 	if( !((struct scd*)conn)->established )
 	{
@@ -163,5 +170,11 @@
 	}
 	
-	return( gnutls_record_send( ((struct scd*)conn)->session, buf, len ) );
+	st = gnutls_record_send( ((struct scd*)conn)->session, buf, len );
+	
+	ssl_errno = SSL_OK;
+	if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED )
+		ssl_errno = SSL_AGAIN;
+	
+	return st;
 }
 
@@ -184,2 +197,8 @@
 	return( ((struct scd*)conn)->fd );
 }
+
+GaimInputCondition ssl_getdirection( void *conn )
+{
+	return( gnutls_record_get_direction( ((struct scd*)conn)->session ) ?
+	        GAIM_INPUT_WRITE : GAIM_INPUT_READ );
+}
Index: protocols/ssl_nss.c
===================================================================
--- protocols/ssl_nss.c	(revision b5a22e33a1aa2500093e783e79de2f44bf53c150)
+++ protocols/ssl_nss.c	(revision 7c0a4975a538ab75405e64919bbdfee51b898b2e)
@@ -45,5 +45,5 @@
 struct scd
 {
-	SslInputFunction func;
+	ssl_input_function func;
 	gpointer data;
 	int fd;
@@ -91,5 +91,5 @@
 
 
-void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data )
+void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
 {
 	struct scd *conn = g_new0( struct scd, 1 );
Index: protocols/ssl_openssl.c
===================================================================
--- protocols/ssl_openssl.c	(revision b5a22e33a1aa2500093e783e79de2f44bf53c150)
+++ protocols/ssl_openssl.c	(revision 7c0a4975a538ab75405e64919bbdfee51b898b2e)
@@ -41,5 +41,5 @@
 struct scd
 {
-	SslInputFunction func;
+	ssl_input_function func;
 	gpointer data;
 	int fd;
@@ -54,5 +54,5 @@
 
 
-void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data )
+void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
 {
 	struct scd *conn = g_new0( struct scd, 1 );
Index: sock.h
===================================================================
--- sock.h	(revision b5a22e33a1aa2500093e783e79de2f44bf53c150)
+++ sock.h	(revision 7c0a4975a538ab75405e64919bbdfee51b898b2e)
@@ -1,2 +1,5 @@
+#include <errno.h>
+#include <fcntl.h>
+
 #ifndef _WIN32
 #include <unistd.h>
Index: url.c
===================================================================
--- url.c	(revision b5a22e33a1aa2500093e783e79de2f44bf53c150)
+++ url.c	(revision 7c0a4975a538ab75405e64919bbdfee51b898b2e)
@@ -2,5 +2,5 @@
   * BitlBee -- An IRC to other IM-networks gateway                     *
   *                                                                    *
-  * Copyright 2001-2004 Wilmer van der Gaast and others                *
+  * Copyright 2001-2005 Wilmer van der Gaast and others                *
   \********************************************************************/
 
@@ -30,5 +30,5 @@
 {
 	char s[MAX_STRING];
-	char *i, *j;
+	char *i;
 	
 	/* protocol://							*/
@@ -40,5 +40,7 @@
 	else
 	{
-		if( g_strncasecmp( set_url, "http", i - set_url ) == 0 )
+		if( g_strncasecmp( set_url, "https", i - set_url ) == 0 )
+			url->proto = PROTO_HTTPS;
+		else if( g_strncasecmp( set_url, "http", i - set_url ) == 0 )
 			url->proto = PROTO_HTTP;
 		else if( g_strncasecmp( set_url, "socks4", i - set_url ) == 0 )
@@ -56,31 +58,12 @@
 	if( ( i = strchr( s, '/' ) ) == NULL )
 	{
-		strcpy( url->dir, "/" );
+		strcpy( url->file, "/" );
 	}
 	else
 	{
+		strncpy( url->file, i, MAX_STRING );
 		*i = 0;
-		g_snprintf( url->dir, MAX_STRING, "/%s", i + 1 );
-		if( url->proto == PROTO_HTTP )
-			http_encode( url->dir );
 	}
 	strncpy( url->host, s, MAX_STRING );
-	j = strchr( url->dir, '?' );
-	if( j != NULL )
-		*j = 0;
-	i = strrchr( url->dir, '/' );
-	*i = 0;
-	if( j != NULL )
-		*j = '?';
-	if( i == NULL )
-	{
-		strcpy( url->file, url->dir );
-		strcpy( url->dir, "/" );
-	}
-	else
-	{
-		strcpy( url->file, i + 1 );
-		strcat( url->dir, "/" );
-	}
 	
 	/* Check for username in host field				*/
@@ -96,13 +79,5 @@
 	else
 	{
-		if( url->proto == PROTO_FTP )
-		{
-			strcpy( url->user, "anonymous" );
-			strcpy( url->pass, "-p.artmaps@lintux.cx" );
-		}
-		else
-		{
-			*url->user = *url->pass = 0;
-		}
+		*url->user = *url->pass = 0;
 	}
 	
@@ -117,11 +92,12 @@
 	{
 		*i = 0;
-		sscanf( i + 1, "%i", &url->port );
+		sscanf( i + 1, "%d", &url->port );
 	}
-	/* Take default port numbers from /etc/services			*/
 	else
 	{
 		if( url->proto == PROTO_HTTP )
-			url->port = 8080;
+			url->port = 80;
+		else if( url->proto == PROTO_HTTPS )
+			url->port = 443;
 		else if( url->proto == PROTO_SOCKS4 || url->proto == PROTO_SOCKS4 )
 			url->port = 1080;
Index: url.h
===================================================================
--- url.h	(revision b5a22e33a1aa2500093e783e79de2f44bf53c150)
+++ url.h	(revision 7c0a4975a538ab75405e64919bbdfee51b898b2e)
@@ -26,6 +26,6 @@
 #include "bitlbee.h"
 
-#define PROTO_FTP		1
 #define PROTO_HTTP		2
+#define PROTO_HTTPS		5
 #define PROTO_SOCKS4	3
 #define PROTO_SOCKS5	4
@@ -37,5 +37,4 @@
 	int port;
 	char host[MAX_STRING];
-	char dir[MAX_STRING];
 	char file[MAX_STRING];
 	char user[MAX_STRING];
