Changeset 62f53b50 for protocols/msn/ns.c
- Timestamp:
- 2010-10-02T05:34:53Z (14 years ago)
- Branches:
- master
- Children:
- 2af3e23
- Parents:
- 05bf2a0 (diff), 04cd284 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
protocols/msn/ns.c
r05bf2a0 r62f53b50 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * 4 * Copyright 2002-20 04Wilmer van der Gaast and others *4 * Copyright 2002-2010 Wilmer van der Gaast and others * 5 5 \********************************************************************/ 6 6 … … 27 27 #include "nogaim.h" 28 28 #include "msn.h" 29 #include "passport.h"30 29 #include "md5.h" 31 30 #include "soap.h" 31 #include "xmltree.h" 32 33 static gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ); 32 34 static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond ); 33 static int msn_ns_command( gpointer data, char **cmd, int num_parts ); 34 static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ); 35 36 static void msn_auth_got_passport_token( struct msn_auth_data *mad ); 37 static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name ); 38 39 gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) 40 { 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 ) 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, ... ) 42 { 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 ) 49 82 { 50 83 imcb_error( ic, "Could not connect to server" ); … … 53 86 } 54 87 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 55 100 md = ic->proto_data; 56 101 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 ); 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 ); 79 116 imcb_log( ic, "Connected to server, waiting for reply" ); 80 117 } … … 83 120 } 84 121 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 85 139 static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond ) 86 140 { 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. */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. */ 91 145 { 92 146 imcb_error( ic, "Error while reading from server" ); … … 99 153 } 100 154 101 static int msn_ns_command( gpointer data, char **cmd, int num_parts )102 { 103 struct im_connection *ic = data;155 static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num_parts ) 156 { 157 struct im_connection *ic = handler->data; 104 158 struct msn_data *md = ic->proto_data; 105 char buf[1024];106 159 107 160 if( num_parts == 0 ) … … 113 166 if( strcmp( cmd[0], "VER" ) == 0 ) 114 167 { 115 if( cmd[2] && strncmp( cmd[2], "MSNP8", 5 ) != 0 )168 if( cmd[2] && strncmp( cmd[2], MSNP_VER, 5 ) != 0 ) 116 169 { 117 170 imcb_error( ic, "Unsupported protocol" ); … … 120 173 } 121 174 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 ) ) ); 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 ) ); 125 177 } 126 178 else if( strcmp( cmd[0], "CVR" ) == 0 ) 127 179 { 128 180 /* We don't give a damn about the information we just received */ 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 ) ) ); 181 return msn_ns_write( ic, handler->fd, "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user ); 131 182 } 132 183 else if( strcmp( cmd[0], "XFR" ) == 0 ) … … 135 186 int port; 136 187 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 ); 188 if( num_parts >= 6 && strcmp( cmd[2], "NS" ) == 0 ) 189 { 190 b_event_remove( handler->inpa ); 191 handler->inpa = -1; 142 192 143 193 server = strchr( cmd[3], ':' ); … … 153 203 154 204 imcb_log( ic, "Transferring to other server" ); 155 156 md->fd = proxy_connect( server, port, msn_ns_connected, ic ); 157 } 158 else if( num_parts == 6 && strcmp( cmd[2], "SB" ) == 0 ) 205 return msn_ns_connect( ic, handler, server, port ); 206 } 207 else if( num_parts >= 6 && strcmp( cmd[2], "SB" ) == 0 ) 159 208 { 160 209 struct msn_switchboard *sb; … … 220 269 else if( strcmp( cmd[0], "USR" ) == 0 ) 221 270 { 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 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 { 239 280 imcb_log( ic, "Authenticated, getting buddy list" ); 240 241 g_snprintf( buf, sizeof( buf ), "SYN %d 0\r\n", ++md->trId ); 242 return( msn_write( ic, buf, strlen( buf ) ) ); 281 msn_soap_memlist_request( ic ); 243 282 } 244 283 else … … 251 290 else if( strcmp( cmd[0], "MSG" ) == 0 ) 252 291 { 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] ); 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 ); 372 328 } 373 329 else if( strcmp( cmd[0], "CHL" ) == 0 ) 374 330 { 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 ) ) ); 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; 396 348 } 397 349 else if( strcmp( cmd[0], "ILN" ) == 0 ) … … 399 351 const struct msn_away_state *st; 400 352 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] );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] ); 410 362 411 363 st = msn_away_state_by_code( cmd[2] ); … … 432 384 { 433 385 const struct msn_away_state *st; 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] ); 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] ); 444 398 445 399 st = msn_away_state_by_code( cmd[1] ); … … 451 405 452 406 imcb_buddy_status( ic, cmd[2], OPT_LOGGED_IN | 453 ( st != msn_away_state_list ? OPT_AWAY : 0 ), 407 ( st != msn_away_state_list ? OPT_AWAY : 0 ) | 408 ( cap & 1 ? OPT_MOBILE : 0 ), 454 409 st->name, NULL ); 455 410 … … 462 417 int session, port; 463 418 464 if( num_parts !=7 )419 if( num_parts < 7 ) 465 420 { 466 421 imcb_error( ic, "Syntax error" ); … … 504 459 } 505 460 } 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 this522 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 }546 461 else if( strcmp( cmd[0], "OUT" ) == 0 ) 547 462 { … … 565 480 return( 0 ); 566 481 } 482 else if( strcmp( cmd[0], "IPG" ) == 0 ) 483 { 484 imcb_error( ic, "Received IPG command, we don't handle them yet." ); 485 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 } 567 495 #if 0 568 /* Discard this one completely for now since I don't care about the ack569 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 else594 {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 #endif601 else if( strcmp( cmd[0], "IPG" ) == 0 )602 {603 imcb_error( ic, "Received IPG command, we don't handle them yet." );604 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 }614 496 else if( strcmp( cmd[0], "ADG" ) == 0 ) 615 497 { … … 656 538 } 657 539 } 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 } 658 560 else if( isdigit( cmd[0][0] ) ) 659 561 { … … 668 570 return( 0 ); 669 571 } 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] ); 670 576 } 671 577 else … … 677 583 } 678 584 679 static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts )680 { 681 struct im_connection *ic = data;585 static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts ) 586 { 587 struct im_connection *ic = handler->data; 682 588 char *body; 683 589 int blen = 0; … … 765 671 } 766 672 } 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 } 767 736 768 737 return( 1 ); 769 738 } 770 739 771 static void msn_auth_got_passport_token( struct msn_auth_data *mad ) 772 { 773 struct im_connection *ic = mad->data; 740 void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error ) 741 { 774 742 struct msn_data *md; 775 743 … … 779 747 780 748 md = ic->proto_data; 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 ) ); 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 ); 787 753 } 788 754 else 789 755 { 790 imcb_error( ic, "Error during Passport authentication: %s", mad->error );756 imcb_error( ic, "Error during Passport authentication: %s", error ); 791 757 imc_logout( ic, TRUE ); 792 758 } 793 759 } 794 760 795 static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name ) 796 { 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 } 761 void msn_auth_got_contact_list( struct im_connection *ic ) 762 { 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" ); 771 } 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" ) ); 818 872 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 } 838 } 873 return 1; 874 }
Note: See TracChangeset
for help on using the changeset viewer.