Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • protocols/msn/ns.c

    r27053b5 r70ac477  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2010 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2004 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    2727#include "nogaim.h"
    2828#include "msn.h"
     29#include "passport.h"
    2930#include "md5.h"
    30 #include "soap.h"
    31 #include "xmltree.h"
    32 
    33 static gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond );
     31
    3432static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond );
    35 static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num_parts );
    36 static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts );
    37 
    38 static void msn_ns_send_adl_start( struct im_connection *ic );
    39 static void msn_ns_send_adl( struct im_connection *ic );
    40 
    41 int msn_ns_write( struct im_connection *ic, int fd, const char *fmt, ... )
     33static int msn_ns_command( gpointer data, char **cmd, int num_parts );
     34static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts );
     35
     36static void msn_auth_got_passport_token( struct msn_auth_data *mad );
     37static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name );
     38
     39gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond )
    4240{
    43         struct msn_data *md = ic->proto_data;
    44         va_list params;
    45         char *out;
    46         size_t len;
    47         int st;
    48        
    49         va_start( params, fmt );
    50         out = g_strdup_vprintf( fmt, params );
    51         va_end( params );
    52        
    53         if( fd < 0 )
    54                 fd = md->ns->fd;
    55        
    56         if( getenv( "BITLBEE_DEBUG" ) )
    57                 fprintf( stderr, "->NS%d:%s", fd, out );
    58        
    59         len = strlen( out );
    60         st = write( fd, out, len );
    61         g_free( out );
    62         if( st != len )
    63         {
    64                 imcb_error( ic, "Short write() to main server" );
    65                 imc_logout( ic, TRUE );
    66                 return 0;
    67         }
    68        
    69         return 1;
    70 }
    71 
    72 gboolean msn_ns_connect( struct im_connection *ic, struct msn_handler_data *handler, const char *host, int port )
    73 {
    74         if( handler->fd >= 0 )
    75                 closesocket( handler->fd );
    76        
    77         handler->exec_command = msn_ns_command;
    78         handler->exec_message = msn_ns_message;
    79         handler->data = ic;
    80         handler->fd = proxy_connect( host, port, msn_ns_connected, handler );
    81         if( handler->fd < 0 )
     41        struct im_connection *ic = data;
     42        struct msn_data *md;
     43        char s[1024];
     44       
     45        if( !g_slist_find( msn_connections, ic ) )
     46                return FALSE;
     47       
     48        if( source == -1 )
    8249        {
    8350                imcb_error( ic, "Could not connect to server" );
     
    8653        }
    8754       
    88         return TRUE;
    89 }
    90 
    91 static gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond )
    92 {
    93         struct msn_handler_data *handler = data;
    94         struct im_connection *ic = handler->data;
    95         struct msn_data *md;
    96        
    97         if( !g_slist_find( msn_connections, ic ) )
    98                 return FALSE;
    99        
    10055        md = ic->proto_data;
    10156       
    102         if( source == -1 )
    103         {
    104                 imcb_error( ic, "Could not connect to server" );
    105                 imc_logout( ic, TRUE );
    106                 return FALSE;
    107         }
    108        
    109         g_free( handler->rxq );
    110         handler->rxlen = 0;
    111         handler->rxq = g_new0( char, 1 );
    112        
    113         if( msn_ns_write( ic, source, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER ) )
    114         {
    115                 handler->inpa = b_input_add( handler->fd, B_EV_IO_READ, msn_ns_callback, handler );
     57        if( !md->handler )
     58        {
     59                md->handler = g_new0( struct msn_handler_data, 1 );
     60                md->handler->data = ic;
     61                md->handler->exec_command = msn_ns_command;
     62                md->handler->exec_message = msn_ns_message;
     63        }
     64        else
     65        {
     66                if( md->handler->rxq )
     67                        g_free( md->handler->rxq );
     68               
     69                md->handler->rxlen = 0;
     70        }
     71       
     72        md->handler->fd = md->fd;
     73        md->handler->rxq = g_new0( char, 1 );
     74       
     75        g_snprintf( s, sizeof( s ), "VER %d MSNP8 CVR0\r\n", ++md->trId );
     76        if( msn_write( ic, s, strlen( s ) ) )
     77        {
     78                ic->inpa = b_input_add( md->fd, B_EV_IO_READ, msn_ns_callback, ic );
    11679                imcb_log( ic, "Connected to server, waiting for reply" );
    11780        }
     
    12083}
    12184
    122 void msn_ns_close( struct msn_handler_data *handler )
    123 {
    124         if( handler->fd >= 0 )
    125         {
    126                 closesocket( handler->fd );
    127                 b_event_remove( handler->inpa );
    128         }
    129        
    130         handler->fd = handler->inpa = -1;
    131         g_free( handler->rxq );
    132         g_free( handler->cmd_text );
    133        
    134         handler->rxlen = 0;
    135         handler->rxq = NULL;
    136         handler->cmd_text = NULL;
    137 }
    138 
    13985static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond )
    14086{
    141         struct msn_handler_data *handler = data;
    142         struct im_connection *ic = handler->data;
    143        
    144         if( msn_handler( handler ) == -1 ) /* Don't do this on ret == 0, it's already done then. */
     87        struct im_connection *ic = data;
     88        struct msn_data *md = ic->proto_data;
     89       
     90        if( msn_handler( md->handler ) == -1 ) /* Don't do this on ret == 0, it's already done then. */
    14591        {
    14692                imcb_error( ic, "Error while reading from server" );
     
    15399}
    154100
    155 static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num_parts )
     101static int msn_ns_command( gpointer data, char **cmd, int num_parts )
    156102{
    157         struct im_connection *ic = handler->data;
     103        struct im_connection *ic = data;
    158104        struct msn_data *md = ic->proto_data;
     105        char buf[1024];
    159106       
    160107        if( num_parts == 0 )
     
    166113        if( strcmp( cmd[0], "VER" ) == 0 )
    167114        {
    168                 if( cmd[2] && strncmp( cmd[2], MSNP_VER, 5 ) != 0 )
     115                if( cmd[2] && strncmp( cmd[2], "MSNP8", 5 ) != 0 )
    169116                {
    170117                        imcb_error( ic, "Unsupported protocol" );
     
    173120                }
    174121               
    175                 return( msn_ns_write( ic, handler->fd, "CVR %d 0x0409 mac 10.2.0 ppc macmsgs 3.5.1 macmsgs %s\r\n",
    176                                       ++md->trId, ic->acc->user ) );
     122                g_snprintf( buf, sizeof( buf ), "CVR %d 0x0409 mac 10.2.0 ppc macmsgs 3.5.1 macmsgs %s\r\n",
     123                                                ++md->trId, ic->acc->user );
     124                return( msn_write( ic, buf, strlen( buf ) ) );
    177125        }
    178126        else if( strcmp( cmd[0], "CVR" ) == 0 )
    179127        {
    180128                /* We don't give a damn about the information we just received */
    181                 return msn_ns_write( ic, handler->fd, "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user );
     129                g_snprintf( buf, sizeof( buf ), "USR %d TWN I %s\r\n", ++md->trId, ic->acc->user );
     130                return( msn_write( ic, buf, strlen( buf ) ) );
    182131        }
    183132        else if( strcmp( cmd[0], "XFR" ) == 0 )
     
    186135                int port;
    187136               
    188                 if( num_parts >= 6 && strcmp( cmd[2], "NS" ) == 0 )
    189                 {
    190                         b_event_remove( handler->inpa );
    191                         handler->inpa = -1;
     137                if( num_parts == 6 && strcmp( cmd[2], "NS" ) == 0 )
     138                {
     139                        b_event_remove( ic->inpa );
     140                        ic->inpa = 0;
     141                        closesocket( md->fd );
    192142                       
    193143                        server = strchr( cmd[3], ':' );
     
    203153                       
    204154                        imcb_log( ic, "Transferring to other server" );
    205                         return msn_ns_connect( ic, handler, server, port );
    206                 }
    207                 else if( num_parts >= 6 && strcmp( cmd[2], "SB" ) == 0 )
     155                       
     156                        md->fd = proxy_connect( server, port, msn_ns_connected, ic );
     157                }
     158                else if( num_parts == 6 && strcmp( cmd[2], "SB" ) == 0 )
    208159                {
    209160                        struct msn_switchboard *sb;
     
    269220        else if( strcmp( cmd[0], "USR" ) == 0 )
    270221        {
    271                 if( num_parts >= 6 && strcmp( cmd[2], "SSO" ) == 0 &&
    272                     strcmp( cmd[3], "S" ) == 0 )
    273                 {
    274                         g_free( md->pp_policy );
    275                         md->pp_policy = g_strdup( cmd[4] );
    276                         msn_soap_passport_sso_request( ic, cmd[5] );
    277                 }
    278                 else if( strcmp( cmd[2], "OK" ) == 0 )
    279                 {
     222                if( num_parts == 5 && strcmp( cmd[2], "TWN" ) == 0 && strcmp( cmd[3], "S" ) == 0 )
     223                {
     224                        /* Time for some Passport black magic... */
     225                        if( !passport_get_token( msn_auth_got_passport_token, ic, ic->acc->user, ic->acc->pass, cmd[4] ) )
     226                        {
     227                                imcb_error( ic, "Error while contacting Passport server" );
     228                                imc_logout( ic, TRUE );
     229                                return( 0 );
     230                        }
     231                }
     232                else if( num_parts >= 7 && strcmp( cmd[2], "OK" ) == 0 )
     233                {
     234                        if( num_parts == 7 )
     235                                msn_ns_got_display_name( ic, cmd[4] );
     236                        else
     237                                imcb_log( ic, "Warning: Friendly name in server response was corrupted" );
     238                       
    280239                        imcb_log( ic, "Authenticated, getting buddy list" );
    281                         msn_soap_memlist_request( ic );
     240                       
     241                        g_snprintf( buf, sizeof( buf ), "SYN %d 0\r\n", ++md->trId );
     242                        return( msn_write( ic, buf, strlen( buf ) ) );
    282243                }
    283244                else
     
    290251        else if( strcmp( cmd[0], "MSG" ) == 0 )
    291252        {
    292                 if( num_parts < 4 )
    293                 {
    294                         imcb_error( ic, "Syntax error" );
    295                         imc_logout( ic, TRUE );
    296                         return( 0 );
    297                 }
    298                
    299                 handler->msglen = atoi( cmd[3] );
    300                
    301                 if( handler->msglen <= 0 )
    302                 {
    303                         imcb_error( ic, "Syntax error" );
    304                         imc_logout( ic, TRUE );
    305                         return( 0 );
    306                 }
    307         }
    308         else if( strcmp( cmd[0], "BLP" ) == 0 )
    309         {
    310                 msn_ns_send_adl_start( ic );
    311                 return msn_ns_finish_login( ic );
    312         }
    313         else if( strcmp( cmd[0], "ADL" ) == 0 )
    314         {
    315                 if( num_parts >= 3 && strcmp( cmd[2], "OK" ) == 0 )
    316                 {
    317                         msn_ns_send_adl( ic );
    318                         return msn_ns_finish_login( ic );
    319                 }
    320                 else if( num_parts >= 3 )
    321                 {
    322                         handler->msglen = atoi( cmd[2] );
    323                 }
    324         }
    325         else if( strcmp( cmd[0], "PRP" ) == 0 )
    326         {
    327                 imcb_connected( ic );
     253                if( num_parts != 4 )
     254                {
     255                        imcb_error( ic, "Syntax error" );
     256                        imc_logout( ic, TRUE );
     257                        return( 0 );
     258                }
     259               
     260                md->handler->msglen = atoi( cmd[3] );
     261               
     262                if( md->handler->msglen <= 0 )
     263                {
     264                        imcb_error( ic, "Syntax error" );
     265                        imc_logout( ic, TRUE );
     266                        return( 0 );
     267                }
     268        }
     269        else if( strcmp( cmd[0], "SYN" ) == 0 )
     270        {
     271                if( num_parts == 5 )
     272                {
     273                        int i, groupcount;
     274                       
     275                        groupcount = atoi( cmd[4] );
     276                        if( groupcount > 0 )
     277                        {
     278                                /* valgrind says this is leaking memory, I'm guessing
     279                                   that this happens during server redirects. */
     280                                if( md->grouplist )
     281                                {
     282                                        for( i = 0; i < md->groupcount; i ++ )
     283                                                g_free( md->grouplist[i] );
     284                                        g_free( md->grouplist );
     285                                }
     286                               
     287                                md->groupcount = groupcount;
     288                                md->grouplist = g_new0( char *, md->groupcount );
     289                        }
     290                       
     291                        md->buddycount = atoi( cmd[3] );
     292                        if( !*cmd[3] || md->buddycount == 0 )
     293                                msn_logged_in( ic );
     294                }
     295                else
     296                {
     297                        /* Hrrm... This SYN reply doesn't really look like something we expected.
     298                           Let's assume everything is okay. */
     299                       
     300                        msn_logged_in( ic );
     301                }
     302        }
     303        else if( strcmp( cmd[0], "LST" ) == 0 )
     304        {
     305                int list;
     306               
     307                if( num_parts != 4 && num_parts != 5 )
     308                {
     309                        imcb_error( ic, "Syntax error" );
     310                        imc_logout( ic, TRUE );
     311                        return( 0 );
     312                }
     313               
     314                http_decode( cmd[2] );
     315                list = atoi( cmd[3] );
     316               
     317                if( list & 1 ) /* FL */
     318                {
     319                        char *group = NULL;
     320                        int num;
     321                       
     322                        if( cmd[4] != NULL && sscanf( cmd[4], "%d", &num ) == 1 && num < md->groupcount )
     323                                group = md->grouplist[num];
     324                       
     325                        imcb_add_buddy( ic, cmd[1], group );
     326                        imcb_rename_buddy( ic, cmd[1], cmd[2] );
     327                }
     328                if( list & 2 ) /* AL */
     329                {
     330                        ic->permit = g_slist_append( ic->permit, g_strdup( cmd[1] ) );
     331                }
     332                if( list & 4 ) /* BL */
     333                {
     334                        ic->deny = g_slist_append( ic->deny, g_strdup( cmd[1] ) );
     335                }
     336                if( list & 8 ) /* RL */
     337                {
     338                        if( ( list & 6 ) == 0 )
     339                                msn_buddy_ask( ic, cmd[1], cmd[2] );
     340                }
     341               
     342                if( --md->buddycount == 0 )
     343                {
     344                        if( ic->flags & OPT_LOGGED_IN )
     345                        {
     346                                imcb_log( ic, "Successfully transferred to different server" );
     347                                g_snprintf( buf, sizeof( buf ), "CHG %d %s %d\r\n", ++md->trId, md->away_state->code, 0 );
     348                                return( msn_write( ic, buf, strlen( buf ) ) );
     349                        }
     350                        else
     351                        {
     352                                msn_logged_in( ic );
     353                        }
     354                }
     355        }
     356        else if( strcmp( cmd[0], "LSG" ) == 0 )
     357        {
     358                int num;
     359               
     360                if( num_parts != 4 )
     361                {
     362                        imcb_error( ic, "Syntax error" );
     363                        imc_logout( ic, TRUE );
     364                        return( 0 );
     365                }
     366               
     367                http_decode( cmd[2] );
     368                num = atoi( cmd[1] );
     369               
     370                if( num < md->groupcount )
     371                        md->grouplist[num] = g_strdup( cmd[2] );
    328372        }
    329373        else if( strcmp( cmd[0], "CHL" ) == 0 )
    330374        {
    331                 char *resp;
    332                 int st;
    333                
    334                 if( num_parts < 3 )
    335                 {
    336                         imcb_error( ic, "Syntax error" );
    337                         imc_logout( ic, TRUE );
    338                         return( 0 );
    339                 }
    340                
    341                 resp = msn_p11_challenge( cmd[2] );
    342                
    343                 st =  msn_ns_write( ic, -1, "QRY %d %s %zd\r\n%s",
    344                                     ++md->trId, MSNP11_PROD_ID,
    345                                     strlen( resp ), resp );
    346                 g_free( resp );
    347                 return st;
     375                md5_state_t state;
     376                md5_byte_t digest[16];
     377                int i;
     378               
     379                if( num_parts != 3 )
     380                {
     381                        imcb_error( ic, "Syntax error" );
     382                        imc_logout( ic, TRUE );
     383                        return( 0 );
     384                }
     385               
     386                md5_init( &state );
     387                md5_append( &state, (const md5_byte_t *) cmd[2], strlen( cmd[2] ) );
     388                md5_append( &state, (const md5_byte_t *) QRY_CODE, strlen( QRY_CODE ) );
     389                md5_finish( &state, digest );
     390               
     391                g_snprintf( buf, sizeof( buf ), "QRY %d %s %d\r\n", ++md->trId, QRY_NAME, 32 );
     392                for( i = 0; i < 16; i ++ )
     393                        g_snprintf( buf + strlen( buf ), 3, "%02x", digest[i] );
     394               
     395                return( msn_write( ic, buf, strlen( buf ) ) );
    348396        }
    349397        else if( strcmp( cmd[0], "ILN" ) == 0 )
     
    351399                const struct msn_away_state *st;
    352400               
    353                 if( num_parts < 6 )
    354                 {
    355                         imcb_error( ic, "Syntax error" );
    356                         imc_logout( ic, TRUE );
    357                         return( 0 );
    358                 }
    359                
    360                 http_decode( cmd[5] );
    361                 imcb_rename_buddy( ic, cmd[3], cmd[5] );
     401                if( num_parts != 6 )
     402                {
     403                        imcb_error( ic, "Syntax error" );
     404                        imc_logout( ic, TRUE );
     405                        return( 0 );
     406                }
     407               
     408                http_decode( cmd[4] );
     409                imcb_rename_buddy( ic, cmd[3], cmd[4] );
    362410               
    363411                st = msn_away_state_by_code( cmd[2] );
     
    384432        {
    385433                const struct msn_away_state *st;
    386                 int cap;
    387                
    388                 if( num_parts < 6 )
    389                 {
    390                         imcb_error( ic, "Syntax error" );
    391                         imc_logout( ic, TRUE );
    392                         return( 0 );
    393                 }
    394                
    395                 http_decode( cmd[4] );
    396                 cap = atoi( cmd[5] );
    397                 imcb_rename_buddy( ic, cmd[2], cmd[4] );
     434               
     435                if( num_parts != 5 )
     436                {
     437                        imcb_error( ic, "Syntax error" );
     438                        imc_logout( ic, TRUE );
     439                        return( 0 );
     440                }
     441               
     442                http_decode( cmd[3] );
     443                imcb_rename_buddy( ic, cmd[2], cmd[3] );
    398444               
    399445                st = msn_away_state_by_code( cmd[1] );
     
    405451               
    406452                imcb_buddy_status( ic, cmd[2], OPT_LOGGED_IN |
    407                                    ( st != msn_away_state_list ? OPT_AWAY : 0 ) |
    408                                    ( cap & 1 ? OPT_MOBILE : 0 ),
     453                                   ( st != msn_away_state_list ? OPT_AWAY : 0 ),
    409454                                   st->name, NULL );
    410455               
     
    417462                int session, port;
    418463               
    419                 if( num_parts < 7 )
     464                if( num_parts != 7 )
    420465                {
    421466                        imcb_error( ic, "Syntax error" );
     
    459504                }
    460505        }
     506        else if( strcmp( cmd[0], "ADD" ) == 0 )
     507        {
     508                if( num_parts == 6 && strcmp( cmd[2], "RL" ) == 0 )
     509                {
     510                        GSList *l;
     511                       
     512                        http_decode( cmd[5] );
     513                       
     514                        if( strchr( cmd[4], '@' ) == NULL )
     515                        {
     516                                imcb_error( ic, "Syntax error" );
     517                                imc_logout( ic, TRUE );
     518                                return 0;
     519                        }
     520                       
     521                        /* We got added by someone. If we don't have this
     522                           person in permit/deny yet, inform the user. */
     523                        for( l = ic->permit; l; l = l->next )
     524                                if( g_strcasecmp( l->data, cmd[4] ) == 0 )
     525                                        return 1;
     526                       
     527                        for( l = ic->deny; l; l = l->next )
     528                                if( g_strcasecmp( l->data, cmd[4] ) == 0 )
     529                                        return 1;
     530                       
     531                        msn_buddy_ask( ic, cmd[4], cmd[5] );
     532                }
     533                else if( num_parts >= 6 && strcmp( cmd[2], "FL" ) == 0 )
     534                {
     535                        const char *group = NULL;
     536                        int num;
     537                       
     538                        if( cmd[6] != NULL && sscanf( cmd[6], "%d", &num ) == 1 && num < md->groupcount )
     539                                group = md->grouplist[num];
     540                       
     541                        http_decode( cmd[5] );
     542                        imcb_add_buddy( ic, cmd[4], group );
     543                        imcb_rename_buddy( ic, cmd[4], cmd[5] );
     544                }
     545        }
    461546        else if( strcmp( cmd[0], "OUT" ) == 0 )
    462547        {
     
    480565                return( 0 );
    481566        }
     567#if 0
     568        /* Discard this one completely for now since I don't care about the ack
     569           and since MSN servers can apparently screw up the formatting. */
     570        else if( strcmp( cmd[0], "REA" ) == 0 )
     571        {
     572                if( num_parts != 5 )
     573                {
     574                        imcb_error( ic, "Syntax error" );
     575                        imc_logout( ic, TRUE );
     576                        return( 0 );
     577                }
     578               
     579                if( g_strcasecmp( cmd[3], ic->acc->user ) == 0 )
     580                {
     581                        set_t *s;
     582                       
     583                        http_decode( cmd[4] );
     584                        strncpy( ic->displayname, cmd[4], sizeof( ic->displayname ) );
     585                        ic->displayname[sizeof(ic->displayname)-1] = 0;
     586                       
     587                        if( ( s = set_find( &ic->acc->set, "display_name" ) ) )
     588                        {
     589                                g_free( s->value );
     590                                s->value = g_strdup( cmd[4] );
     591                        }
     592                }
     593                else
     594                {
     595                        /* This is not supposed to happen, but let's handle it anyway... */
     596                        http_decode( cmd[4] );
     597                        imcb_rename_buddy( ic, cmd[3], cmd[4] );
     598                }
     599        }
     600#endif
    482601        else if( strcmp( cmd[0], "IPG" ) == 0 )
    483602        {
    484603                imcb_error( ic, "Received IPG command, we don't handle them yet." );
    485604               
    486                 handler->msglen = atoi( cmd[1] );
    487                
    488                 if( handler->msglen <= 0 )
    489                 {
    490                         imcb_error( ic, "Syntax error" );
    491                         imc_logout( ic, TRUE );
    492                         return( 0 );
    493                 }
    494         }
    495 #if 0
     605                md->handler->msglen = atoi( cmd[1] );
     606               
     607                if( md->handler->msglen <= 0 )
     608                {
     609                        imcb_error( ic, "Syntax error" );
     610                        imc_logout( ic, TRUE );
     611                        return( 0 );
     612                }
     613        }
    496614        else if( strcmp( cmd[0], "ADG" ) == 0 )
    497615        {
     
    538656                }
    539657        }
    540 #endif
    541         else if( strcmp( cmd[0], "GCF" ) == 0 )
    542         {
    543                 /* Coming up is cmd[2] bytes of stuff we're supposed to
    544                    censore. Meh. */
    545                 handler->msglen = atoi( cmd[2] );
    546         }
    547         else if( strcmp( cmd[0], "UBX" ) == 0 )
    548         {
    549                 /* Status message. */
    550                 if( num_parts >= 4 )
    551                         handler->msglen = atoi( cmd[3] );
    552         }
    553         else if( strcmp( cmd[0], "NOT" ) == 0 )
    554         {
    555                 /* Some kind of notification, poorly documented but
    556                    apparently used to announce address book changes. */
    557                 if( num_parts >= 2 )
    558                         handler->msglen = atoi( cmd[1] );
    559         }
    560658        else if( isdigit( cmd[0][0] ) )
    561659        {
     
    570668                        return( 0 );
    571669                }
    572                
    573                 /* Oh yes, errors can have payloads too now. Discard them for now. */
    574                 if( num_parts >= 3 )
    575                         handler->msglen = atoi( cmd[2] );
    576670        }
    577671        else
     
    583677}
    584678
    585 static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts )
     679static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts )
    586680{
    587         struct im_connection *ic = handler->data;
     681        struct im_connection *ic = data;
    588682        char *body;
    589683        int blen = 0;
     
    671765                }
    672766        }
    673         else if( strcmp( cmd[0], "UBX" ) == 0 )
    674         {
    675                 struct xt_node *psm;
    676                 char *psm_text = NULL;
    677                
    678                 psm = xt_from_string( msg );
    679                 if( psm && strcmp( psm->name, "Data" ) == 0 &&
    680                     ( psm = xt_find_node( psm->children, "PSM" ) ) )
    681                         psm_text = psm->text;
    682                
    683                 imcb_buddy_status_msg( ic, cmd[1], psm_text );
    684                 xt_free_node( psm );
    685         }
    686         else if( strcmp( cmd[0], "ADL" ) == 0 )
    687         {
    688                 struct xt_node *adl, *d, *c;
    689                
    690                 if( !( adl = xt_from_string( msg ) ) )
    691                         return 1;
    692                
    693                 for( d = adl->children; d; d = d->next )
    694                 {
    695                         char *dn;
    696                         if( strcmp( d->name, "d" ) != 0 ||
    697                             ( dn = xt_find_attr( d, "n" ) ) == NULL )
    698                                 continue;
    699                         for( c = d->children; c; c = c->next )
    700                         {
    701                                 bee_user_t *bu;
    702                                 struct msn_buddy_data *bd;
    703                                 char *cn, *handle, *f, *l;
    704                                 int flags;
    705                                
    706                                 if( strcmp( c->name, "c" ) != 0 ||
    707                                     ( l = xt_find_attr( c, "l" ) ) == NULL ||
    708                                     ( cn = xt_find_attr( c, "n" ) ) == NULL )
    709                                         continue;
    710                                
    711                                 handle = g_strdup_printf( "%s@%s", cn, dn );
    712                                 if( !( ( bu = bee_user_by_handle( ic->bee, ic, handle ) ) ||
    713                                        ( bu = bee_user_new( ic->bee, ic, handle, 0 ) ) ) )
    714                                 {
    715                                         g_free( handle );
    716                                         continue;
    717                                 }
    718                                 g_free( handle );
    719                                 bd = bu->data;
    720                                
    721                                 if( ( f = xt_find_attr( c, "f" ) ) )
    722                                 {
    723                                         http_decode( f );
    724                                         imcb_rename_buddy( ic, bu->handle, f );
    725                                 }
    726                                
    727                                 flags = atoi( l ) & 15;
    728                                 if( bd->flags != flags )
    729                                 {
    730                                         bd->flags = flags;
    731                                         msn_buddy_ask( bu );
    732                                 }
    733                         }
    734                 }
    735         }
    736767       
    737768        return( 1 );
    738769}
    739770
    740 void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error )
     771static void msn_auth_got_passport_token( struct msn_auth_data *mad )
    741772{
     773        struct im_connection *ic = mad->data;
    742774        struct msn_data *md;
    743775       
     
    747779       
    748780        md = ic->proto_data;
    749        
    750         if( token )
    751         {
    752                 msn_ns_write( ic, -1, "USR %d SSO S %s %s\r\n", ++md->trId, md->tokens[0], token );
     781        if( mad->token )
     782        {
     783                char buf[1024];
     784               
     785                g_snprintf( buf, sizeof( buf ), "USR %d TWN S %s\r\n", ++md->trId, mad->token );
     786                msn_write( ic, buf, strlen( buf ) );
    753787        }
    754788        else
    755789        {
    756                 imcb_error( ic, "Error during Passport authentication: %s", error );
     790                imcb_error( ic, "Error during Passport authentication: %s", mad->error );
    757791                imc_logout( ic, TRUE );
    758792        }
    759793}
    760794
    761 void msn_auth_got_contact_list( struct im_connection *ic )
     795static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name )
    762796{
    763         struct msn_data *md;
    764        
    765         /* Dead connection? */
    766         if( g_slist_find( msn_connections, ic ) == NULL )
    767                 return;
    768        
    769         md = ic->proto_data;
    770         msn_ns_write( ic, -1, "BLP %d %s\r\n", ++md->trId, "BL" );
     797        set_t *s;
     798       
     799        if( ( s = set_find( &ic->acc->set, "display_name" ) ) == NULL )
     800                return FALSE; /* Shouldn't happen.. */
     801       
     802        http_decode( name );
     803       
     804        if( s->value && strcmp( s->value, name ) == 0 )
     805        {
     806                return TRUE;
     807                /* The names match, nothing to worry about. */
     808        }
     809        else if( s->value != NULL &&
     810                 ( strcmp( name, ic->acc->user ) == 0 ||
     811                   set_getbool( &ic->acc->set, "local_display_name" ) ) )
     812        {
     813                /* The server thinks our display name is our e-mail address
     814                   which is probably wrong, or the user *wants* us to do this:
     815                   Always use the locally set display_name. */
     816                return msn_set_display_name( ic, s->value );
     817        }
     818        else
     819        {
     820                if( s->value && *s->value )
     821                        imcb_log( ic, "BitlBee thinks your display name is `%s' but "
     822                                      "the MSN server says it's `%s'. Using the MSN "
     823                                      "server's name. Set local_display_name to true "
     824                                      "to use the local name.", s->value, name );
     825               
     826                if( g_utf8_validate( name, -1, NULL ) )
     827                {
     828                        g_free( s->value );
     829                        s->value = g_strdup( name );
     830                }
     831                else
     832                {
     833                        imcb_log( ic, "Warning: Friendly name in server response was corrupted" );
     834                }
     835               
     836                return TRUE;
     837        }
    771838}
    772 
    773 static gboolean msn_ns_send_adl_1( gpointer key, gpointer value, gpointer data )
    774 {
    775         struct xt_node *adl = data, *d, *c;
    776         struct bee_user *bu = value;
    777         struct msn_buddy_data *bd = bu->data;
    778         struct msn_data *md = bu->ic->proto_data;
    779         char handle[strlen(bu->handle)];
    780         char *domain;
    781         char l[4];
    782        
    783         if( ( bd->flags & 7 ) == 0 || ( bd->flags & MSN_BUDDY_ADL_SYNCED ) )
    784                 return FALSE;
    785        
    786         strcpy( handle, bu->handle );
    787         if( ( domain = strchr( handle, '@' ) ) == NULL ) /* WTF */
    788                 return FALSE;
    789         *domain = '\0';
    790         domain ++;
    791        
    792         if( ( d = adl->children ) == NULL ||
    793             g_strcasecmp( xt_find_attr( d, "n" ), domain ) != 0 )
    794         {
    795                 d = xt_new_node( "d", NULL, NULL );
    796                 xt_add_attr( d, "n", domain );
    797                 xt_insert_child( adl, d );
    798         }
    799        
    800         g_snprintf( l, sizeof( l ), "%d", bd->flags & 7 );
    801         c = xt_new_node( "c", NULL, NULL );
    802         xt_add_attr( c, "n", handle );
    803         xt_add_attr( c, "l", l );
    804         xt_add_attr( c, "t", "1" ); /* 1 means normal, 4 means mobile? */
    805         xt_insert_child( d, c );
    806        
    807         /* Do this in batches of 100. */
    808         bd->flags |= MSN_BUDDY_ADL_SYNCED;
    809         return (--md->adl_todo % 140) == 0;
    810 }
    811 
    812 static void msn_ns_send_adl( struct im_connection *ic )
    813 {
    814         struct xt_node *adl;
    815         struct msn_data *md = ic->proto_data;
    816         char *adls;
    817        
    818         adl = xt_new_node( "ml", NULL, NULL );
    819         xt_add_attr( adl, "l", "1" );
    820         g_tree_foreach( md->domaintree, msn_ns_send_adl_1, adl );
    821         if( adl->children == NULL )
    822         {
    823                 /* This tells the caller that we're done now. */
    824                 md->adl_todo = -1;
    825                 xt_free_node( adl );
    826                 return;
    827         }
    828        
    829         adls = xt_to_string( adl );
    830         msn_ns_write( ic, -1, "ADL %d %zd\r\n%s", ++md->trId, strlen( adls ), adls );
    831         g_free( adls );
    832 }
    833 
    834 static void msn_ns_send_adl_start( struct im_connection *ic )
    835 {
    836         struct msn_data *md;
    837         GSList *l;
    838        
    839         /* Dead connection? */
    840         if( g_slist_find( msn_connections, ic ) == NULL )
    841                 return;
    842        
    843         md = ic->proto_data;
    844         md->adl_todo = 0;
    845         for( l = ic->bee->users; l; l = l->next )
    846         {
    847                 bee_user_t *bu = l->data;
    848                 struct msn_buddy_data *bd = bu->data;
    849                
    850                 if( bu->ic != ic || ( bd->flags & 7 ) == 0 )
    851                         continue;
    852                
    853                 bd->flags &= ~MSN_BUDDY_ADL_SYNCED;
    854                 md->adl_todo++;
    855         }
    856        
    857         msn_ns_send_adl( ic );
    858 }
    859 
    860 int msn_ns_finish_login( struct im_connection *ic )
    861 {
    862         struct msn_data *md = ic->proto_data;
    863        
    864         if( ic->flags & OPT_LOGGED_IN )
    865                 return 1;
    866        
    867         if( md->adl_todo < 0 )
    868                 md->flags |= MSN_DONE_ADL;
    869        
    870         if( ( md->flags & MSN_DONE_ADL ) && ( md->flags & MSN_GOT_PROFILE ) )
    871                 return msn_ns_set_display_name( ic, set_getstr( &ic->acc->set, "display_name" ) );
    872         else
    873                 return 1;
    874 }
Note: See TracChangeset for help on using the changeset viewer.