Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • protocols/msn/ns.c

    rfd424c8 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"
    3231
    3332static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond );
     
    3534static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts );
    3635
    37 static void msn_ns_send_adl_start( struct im_connection *ic );
    38 static void msn_ns_send_adl( struct im_connection *ic );
     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 );
    3938
    4039gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond )
     
    7473        md->handler->rxq = g_new0( char, 1 );
    7574       
    76         g_snprintf( s, sizeof( s ), "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER );
     75        g_snprintf( s, sizeof( s ), "VER %d MSNP8 CVR0\r\n", ++md->trId );
    7776        if( msn_write( ic, s, strlen( s ) ) )
    7877        {
     
    114113        if( strcmp( cmd[0], "VER" ) == 0 )
    115114        {
    116                 if( cmd[2] && strncmp( cmd[2], MSNP_VER, 5 ) != 0 )
     115                if( cmd[2] && strncmp( cmd[2], "MSNP8", 5 ) != 0 )
    117116                {
    118117                        imcb_error( ic, "Unsupported protocol" );
     
    128127        {
    129128                /* We don't give a damn about the information we just received */
    130                 g_snprintf( buf, sizeof( buf ), "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 );
    131130                return( msn_write( ic, buf, strlen( buf ) ) );
    132131        }
     
    136135                int port;
    137136               
    138                 if( num_parts >= 6 && strcmp( cmd[2], "NS" ) == 0 )
     137                if( num_parts == 6 && strcmp( cmd[2], "NS" ) == 0 )
    139138                {
    140139                        b_event_remove( ic->inpa );
     
    157156                        md->fd = proxy_connect( server, port, msn_ns_connected, ic );
    158157                }
    159                 else if( num_parts >= 6 && strcmp( cmd[2], "SB" ) == 0 )
     158                else if( num_parts == 6 && strcmp( cmd[2], "SB" ) == 0 )
    160159                {
    161160                        struct msn_switchboard *sb;
     
    221220        else if( strcmp( cmd[0], "USR" ) == 0 )
    222221        {
    223                 if( num_parts >= 6 && strcmp( cmd[2], "SSO" ) == 0 &&
    224                     strcmp( cmd[3], "S" ) == 0 )
    225                 {
    226                         msn_soap_passport_sso_request( ic, cmd[4], cmd[5] );
    227                 }
    228                 else if( strcmp( cmd[2], "OK" ) == 0 )
    229                 {
     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                       
    230239                        imcb_log( ic, "Authenticated, getting buddy list" );
    231                         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 ) ) );
    232243                }
    233244                else
     
    240251        else if( strcmp( cmd[0], "MSG" ) == 0 )
    241252        {
    242                 if( num_parts < 4 )
     253                if( num_parts != 4 )
    243254                {
    244255                        imcb_error( ic, "Syntax error" );
     
    256267                }
    257268        }
    258         else if( strcmp( cmd[0], "BLP" ) == 0 )
    259         {
    260                 msn_ns_send_adl_start( ic );
    261                 return msn_ns_finish_login( ic );
    262         }
    263         else if( strcmp( cmd[0], "ADL" ) == 0 )
    264         {
    265                 if( num_parts >= 3 && strcmp( cmd[2], "OK" ) == 0 )
    266                 {
    267                         msn_ns_send_adl( ic );
    268                         return msn_ns_finish_login( ic );
    269                 }
    270                 else if( num_parts >= 3 )
    271                 {
    272                         md->handler->msglen = atoi( cmd[2] );
    273                 }
    274         }
    275         else if( strcmp( cmd[0], "PRP" ) == 0 )
    276         {
    277                 imcb_connected( ic );
     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] );
    278372        }
    279373        else if( strcmp( cmd[0], "CHL" ) == 0 )
    280374        {
    281                 char *resp;
    282                
    283                 if( num_parts < 3 )
    284                 {
    285                         imcb_error( ic, "Syntax error" );
    286                         imc_logout( ic, TRUE );
    287                         return( 0 );
    288                 }
    289                
    290                 resp = msn_p11_challenge( cmd[2] );
    291                 g_snprintf( buf, sizeof( buf ), "QRY %d %s %zd\r\n%s",
    292                             ++md->trId, MSNP11_PROD_ID,
    293                             strlen( resp ), resp );
    294                 g_free( resp );
     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] );
    295394               
    296395                return( msn_write( ic, buf, strlen( buf ) ) );
     
    300399                const struct msn_away_state *st;
    301400               
    302                 if( num_parts < 6 )
    303                 {
    304                         imcb_error( ic, "Syntax error" );
    305                         imc_logout( ic, TRUE );
    306                         return( 0 );
    307                 }
    308                
    309                 http_decode( cmd[5] );
    310                 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] );
    311410               
    312411                st = msn_away_state_by_code( cmd[2] );
     
    333432        {
    334433                const struct msn_away_state *st;
    335                 int cap;
    336                
    337                 if( num_parts < 6 )
    338                 {
    339                         imcb_error( ic, "Syntax error" );
    340                         imc_logout( ic, TRUE );
    341                         return( 0 );
    342                 }
    343                
    344                 http_decode( cmd[4] );
    345                 cap = atoi( cmd[5] );
    346                 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] );
    347444               
    348445                st = msn_away_state_by_code( cmd[1] );
     
    354451               
    355452                imcb_buddy_status( ic, cmd[2], OPT_LOGGED_IN |
    356                                    ( st != msn_away_state_list ? OPT_AWAY : 0 ) |
    357                                    ( cap & 1 ? OPT_MOBILE : 0 ),
     453                                   ( st != msn_away_state_list ? OPT_AWAY : 0 ),
    358454                                   st->name, NULL );
    359455               
     
    366462                int session, port;
    367463               
    368                 if( num_parts < 7 )
     464                if( num_parts != 7 )
    369465                {
    370466                        imcb_error( ic, "Syntax error" );
     
    408504                }
    409505        }
     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        }
    410546        else if( strcmp( cmd[0], "OUT" ) == 0 )
    411547        {
     
    429565                return( 0 );
    430566        }
     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
    431601        else if( strcmp( cmd[0], "IPG" ) == 0 )
    432602        {
     
    442612                }
    443613        }
    444 #if 0
    445614        else if( strcmp( cmd[0], "ADG" ) == 0 )
    446615        {
     
    486655                        }
    487656                }
    488         }
    489 #endif
    490         else if( strcmp( cmd[0], "GCF" ) == 0 )
    491         {
    492                 /* Coming up is cmd[2] bytes of stuff we're supposed to
    493                    censore. Meh. */
    494                 md->handler->msglen = atoi( cmd[2] );
    495         }
    496         else if( strcmp( cmd[0], "UBX" ) == 0 )
    497         {
    498                 /* Status message. */
    499                 if( num_parts >= 4 )
    500                         md->handler->msglen = atoi( cmd[3] );
    501         }
    502         else if( strcmp( cmd[0], "NOT" ) == 0 )
    503         {
    504                 /* Some kind of notification, poorly documented but
    505                    apparently used to announce address book changes. */
    506                 if( num_parts >= 2 )
    507                         md->handler->msglen = atoi( cmd[1] );
    508657        }
    509658        else if( isdigit( cmd[0][0] ) )
     
    616765                }
    617766        }
    618         else if( strcmp( cmd[0], "UBX" ) == 0 )
    619         {
    620                 struct xt_node *psm;
    621                 char *psm_text = NULL;
    622                
    623                 psm = xt_from_string( msg );
    624                 if( psm && strcmp( psm->name, "Data" ) == 0 &&
    625                     ( psm = xt_find_node( psm->children, "PSM" ) ) )
    626                         psm_text = psm->text;
    627                
    628                 imcb_buddy_status_msg( ic, cmd[1], psm_text );
    629                 xt_free_node( psm );
    630         }
    631         else if( strcmp( cmd[0], "ADL" ) == 0 )
    632         {
    633                 struct xt_node *adl, *d, *c;
    634                
    635                 if( !( adl = xt_from_string( msg ) ) )
    636                         return 1;
    637                
    638                 for( d = adl->children; d; d = d->next )
    639                 {
    640                         char *dn;
    641                         if( strcmp( d->name, "d" ) != 0 ||
    642                             ( dn = xt_find_attr( d, "n" ) ) == NULL )
    643                                 continue;
    644                         for( c = d->children; c; c = c->next )
    645                         {
    646                                 bee_user_t *bu;
    647                                 struct msn_buddy_data *bd;
    648                                 char *cn, *handle, *f, *l;
    649                                 int flags;
    650                                
    651                                 if( strcmp( c->name, "c" ) != 0 ||
    652                                     ( l = xt_find_attr( c, "l" ) ) == NULL ||
    653                                     ( cn = xt_find_attr( c, "n" ) ) == NULL )
    654                                         continue;
    655                                
    656                                 handle = g_strdup_printf( "%s@%s", cn, dn );
    657                                 if( !( ( bu = bee_user_by_handle( ic->bee, ic, handle ) ) ||
    658                                        ( bu = bee_user_new( ic->bee, ic, handle, 0 ) ) ) )
    659                                 {
    660                                         g_free( handle );
    661                                         continue;
    662                                 }
    663                                 g_free( handle );
    664                                 bd = bu->data;
    665                                
    666                                 if( ( f = xt_find_attr( c, "f" ) ) )
    667                                 {
    668                                         http_decode( f );
    669                                         imcb_rename_buddy( ic, bu->handle, f );
    670                                 }
    671                                
    672                                 flags = atoi( l ) & 15;
    673                                 if( bd->flags != flags )
    674                                 {
    675                                         bd->flags = flags;
    676                                         msn_buddy_ask( bu );
    677                                 }
    678                         }
    679                 }
    680         }
    681767       
    682768        return( 1 );
    683769}
    684770
    685 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 )
    686772{
     773        struct im_connection *ic = mad->data;
    687774        struct msn_data *md;
    688775       
     
    692779       
    693780        md = ic->proto_data;
    694        
    695         if( token )
    696         {
    697                 char buf[1536];
    698                
    699                 g_snprintf( buf, sizeof( buf ), "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 );
    700786                msn_write( ic, buf, strlen( buf ) );
    701787        }
    702788        else
    703789        {
    704                 imcb_error( ic, "Error during Passport authentication: %s", error );
     790                imcb_error( ic, "Error during Passport authentication: %s", mad->error );
    705791                imc_logout( ic, TRUE );
    706792        }
    707793}
    708794
    709 void msn_auth_got_contact_list( struct im_connection *ic )
     795static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name )
    710796{
    711         char buf[64];
    712         struct msn_data *md;
    713        
    714         /* Dead connection? */
    715         if( g_slist_find( msn_connections, ic ) == NULL )
    716                 return;
    717        
    718         md = ic->proto_data;
    719        
    720        
    721         g_snprintf( buf, sizeof( buf ), "BLP %d %s\r\n", ++md->trId, "BL" );
    722         msn_write( ic, buf, strlen( buf ) );
     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        }
    723838}
    724 
    725 static gboolean msn_ns_send_adl_1( gpointer key, gpointer value, gpointer data )
    726 {
    727         struct xt_node *adl = data, *d, *c;
    728         struct bee_user *bu = value;
    729         struct msn_buddy_data *bd = bu->data;
    730         struct msn_data *md = bu->ic->proto_data;
    731         char handle[strlen(bu->handle)];
    732         char *domain;
    733         char l[4];
    734        
    735         if( ( bd->flags & 7 ) == 0 || ( bd->flags & MSN_BUDDY_ADL_SYNCED ) )
    736                 return FALSE;
    737        
    738         strcpy( handle, bu->handle );
    739         if( ( domain = strchr( handle, '@' ) ) == NULL ) /* WTF */
    740                 return FALSE;
    741         *domain = '\0';
    742         domain ++;
    743        
    744         if( ( d = adl->children ) == NULL ||
    745             g_strcasecmp( xt_find_attr( d, "n" ), domain ) != 0 )
    746         {
    747                 d = xt_new_node( "d", NULL, NULL );
    748                 xt_add_attr( d, "n", domain );
    749                 xt_insert_child( adl, d );
    750         }
    751        
    752         g_snprintf( l, sizeof( l ), "%d", bd->flags & 7 );
    753         c = xt_new_node( "c", NULL, NULL );
    754         xt_add_attr( c, "n", handle );
    755         xt_add_attr( c, "l", l );
    756         xt_add_attr( c, "t", "1" ); /* 1 means normal, 4 means mobile? */
    757         xt_insert_child( d, c );
    758        
    759         /* Do this in batches of 100. */
    760         bd->flags |= MSN_BUDDY_ADL_SYNCED;
    761         return (--md->adl_todo % 140) == 0;
    762 }
    763 
    764 static void msn_ns_send_adl( struct im_connection *ic )
    765 {
    766         struct xt_node *adl;
    767         struct msn_data *md = ic->proto_data;
    768         char *adls, buf[64];
    769        
    770         adl = xt_new_node( "ml", NULL, NULL );
    771         xt_add_attr( adl, "l", "1" );
    772         g_tree_foreach( md->domaintree, msn_ns_send_adl_1, adl );
    773         if( adl->children == NULL )
    774         {
    775                 /* This tells the caller that we're done now. */
    776                 md->adl_todo = -1;
    777                 xt_free_node( adl );
    778                 return;
    779         }
    780         adls = xt_to_string( adl );
    781        
    782         g_snprintf( buf, sizeof( buf ), "ADL %d %zd\r\n", ++md->trId, strlen( adls ) );
    783         if( msn_write( ic, buf, strlen( buf ) ) )
    784                 msn_write( ic, adls, strlen( adls ) );
    785        
    786         g_free( adls );
    787 }
    788 
    789 static void msn_ns_send_adl_start( struct im_connection *ic )
    790 {
    791         struct msn_data *md;
    792         GSList *l;
    793        
    794         /* Dead connection? */
    795         if( g_slist_find( msn_connections, ic ) == NULL )
    796                 return;
    797        
    798         md = ic->proto_data;
    799         md->adl_todo = 0;
    800         for( l = ic->bee->users; l; l = l->next )
    801         {
    802                 bee_user_t *bu = l->data;
    803                 struct msn_buddy_data *bd = bu->data;
    804                
    805                 if( bu->ic != ic || ( bd->flags & 7 ) == 0 )
    806                         continue;
    807                
    808                 bd->flags &= ~MSN_BUDDY_ADL_SYNCED;
    809                 md->adl_todo++;
    810         }
    811        
    812         msn_ns_send_adl( ic );
    813 }
    814 
    815 int msn_ns_finish_login( struct im_connection *ic )
    816 {
    817         struct msn_data *md = ic->proto_data;
    818        
    819         if( ic->flags & OPT_LOGGED_IN )
    820                 return 1;
    821        
    822         if( md->adl_todo < 0 )
    823                 md->flags |= MSN_DONE_ADL;
    824        
    825         if( ( md->flags & MSN_DONE_ADL ) && ( md->flags & MSN_GOT_PROFILE ) )
    826                 return msn_ns_set_display_name( ic, set_getstr( &ic->acc->set, "display_name" ) );
    827         else
    828                 return 1;
    829 }
Note: See TracChangeset for help on using the changeset viewer.