From bc676acb5f316f0688ab9f99dd2b73315a6ad50c Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 16 Sep 2012 01:09:58 +0100 Subject: MSNP18 code. It logs in now but otherwise doesn't work all too well. --- protocols/msn/msn.c | 8 ++------ protocols/msn/msn.h | 15 +++++++++++---- protocols/msn/ns.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- protocols/msn/sb.c | 5 +---- 4 files changed, 63 insertions(+), 15 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 03f28422..b05a2b85 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -231,13 +231,9 @@ static void msn_chat_msg( struct groupchat *c, char *message, int flags ) static void msn_chat_invite( struct groupchat *c, char *who, char *message ) { struct msn_switchboard *sb = msn_sb_by_chat( c ); - char buf[1024]; if( sb ) - { - g_snprintf( buf, sizeof( buf ), "CAL %d %s\r\n", ++sb->trId, who ); - msn_sb_write( sb, buf, strlen( buf ) ); - } + msn_sb_write( sb, "CAL %d %s\r\n", ++sb->trId, who ); } static void msn_chat_leave( struct groupchat *c ) @@ -245,7 +241,7 @@ static void msn_chat_leave( struct groupchat *c ) struct msn_switchboard *sb = msn_sb_by_chat( c ); if( sb ) - msn_sb_write( sb, "OUT\r\n", 5 ); + msn_sb_write( sb, "OUT\r\n" ); } static struct groupchat *msn_chat_with( struct im_connection *ic, char *who ) diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index bf7cdfa8..f3e5b9b9 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -52,10 +52,15 @@ #define MSNP11_PROD_ID "PROD01065C%ZFN6F" */ +/* <= BitlBee 3.0.5 #define MSNP11_PROD_KEY "ILTXC!4IXB5FB*PX" #define MSNP11_PROD_ID "PROD0119GSJUC$18" -#define MSNP_VER "MSNP15" -#define MSNP_BUILD "8.5.1288" +*/ + +#define MSNP11_PROD_KEY "C1BX{V4W}Q3*10SM" +#define MSNP11_PROD_ID "PROD0120PW!CCV9@" +#define MSNP_VER "MSNP18" +#define MSNP_BUILD "14.0.8117.416" #define MSN_SB_NEW -24062002 @@ -221,12 +226,14 @@ extern GSList *msn_connections; extern GSList *msn_switchboards; /* ns.c */ -int msn_ns_write( struct im_connection *ic, int fd, const char *fmt, ... ); +int msn_ns_write( struct im_connection *ic, int fd, const char *fmt, ... ) G_GNUC_PRINTF( 3, 4 ); gboolean msn_ns_connect( struct im_connection *ic, struct msn_handler_data *handler, const char *host, int port ); void msn_ns_close( struct msn_handler_data *handler ); void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error ); void msn_auth_got_contact_list( struct im_connection *ic ); int msn_ns_finish_login( struct im_connection *ic ); +int msn_ns_sendmessage( struct im_connection *ic, struct bee_user *bu, const char *text ); +void msn_ns_oim_send_queue( struct im_connection *ic, GSList **msgq ); /* msn_util.c */ int msn_logged_in( struct im_connection *ic ); @@ -249,7 +256,7 @@ const struct msn_away_state *msn_away_state_by_name( char *name ); const struct msn_status_code *msn_status_by_number( int number ); /* sb.c */ -int msn_sb_write( struct msn_switchboard *sb, const char *fmt, ... ); +int msn_sb_write( struct msn_switchboard *sb, const char *fmt, ... ) G_GNUC_PRINTF( 2, 3 );; struct msn_switchboard *msn_sb_create( struct im_connection *ic, char *host, int port, char *key, int session ); struct msn_switchboard *msn_sb_by_handle( struct im_connection *ic, char *handle ); struct msn_switchboard *msn_sb_by_chat( struct groupchat *c ); diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 5436270e..4dac75c5 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -756,7 +756,7 @@ void msn_auth_got_passport_token( struct im_connection *ic, const char *token, c if( token ) { - msn_ns_write( ic, -1, "USR %d SSO S %s %s\r\n", ++md->trId, md->tokens[0], token ); + msn_ns_write( ic, -1, "USR %d SSO S %s %s {7535ef7c-ff92-11e1-8069-50e5493b06de}\r\n", ++md->trId, md->tokens[0], token ); } else { @@ -885,3 +885,51 @@ int msn_ns_finish_login( struct im_connection *ic ) return 1; } + +int msn_ns_sendmessage( struct im_connection *ic, bee_user_t *bu, const char *text ) +{ + struct msn_data *md = ic->proto_data; + char *buf; + + if( strncmp( text, "\r\r\r", 3 ) == 0 ) + /* Err. Shouldn't happen but I guess it can. Don't send others + any of the "SHAKE THAT THING" messages. :-D */ + return 1; + + buf = g_strdup_printf( "%s%s", MSN_MESSAGE_HEADERS, text ); + + if( msn_ns_write( ic, -1, "UUM %d %s %d %d %zd\r\n%s", + ++md->trId, bu->handle, + 1, /* type == MSN offline message */ + 1, /* type == IM (not nudge/typing) */ + strlen( buf ), buf ) ) + return 1; + else + return 0; +} + +void msn_ns_oim_send_queue( struct im_connection *ic, GSList **msgq ) +{ + GSList *l; + + for( l = *msgq; l; l = l->next ) + { + struct msn_message *m = l->data; + bee_user_t *bu = bee_user_by_handle( ic->bee, ic, m->who ); + + if( bu ) + if( !msn_ns_sendmessage( ic, bu, m->text ) ) + return; + } + + while( *msgq != NULL ) + { + struct msn_message *m = (*msgq)->data; + + g_free( m->who ); + g_free( m->text ); + g_free( m ); + + *msgq = g_slist_remove( *msgq, m ); + } +} diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index 45e74cb0..14465c67 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -628,12 +628,9 @@ static int msn_sb_command( struct msn_handler_data *handler, char **cmd, int num /* If the person is offline, send an offline message instead, and don't report an error. */ - /* TODO: Support for OIMs that works. (#874) */ - /* if( num == 217 ) - msn_soap_oim_send_queue( ic, &sb->msgq ); + msn_ns_oim_send_queue( ic, &sb->msgq ); else - */ imcb_error( ic, "Error reported by switchboard server: %s", err->text ); if( err->flags & STATUS_SB_FATAL ) -- cgit v1.2.3 From f9258aead615ef9b87baa1754777fd5faf867fe1 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 16 Sep 2012 12:52:35 +0100 Subject: Generate a machine UUID instead of using a hardcoded one. --- protocols/msn/msn.c | 3 ++- protocols/msn/msn.h | 1 + protocols/msn/ns.c | 23 +++++++++++++++++++++-- 3 files changed, 24 insertions(+), 3 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index b05a2b85..59adec62 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* MSN module - Main file; functions to be called from BitlBee */ @@ -97,6 +97,7 @@ static void msn_logout( struct im_connection *ic ) g_free( md->tokens[i] ); g_free( md->lock_key ); g_free( md->pp_policy ); + g_free( md->uuid ); while( md->groups ) { diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index f3e5b9b9..4d2d0fdd 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -122,6 +122,7 @@ struct msn_data int trId; char *tokens[4]; char *lock_key, *pp_policy; + char *uuid; GSList *msgq, *grpq, *soapq; GSList *switchboards; diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 4dac75c5..b613b557 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* MSN module - Notification server callbacks */ @@ -24,9 +24,11 @@ */ #include +#include #include "nogaim.h" #include "msn.h" #include "md5.h" +#include "sha1.h" #include "soap.h" #include "xmltree.h" @@ -110,6 +112,23 @@ static gboolean msn_ns_connected( gpointer data, gint source, b_input_condition handler->rxlen = 0; handler->rxq = g_new0( char, 1 ); + if( md->uuid == NULL ) + { + struct utsname name; + sha1_state_t sha[1]; + + /* UUID == SHA1("BitlBee" + my hostname + MSN username) */ + sha1_init( sha ); + sha1_append( sha, (void*) "BitlBee", 7 ); + if( uname( &name ) == 0 ) + { + sha1_append( sha, (void*) name.nodename, strlen( name.nodename ) ); + } + sha1_append( sha, (void*) ic->acc->user, strlen( ic->acc->user ) ); + md->uuid = sha1_random_uuid( sha ); + memcpy( md->uuid, "b171be3e", 8 ); /* :-P */ + } + if( msn_ns_write( ic, source, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER ) ) { handler->inpa = b_input_add( handler->fd, B_EV_IO_READ, msn_ns_callback, handler ); @@ -756,7 +775,7 @@ void msn_auth_got_passport_token( struct im_connection *ic, const char *token, c if( token ) { - msn_ns_write( ic, -1, "USR %d SSO S %s %s {7535ef7c-ff92-11e1-8069-50e5493b06de}\r\n", ++md->trId, md->tokens[0], token ); + msn_ns_write( ic, -1, "USR %d SSO S %s %s {%s}\r\n", ++md->trId, md->tokens[0], token, md->uuid ); } else { -- cgit v1.2.3 From 080c43a862bca535e51682423afc9d0f75ea1d02 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 16 Sep 2012 14:52:19 +0100 Subject: Some more tweaks: Should show up online now, and be able to send and receive messages. Seeing online state is still a problem due to the protocol#: gunk. --- protocols/msn/msn.c | 24 +++++++++++++++++++++--- protocols/msn/msn.h | 3 +++ protocols/msn/ns.c | 4 ++-- protocols/msn/sb.c | 21 ++++++++++++++++++--- 4 files changed, 44 insertions(+), 8 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 59adec62..8e10e202 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -190,11 +190,29 @@ static void msn_set_away( struct im_connection *ic, char *state, char *message ) else if( ( md->away_state = msn_away_state_by_name( state ) ) == NULL ) md->away_state = msn_away_state_list + 1; - if( !msn_ns_write( ic, -1, "CHG %d %s\r\n", ++md->trId, md->away_state->code ) ) + if( !msn_ns_write( ic, -1, "CHG %d %s %d:%02d\r\n", ++md->trId, md->away_state->code, MSN_CAP1, MSN_CAP2 ) ) return; - uux = g_markup_printf_escaped( "%s" - "", message ? message : "" ); + uux = g_markup_printf_escaped( "%d:%02d" + "", + MSN_CAP1, MSN_CAP2 ); + msn_ns_write( ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux ); + g_free( uux ); + + uux = g_markup_printf_escaped( "%s" + "%s%d" + "%s", + md->uuid, + strcmp( md->away_state->code, "IDL" ) ? "false" : "true", + 1, /* ? */ + md->away_state->code ); + msn_ns_write( ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux ); + g_free( uux ); + + uux = g_markup_printf_escaped( "%s" + "" + "%s", + message ? message : "", md->uuid ); msn_ns_write( ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux ); g_free( uux ); } diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 4d2d0fdd..ed6db6f0 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -64,6 +64,9 @@ #define MSN_SB_NEW -24062002 +#define MSN_CAP1 0xC000 +#define MSN_CAP2 0x0000 + #define MSN_MESSAGE_HEADERS "MIME-Version: 1.0\r\n" \ "Content-Type: text/plain; charset=UTF-8\r\n" \ "User-Agent: BitlBee " BITLBEE_VERSION "\r\n" \ diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index b613b557..f8f18c80 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -573,8 +573,8 @@ static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num else if( strcmp( cmd[0], "UBX" ) == 0 ) { /* Status message. */ - if( num_parts >= 4 ) - handler->msglen = atoi( cmd[3] ); + if( num_parts >= 3 ) + handler->msglen = atoi( cmd[2] ); } else if( strcmp( cmd[0], "NOT" ) == 0 ) { diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index 14465c67..c8e97433 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -307,6 +307,7 @@ gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ) { struct msn_switchboard *sb = data; struct im_connection *ic; + struct msn_data *md; char buf[1024]; /* Are we still alive? */ @@ -314,6 +315,7 @@ gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ) return FALSE; ic = sb->ic; + md = ic->proto_data; if( source != sb->fd ) { @@ -331,9 +333,9 @@ gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ) sb->handler->exec_message = msn_sb_message; if( sb->session == MSN_SB_NEW ) - g_snprintf( buf, sizeof( buf ), "USR %d %s %s\r\n", ++sb->trId, ic->acc->user, sb->key ); + g_snprintf( buf, sizeof( buf ), "USR %d %s;{%s} %s\r\n", ++sb->trId, ic->acc->user, md->uuid, sb->key ); else - g_snprintf( buf, sizeof( buf ), "ANS %d %s %s %d\r\n", ++sb->trId, ic->acc->user, sb->key, sb->session ); + g_snprintf( buf, sizeof( buf ), "ANS %d %s;{%s} %s %d\r\n", ++sb->trId, ic->acc->user, md->uuid, sb->key, sb->session ); if( msn_sb_write( sb, "%s", buf ) ) sb->inp = b_input_add( sb->fd, B_EV_IO_READ, msn_sb_callback, sb ); @@ -461,7 +463,12 @@ static int msn_sb_command( struct msn_handler_data *handler, char **cmd, int num sb->who = NULL; } - imcb_chat_add_buddy( sb->chat, cmd[4] ); + /* For as much as I understand this MPOP stuff now, a + switchboard has two (or more) roster entries per + participant. One "bare JID" and one JID;UUID. Ignore + the latter. */ + if( !strchr( cmd[4], ';' ) ) + imcb_chat_add_buddy( sb->chat, cmd[4] ); if( num == tot ) { @@ -506,6 +513,10 @@ static int msn_sb_command( struct msn_handler_data *handler, char **cmd, int num return( 0 ); } + /* See IRO above. Handle "bare JIDs" only. */ + if( strchr( cmd[1], ';' ) ) + return 1; + if( sb->who && g_strcasecmp( cmd[1], sb->who ) == 0 ) { /* The user we wanted to talk to is finally there, let's send the queued messages then. */ @@ -540,6 +551,10 @@ static int msn_sb_command( struct msn_handler_data *handler, char **cmd, int num return( st ); } + else if( strcmp( cmd[1], ic->acc->user ) == 0 ) + { + /* Well, gee thanks. Thanks for letting me know I've arrived.. */ + } else if( sb->who ) { debug( "Converting chat with %s to a groupchat because %s joined the session.", sb->who, cmd[1] ); -- cgit v1.2.3 From 79bb7e412d28e8afe734762e8bd3e4c488a53562 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 16 Sep 2012 18:40:44 +0100 Subject: Online status should be read properly now. --- protocols/msn/msn.h | 5 ++-- protocols/msn/msn_util.c | 10 ++++++- protocols/msn/ns.c | 70 ++++++++++++++++++++---------------------------- protocols/msn/sb.c | 4 +-- 4 files changed, 43 insertions(+), 46 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index ed6db6f0..7c23f282 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* MSN module */ @@ -252,6 +252,7 @@ gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ ); struct msn_group *msn_group_by_name( struct im_connection *ic, const char *name ); struct msn_group *msn_group_by_id( struct im_connection *ic, const char *id ); int msn_ns_set_display_name( struct im_connection *ic, const char *value ); +const char *msn_normalize_handle( const char *handle ); /* tables.c */ const struct msn_away_state *msn_away_state_by_number( int number ); @@ -262,7 +263,7 @@ const struct msn_status_code *msn_status_by_number( int number ); /* sb.c */ int msn_sb_write( struct msn_switchboard *sb, const char *fmt, ... ) G_GNUC_PRINTF( 2, 3 );; struct msn_switchboard *msn_sb_create( struct im_connection *ic, char *host, int port, char *key, int session ); -struct msn_switchboard *msn_sb_by_handle( struct im_connection *ic, char *handle ); +struct msn_switchboard *msn_sb_by_handle( struct im_connection *ic, const char *handle ); struct msn_switchboard *msn_sb_by_chat( struct groupchat *c ); struct msn_switchboard *msn_sb_spare( struct im_connection *ic ); int msn_sb_sendmessage( struct msn_switchboard *sb, char *text ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index d5a74a47..f2f67eb3 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* MSN module - Miscellaneous utilities */ @@ -536,3 +536,11 @@ int msn_ns_set_display_name( struct im_connection *ic, const char *value ) and won't give proper feedback yet if it doesn't. */ return msn_ns_write( ic, -1, "PRP %d MFN %s\r\n", ++md->trId, fn ); } + +const char *msn_normalize_handle( const char *handle ) +{ + if( strncmp( handle, "1:", 2 ) == 0 ) + return handle + 2; + else + return handle; +} diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index f8f18c80..4f80f490 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -371,9 +371,11 @@ static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num g_free( resp ); return st; } - else if( strcmp( cmd[0], "ILN" ) == 0 ) + else if( strcmp( cmd[0], "ILN" ) == 0 || strcmp( cmd[0], "NLN" ) == 0 ) { const struct msn_away_state *st; + const char *handle; + int cap = 0; if( num_parts < 6 ) { @@ -381,59 +383,45 @@ static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num imc_logout( ic, TRUE ); return( 0 ); } + /* ILN and NLN are more or less the same, except ILN has a trId + at the start, and NLN has a capability field at the end. + Does ILN still exist BTW? */ + if( cmd[0][1] == 'I' ) + cmd ++; + else + cap = atoi( cmd[4] ); + + handle = msn_normalize_handle( cmd[2] ); + if( strcmp( handle, ic->acc->user ) == 0 ) + return 1; /* That's me! */ - http_decode( cmd[5] ); - imcb_rename_buddy( ic, cmd[3], cmd[5] ); + http_decode( cmd[3] ); + imcb_rename_buddy( ic, handle, cmd[3] ); - st = msn_away_state_by_code( cmd[2] ); + st = msn_away_state_by_code( cmd[1] ); if( !st ) { /* FIXME: Warn/Bomb about unknown away state? */ st = msn_away_state_list + 1; } - imcb_buddy_status( ic, cmd[3], OPT_LOGGED_IN | - ( st != msn_away_state_list ? OPT_AWAY : 0 ), + imcb_buddy_status( ic, handle, OPT_LOGGED_IN | + ( st != msn_away_state_list ? OPT_AWAY : 0 ) | + ( cap & 1 ? OPT_MOBILE : 0 ), st->name, NULL ); + + msn_sb_stop_keepalives( msn_sb_by_handle( ic, handle ) ); } else if( strcmp( cmd[0], "FLN" ) == 0 ) { + const char *handle; + if( cmd[1] == NULL ) return 1; - imcb_buddy_status( ic, cmd[1], 0, NULL, NULL ); - - msn_sb_start_keepalives( msn_sb_by_handle( ic, cmd[1] ), TRUE ); - } - else if( strcmp( cmd[0], "NLN" ) == 0 ) - { - const struct msn_away_state *st; - int cap; - - if( num_parts < 6 ) - { - imcb_error( ic, "Syntax error" ); - imc_logout( ic, TRUE ); - return( 0 ); - } - - http_decode( cmd[4] ); - cap = atoi( cmd[5] ); - imcb_rename_buddy( ic, cmd[2], cmd[4] ); - - st = msn_away_state_by_code( cmd[1] ); - if( !st ) - { - /* FIXME: Warn/Bomb about unknown away state? */ - st = msn_away_state_list + 1; - } - - imcb_buddy_status( ic, cmd[2], OPT_LOGGED_IN | - ( st != msn_away_state_list ? OPT_AWAY : 0 ) | - ( cap & 1 ? OPT_MOBILE : 0 ), - st->name, NULL ); - - msn_sb_stop_keepalives( msn_sb_by_handle( ic, cmd[2] ) ); + handle = msn_normalize_handle( cmd[1] ); + imcb_buddy_status( ic, handle, 0, NULL, NULL ); + msn_sb_start_keepalives( msn_sb_by_handle( ic, handle ), TRUE ); } else if( strcmp( cmd[0], "RNG" ) == 0 ) { @@ -480,7 +468,7 @@ static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num } else { - sb->who = g_strdup( cmd[5] ); + sb->who = g_strdup( msn_normalize_handle( cmd[5] ) ); } } else if( strcmp( cmd[0], "OUT" ) == 0 ) @@ -706,7 +694,7 @@ static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msgl ( psm = xt_find_node( ubx->children, "PSM" ) ) ) psm_text = psm->text; - imcb_buddy_status_msg( ic, cmd[1], psm_text ); + imcb_buddy_status_msg( ic, msn_normalize_handle( cmd[1] ), psm_text ); xt_free_node( ubx ); } else if( strcmp( cmd[0], "ADL" ) == 0 ) diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index c8e97433..a1e07b73 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2010 Wilmer van der Gaast and others * + * Copyright 2002-2012 Wilmer van der Gaast and others * \********************************************************************/ /* MSN module - Switchboard server callbacks and utilities */ @@ -121,7 +121,7 @@ struct msn_switchboard *msn_sb_create( struct im_connection *ic, char *host, int return( sb ); } -struct msn_switchboard *msn_sb_by_handle( struct im_connection *ic, char *handle ) +struct msn_switchboard *msn_sb_by_handle( struct im_connection *ic, const char *handle ) { struct msn_data *md = ic->proto_data; struct msn_switchboard *sb; -- cgit v1.2.3 From e9caacd00fc7f7682664d29567a5b7dcfbde7479 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 16 Sep 2012 19:08:15 +0100 Subject: Don't accidentally create groupchats for 1:1 chats. --- protocols/msn/sb.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index a1e07b73..9c015a9c 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -454,23 +454,31 @@ static int msn_sb_command( struct msn_handler_data *handler, char **cmd, int num { char buf[1024]; - if( num == 1 ) - { - g_snprintf( buf, sizeof( buf ), "MSN groupchat session %d", sb->session ); - sb->chat = imcb_chat_new( ic, buf ); - - g_free( sb->who ); - sb->who = NULL; - } - /* For as much as I understand this MPOP stuff now, a switchboard has two (or more) roster entries per participant. One "bare JID" and one JID;UUID. Ignore the latter. */ if( !strchr( cmd[4], ';' ) ) - imcb_chat_add_buddy( sb->chat, cmd[4] ); + { + /* HACK: Since even 1:1 chats now have >2 participants + (ourselves included) it gets hard to tell them apart + from rooms. Let's hope this is enough: */ + if( sb->chat == NULL && num != tot ) + { + g_snprintf( buf, sizeof( buf ), "MSN groupchat session %d", sb->session ); + sb->chat = imcb_chat_new( ic, buf ); + + g_free( sb->who ); + sb->who = NULL; + } + + if( sb->chat ) + imcb_chat_add_buddy( sb->chat, cmd[4] ); + } - if( num == tot ) + /* We have the full roster, start showing the channel to + the user. */ + if( num == tot && sb->chat ) { imcb_chat_add_buddy( sb->chat, ic->acc->user ); } -- cgit v1.2.3 From fe79de663c230f7d4b525a5052da39b1d10c3b9d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 16 Sep 2012 21:42:11 +0100 Subject: One more semicolon check (BYE command). --- protocols/msn/sb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index 9c015a9c..1cd1c743 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -635,7 +635,7 @@ static int msn_sb_command( struct msn_handler_data *handler, char **cmd, int num as a spare for a next conversation sounds more sane to me. The server will clean it up when it's idle for too long. */ } - else if( sb->chat ) + else if( sb->chat && !strchr( cmd[1], ';' ) ) { imcb_chat_remove_buddy( sb->chat, cmd[1], "" ); } -- cgit v1.2.3 From a325ebd591a7c54d5fc34a2ac313d0a723f54e05 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 16 Sep 2012 22:44:09 +0100 Subject: Notification on incoming offline messages. Life is too short to implement the SOAP code to actually fetch them but at least tell the user that s/he received something. --- protocols/msn/ns.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 4f80f490..a4785eb2 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -674,7 +674,57 @@ static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msgl } else if( g_strncasecmp( ct, "text/x-msmsgsactivemailnotification", 35 ) == 0 ) { - /* Sorry, but this one really is *USELESS* */ + } + else if( g_strncasecmp( ct, "text/x-msmsgsinitialmdatanotification", 37 ) == 0 || + g_strncasecmp( ct, "text/x-msmsgsoimnotification", 28 ) == 0 ) + { + /* We received an offline message. Or at least notification + that there is one waiting for us. Fetching the message(s) + and purging them from the server is a lot of SOAPy work + not worth doing IMHO. Also I thought it was possible to + have the notification server send them directly, I was + pretty sure I saw Pidgin do it.. + + At least give a notification for now, seems like a + reasonable thing to do. Only problem is, they'll keep + coming back at login time until you read them using a + different client. :-( */ + + char *xml = get_rfc822_header( body, "Mail-Data:", blen ); + struct xt_node *md, *m; + + if( !xml ) + return 1; + md = xt_from_string( xml ); + if( !md ) + return 1; + + for( m = md->children; ( m = xt_find_node( m, "M" ) ); m = m->next ) + { + struct xt_node *e = xt_find_node( m->children, "E" ); + struct xt_node *rt = xt_find_node( m->children, "RT" ); + struct tm tp; + time_t msgtime = 0; + + if( !e || !e->text ) + continue; + + memset( &tp, 0, sizeof( tp ) ); + if( rt && rt->text && + sscanf( rt->text, "%4d-%2d-%2dT%2d:%2d:%2d.", + &tp.tm_year, &tp.tm_mon, &tp.tm_mday, + &tp.tm_hour, &tp.tm_min, &tp.tm_sec ) == 6 ) + { + tp.tm_year -= 1900; + tp.tm_mon --; + msgtime = mktime_utc( &tp ); + + } + imcb_buddy_msg( ic, e->text, "<< \002BitlBee\002 - Received offline message. BitlBee can't show these. >>", 0, msgtime ); + } + + g_free( xml ); + xt_free_node( md ); } else { -- cgit v1.2.3 From 6bef2110ddeb9e1f8e8233a4e61b8917fb939b29 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 22 Sep 2012 13:55:02 +0100 Subject: Fixed syntax error introduced by latest merge. --- protocols/msn/ns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index f2fc561f..a90c8a9d 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -695,7 +695,7 @@ static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msgl if( !xml ) return 1; - md = xt_from_string( xml ); + md = xt_from_string( xml, 0 ); if( !md ) return 1; -- cgit v1.2.3 From 3901b5dc7145de0db36d4a8820836daf91febc24 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Tue, 25 Sep 2012 23:48:56 +0100 Subject: Support for receiving messages via the NS (UBM command). --- protocols/msn/ns.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index a90c8a9d..fb85c989 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -571,6 +571,11 @@ static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num if( num_parts >= 2 ) handler->msglen = atoi( cmd[1] ); } + else if( strcmp( cmd[0], "UBM" ) == 0 ) + { + if( num_parts >= 7 ) + handler->msglen = atoi( cmd[6] ); + } else if( isdigit( cmd[0][0] ) ) { int num = atoi( cmd[0] ); @@ -772,6 +777,8 @@ static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msgl ( cn = xt_find_attr( c, "n" ) ) == NULL ) continue; + /* FIXME: Use "t" here, guess I should just add it + as a prefix like elsewhere in the protocol. */ handle = g_strdup_printf( "%s@%s", cn, dn ); if( !( ( bu = bee_user_by_handle( ic->bee, ic, handle ) ) || ( bu = bee_user_new( ic->bee, ic, handle, 0 ) ) ) ) @@ -797,8 +804,26 @@ static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msgl } } } + else if( strcmp( cmd[0], "UBM" ) == 0 ) + { + char *ct = get_rfc822_header( msg, "Content-Type", msglen ); + char *handle; + + if( strncmp( ct, "text/plain", 10 ) != 0 ) + { + g_free( ct ); + return 1; + } + if( strcmp( cmd[2], "1" ) != 0 ) + handle = g_strdup_printf( "%s:%s", cmd[2], cmd[1] ); + else + handle = g_strdup( cmd[1] ); + + imcb_buddy_msg( ic, handle, body, 0, 0 ); + g_free( handle ); + } - return( 1 ); + return 1; } void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error ) @@ -865,7 +890,7 @@ static gboolean msn_ns_send_adl_1( gpointer key, gpointer value, gpointer data ) c = xt_new_node( "c", NULL, NULL ); xt_add_attr( c, "n", handle ); xt_add_attr( c, "l", l ); - xt_add_attr( c, "t", "1" ); /* 1 means normal, 4 means mobile? */ + xt_add_attr( c, "t", "1" ); /* FIXME: Network type, i.e. 32 for Y!MSG */ xt_insert_child( d, c ); /* Do this in batches of 100. */ @@ -957,7 +982,7 @@ int msn_ns_sendmessage( struct im_connection *ic, bee_user_t *bu, const char *te if( msn_ns_write( ic, -1, "UUM %d %s %d %d %zd\r\n%s", ++md->trId, bu->handle, - 1, /* type == MSN offline message */ + 1, /* type == MSN (offline) message */ 1, /* type == IM (not nudge/typing) */ strlen( buf ), buf ) ) return 1; -- cgit v1.2.3 From 208db4babb7a9be245cedd3a0a4758891fece03d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 29 Sep 2012 20:38:18 +0100 Subject: Support for sending messages to federated contacts. They don't seem to arrive but Pidgin seems to have the same problem. --- protocols/msn/msn.c | 29 +++++++++++++++++++++++++++-- protocols/msn/msn.h | 1 + protocols/msn/ns.c | 15 ++++++++++++--- 3 files changed, 40 insertions(+), 5 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 8e10e202..71570ce0 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -139,6 +139,8 @@ static void msn_logout( struct im_connection *ic ) static int msn_buddy_msg( struct im_connection *ic, char *who, char *message, int away ) { + struct bee_user *bu = bee_user_by_handle( ic->bee, ic, who ); + struct msn_buddy_data *bd = bu ? bu->data : NULL; struct msn_switchboard *sb; #ifdef DEBUG @@ -148,7 +150,11 @@ static int msn_buddy_msg( struct im_connection *ic, char *who, char *message, in } else #endif - if( ( sb = msn_sb_by_handle( ic, who ) ) ) + if( bd && bd->flags & MSN_BUDDY_FED ) + { + msn_ns_sendmessage( ic, bu, message ); + } + else if( ( sb = msn_sb_by_handle( ic, who ) ) ) { return( msn_sb_sendmessage( sb, message ) ); } @@ -354,8 +360,27 @@ static char *set_eval_display_name( set_t *set, char *value ) static void msn_buddy_data_add( bee_user_t *bu ) { struct msn_data *md = bu->ic->proto_data; - bu->data = g_new0( struct msn_buddy_data, 1 ); + struct msn_buddy_data *bd; + char *handle; + + bd = bu->data = g_new0( struct msn_buddy_data, 1 ); g_tree_insert( md->domaintree, bu->handle, bu ); + + for( handle = bu->handle; isdigit( *handle ); handle ++ ); + if( *handle == ':' ) + { + /* Pass a nick hint so hopefully the stupid numeric prefix + won't show up to the user. */ + char *s = strchr( ++handle, '@' ); + if( s ) + { + handle = g_strndup( handle, s - handle ); + imcb_buddy_nick_hint( bu->ic, bu->handle, handle ); + g_free( handle ); + } + + bd->flags |= MSN_BUDDY_FED; + } } static void msn_buddy_data_free( bee_user_t *bu ) diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 7c23f282..1dcb0071 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -197,6 +197,7 @@ typedef enum MSN_BUDDY_RL = 8, MSN_BUDDY_PL = 16, MSN_BUDDY_ADL_SYNCED = 256, + MSN_BUDDY_FED = 512, } msn_buddy_flags_t; struct msn_buddy_data diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index fb85c989..49ccc5de 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -971,18 +971,27 @@ int msn_ns_finish_login( struct im_connection *ic ) int msn_ns_sendmessage( struct im_connection *ic, bee_user_t *bu, const char *text ) { struct msn_data *md = ic->proto_data; - char *buf; + int type = 0; + char *buf, *handle; if( strncmp( text, "\r\r\r", 3 ) == 0 ) /* Err. Shouldn't happen but I guess it can. Don't send others any of the "SHAKE THAT THING" messages. :-D */ return 1; + /* This might be a federated contact. Get its network number, + prefixed to bu->handle with a colon. Default is 1. */ + for( handle = bu->handle; isdigit( *handle ); handle ++ ) + type = type * 10 + *handle - '0'; + if( *handle == ':' ) + handle ++; + else + type = 1; + buf = g_strdup_printf( "%s%s", MSN_MESSAGE_HEADERS, text ); if( msn_ns_write( ic, -1, "UUM %d %s %d %d %zd\r\n%s", - ++md->trId, bu->handle, - 1, /* type == MSN (offline) message */ + ++md->trId, handle, type, 1, /* type == IM (not nudge/typing) */ strlen( buf ), buf ) ) return 1; -- cgit v1.2.3 From 4c9d3777d99191786a449912989a66a44a038383 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 29 Sep 2012 20:49:19 +0100 Subject: Suppress own UBM messages. --- protocols/msn/ns.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'protocols') diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 49ccc5de..d9a558f9 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -806,11 +806,22 @@ static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msgl } else if( strcmp( cmd[0], "UBM" ) == 0 ) { - char *ct = get_rfc822_header( msg, "Content-Type", msglen ); - char *handle; + /* This one will give us msgs from federated networks. Technically + it should also get us offline messages, but I don't know how + I can signal MSN servers to use it. */ + char *ct, *handle; + if( strcmp( cmd[1], ic->acc->user ) == 0 ) + { + /* With MPOP, you'll get copies of your own msgs from other + sessions. Discard those at least for now. */ + return 1; + } + + ct = get_rfc822_header( msg, "Content-Type", msglen ); if( strncmp( ct, "text/plain", 10 ) != 0 ) { + /* Typing notification or something? */ g_free( ct ); return 1; } -- cgit v1.2.3