diff options
Diffstat (limited to 'protocols/msn')
-rw-r--r-- | protocols/msn/Makefile | 8 | ||||
-rw-r--r-- | protocols/msn/msn.h | 2 | ||||
-rw-r--r-- | protocols/msn/ns.c | 2 | ||||
-rw-r--r-- | protocols/msn/passport.c | 308 | ||||
-rw-r--r-- | protocols/msn/passport.h | 6 | ||||
-rw-r--r-- | protocols/msn/sb.c | 26 | ||||
-rw-r--r-- | protocols/msn/tables.c | 8 |
7 files changed, 141 insertions, 219 deletions
diff --git a/protocols/msn/Makefile b/protocols/msn/Makefile index e6620323..873c831c 100644 --- a/protocols/msn/Makefile +++ b/protocols/msn/Makefile @@ -15,7 +15,7 @@ CFLAGS += -Wall LFLAGS += -r # [SH] Phony targets -all: msnn.o +all: msn_mod.o .PHONY: all clean distclean @@ -32,8 +32,8 @@ $(objects): %.o: %.c @echo '*' Compiling $< @$(CC) -c $(CFLAGS) $< -o $@ -msnn.o: $(objects) - @echo '*' Linking msnn.o - @$(LD) $(LFLAGS) $(objects) -o msnn.o +msn_mod.o: $(objects) + @echo '*' Linking msn_mod.o + @$(LD) $(LFLAGS) $(objects) -o msn_mod.o diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 61231d8a..c8c7a788 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -126,6 +126,8 @@ struct msn_handler_data /* Bitfield values for msn_status_code.flags */ #define STATUS_FATAL 1 #define STATUS_SB_FATAL 2 +#define STATUS_SB_IM_SPARE 4 /* Make one-to-one conversation switchboard available again, invite failed. */ +#define STATUS_SB_CHAT_SPARE 8 /* Same, but also for groupchats (not used yet). */ int msn_chat_id; extern struct msn_away_state msn_away_state_list[]; diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index f1bda1a4..2d90b2f3 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -207,7 +207,7 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) if( num_parts == 5 && strcmp( cmd[2], "TWN" ) == 0 && strcmp( cmd[3], "S" ) == 0 ) { /* 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" ); signoff( gc ); diff --git a/protocols/msn/passport.c b/protocols/msn/passport.c index 640126a0..34703432 100644 --- a/protocols/msn/passport.c +++ b/protocols/msn/passport.c @@ -19,7 +19,7 @@ * */ -#include "ssl_client.h" +#include "http_client.h" #include "passport.h" #include "msn.h" #include "bitlbee.h" @@ -30,34 +30,91 @@ 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 destroy_reply( struct passport_reply *rep ); +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_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; + + server = g_strdup( prd_cached ); + dummy = strchr( server, '/' ); + + if( dummy == NULL ) { - return( passport_retrieve_dalogin( data, func, header ) ); + 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 ) || !req->finished || !req->reply_headers ) + { + destroy_reply( rep ); + return; + } + + if( req->status_code == 200 ) + { + char *dummy; + + if( ( dummy = strstr( req->reply_headers, "from-PP='" ) ) ) + { + char *responseend; + + dummy += strlen( "from-PP='" ); + responseend = strchr( dummy, '\'' ); + if( responseend ) + *responseend = 0; + + rep->result = g_strdup( dummy ); + } + } + + rep->func( rep ); + destroy_reply( rep ); +} -static char *passport_create_header( char *reply, char *email, char *pwd ) +static char *passport_create_header( char *cookie, char *email, char *pwd ) { char *buffer = g_new0( char, 2048 ); char *currenttoken; @@ -71,7 +128,7 @@ static char *passport_create_header( char *reply, char *email, char *pwd ) strcpy( pwd_enc, pwd ); http_encode( pwd_enc ); - currenttoken = strstr( reply, "lc=" ); + currenttoken = strstr( cookie, "lc=" ); if( currenttoken == NULL ) return( NULL ); @@ -87,227 +144,68 @@ static char *passport_create_header( char *reply, char *email, char *pwd ) return( buffer ); } - -static int passport_retrieve_dalogin( gpointer data, gpointer func, char *header ) +#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 ); - void *ssl; + struct http_request *req; rep->data = data; rep->func = func; rep->header = header; - ssl = ssl_connect( "nexus.passport.com", 443, passport_retrieve_dalogin_connected, rep ); + req = http_dorequest( "nexus.passport.com", 443, 1, PPR_REQUEST, passport_retrieve_dalogin_ready, rep ); - if( !ssl ) + if( !req ) destroy_reply( rep ); - return( ssl != NULL ); + return( req != 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 ) +static void passport_retrieve_dalogin_ready( struct http_request *req ) { - int ret; - char buffer[PPR_BUFFERSIZE+1]; - struct passport_reply *rep = data; + struct passport_reply *rep = req->data; + char *dalogin; + char *urlend; - if( !g_slist_find( msn_connections, rep->data ) ) + if( !g_slist_find( msn_connections, rep->data ) || !req->finished || !req->reply_headers ) { - 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 ) ); + dalogin = strstr( req->reply_headers, "DALogin=" ); - if( ( ret = ssl_read( ssl, buffer, PPR_BUFFERSIZE ) ) <= 0 ) - { + if( !dalogin ) goto failure; - } - - { - char *dalogin = strstr( buffer, "DALogin=" ); - char *urlend; - - 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 ); - } + dalogin += strlen( "DALogin=" ); + urlend = strchr( dalogin, ',' ); + if( urlend ) + *urlend = 0; - 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; + /* strip the http(s):// part from the url */ + urlend = strstr( urlend, "://" ); + if( urlend ) + dalogin = urlend + strlen( "://" ); - if( !g_slist_find( msn_connections, rep->data ) ) - { - if( ssl ) ssl_disconnect( ssl ); - destroy_reply( rep ); - return; - } + if( prd_cached == NULL ) + prd_cached = g_strdup( dalogin ); - if( !ssl ) + if( passport_get_id_real( rep->func, rep->data, rep->header ) ) { - 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='" ) ) ) - { - char *responseend; - - dummy += strlen( "from-PP='" ); - responseend = strchr( dummy, '\'' ); - if( responseend ) - *responseend = 0; - - rep->result = g_strdup( dummy ); - } - } - -end: - ssl_disconnect( ssl ); +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 ); } diff --git a/protocols/msn/passport.h b/protocols/msn/passport.h index 63fef2e9..f7e6ebb6 100644 --- a/protocols/msn/passport.h +++ b/protocols/msn/passport.h @@ -34,14 +34,12 @@ 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__ */ diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index 2f4d05d5..11728f03 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -521,11 +521,35 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts ) msn_sb_destroy( sb ); return( 0 ); } - else if( err->flags & STATUS_FATAL ) + if( err->flags & STATUS_FATAL ) { signoff( gc ); return( 0 ); } + if( err->flags & STATUS_SB_IM_SPARE ) + { + if( sb->who ) + { + struct msn_message *m; + GSList *l; + + /* Apparently some invitation failed. We might want to use this + board later, so keep it as a spare. */ + g_free( sb->who ); + sb->who = NULL; + + /* Also clear the msgq, otherwise someone else might get them. */ + for( l = sb->msgq; l; l = l->next ) + { + m = l->data; + g_free( m->who ); + g_free( m->text ); + g_free( m ); + } + g_slist_free( sb->msgq ); + sb->msgq = NULL; + } + } } else { diff --git a/protocols/msn/tables.c b/protocols/msn/tables.c index 0cd80c01..2741048a 100644 --- a/protocols/msn/tables.c +++ b/protocols/msn/tables.c @@ -79,12 +79,12 @@ struct msn_status_code msn_status_code_list[] = { 205, "Invalid (non-existent) handle", 0 }, { 206, "Domain name missing", 0 }, { 207, "Already logged in", 0 }, - { 208, "Invalid handle", 0 }, + { 208, "Invalid handle", STATUS_SB_IM_SPARE }, { 209, "Forbidden nickname", 0 }, { 210, "Buddy list too long", 0 }, { 215, "Handle is already in list", 0 }, - { 216, "Handle is not in list", 0 }, - { 217, "Person is off-line or non-existent", 0 }, + { 216, "Handle is not in list", STATUS_SB_IM_SPARE }, + { 217, "Person is off-line or non-existent", STATUS_SB_IM_SPARE }, { 218, "Already in that mode", 0 }, { 219, "Handle is already in opposite list", 0 }, { 223, "Too many groups", 0 }, @@ -117,7 +117,7 @@ struct msn_status_code msn_status_code_list[] = { 710, "Invalid CVR parameters", STATUS_FATAL }, { 711, "Write is blocking", STATUS_FATAL }, { 712, "Session is overloaded", STATUS_FATAL }, - { 713, "Calling too rapidly", 0 }, + { 713, "Calling too rapidly", STATUS_SB_IM_SPARE }, { 714, "Too many sessions", STATUS_FATAL }, { 715, "Not expected/Invalid argument/action", 0 }, { 717, "Bad friend file", STATUS_FATAL }, |