Changes in protocols/msn/ns.c [eb54f56:e132b60]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
protocols/msn/ns.c
reb54f56 re132b60 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * 4 * Copyright 2002-201 0Wilmer van der Gaast and others *4 * Copyright 2002-2012 Wilmer van der Gaast and others * 5 5 \********************************************************************/ 6 6 … … 25 25 26 26 #include <ctype.h> 27 #include <sys/utsname.h> 27 28 #include "nogaim.h" 28 29 #include "msn.h" 29 30 #include "md5.h" 31 #include "sha1.h" 30 32 #include "soap.h" 31 33 #include "xmltree.h" … … 110 112 handler->rxlen = 0; 111 113 handler->rxq = g_new0( char, 1 ); 114 115 if( md->uuid == NULL ) 116 { 117 struct utsname name; 118 sha1_state_t sha[1]; 119 120 /* UUID == SHA1("BitlBee" + my hostname + MSN username) */ 121 sha1_init( sha ); 122 sha1_append( sha, (void*) "BitlBee", 7 ); 123 if( uname( &name ) == 0 ) 124 { 125 sha1_append( sha, (void*) name.nodename, strlen( name.nodename ) ); 126 } 127 sha1_append( sha, (void*) ic->acc->user, strlen( ic->acc->user ) ); 128 md->uuid = sha1_random_uuid( sha ); 129 memcpy( md->uuid, "b171be3e", 8 ); /* :-P */ 130 } 112 131 113 132 if( msn_ns_write( ic, source, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER ) ) … … 353 372 return st; 354 373 } 355 else if( strcmp( cmd[0], "ILN" ) == 0 )374 else if( strcmp( cmd[0], "ILN" ) == 0 || strcmp( cmd[0], "NLN" ) == 0 ) 356 375 { 357 376 const struct msn_away_state *st; 377 const char *handle; 378 int cap = 0; 358 379 359 380 if( num_parts < 6 ) … … 363 384 return( 0 ); 364 385 } 365 366 http_decode( cmd[5] ); 367 imcb_rename_buddy( ic, cmd[3], cmd[5] ); 368 369 st = msn_away_state_by_code( cmd[2] ); 386 /* ILN and NLN are more or less the same, except ILN has a trId 387 at the start, and NLN has a capability field at the end. 388 Does ILN still exist BTW? */ 389 if( cmd[0][1] == 'I' ) 390 cmd ++; 391 else 392 cap = atoi( cmd[4] ); 393 394 handle = msn_normalize_handle( cmd[2] ); 395 if( strcmp( handle, ic->acc->user ) == 0 ) 396 return 1; /* That's me! */ 397 398 http_decode( cmd[3] ); 399 imcb_rename_buddy( ic, handle, cmd[3] ); 400 401 st = msn_away_state_by_code( cmd[1] ); 370 402 if( !st ) 371 403 { … … 374 406 } 375 407 376 imcb_buddy_status( ic, cmd[3], OPT_LOGGED_IN | 377 ( st != msn_away_state_list ? OPT_AWAY : 0 ), 378 st->name, NULL ); 379 } 380 else if( strcmp( cmd[0], "FLN" ) == 0 ) 381 { 382 if( cmd[1] == NULL ) 383 return 1; 384 385 imcb_buddy_status( ic, cmd[1], 0, NULL, NULL ); 386 387 msn_sb_start_keepalives( msn_sb_by_handle( ic, cmd[1] ), TRUE ); 388 } 389 else if( strcmp( cmd[0], "NLN" ) == 0 ) 390 { 391 const struct msn_away_state *st; 392 int cap; 393 394 if( num_parts < 6 ) 395 { 396 imcb_error( ic, "Syntax error" ); 397 imc_logout( ic, TRUE ); 398 return( 0 ); 399 } 400 401 http_decode( cmd[4] ); 402 cap = atoi( cmd[5] ); 403 imcb_rename_buddy( ic, cmd[2], cmd[4] ); 404 405 st = msn_away_state_by_code( cmd[1] ); 406 if( !st ) 407 { 408 /* FIXME: Warn/Bomb about unknown away state? */ 409 st = msn_away_state_list + 1; 410 } 411 412 imcb_buddy_status( ic, cmd[2], OPT_LOGGED_IN | 408 imcb_buddy_status( ic, handle, OPT_LOGGED_IN | 413 409 ( st != msn_away_state_list ? OPT_AWAY : 0 ) | 414 410 ( cap & 1 ? OPT_MOBILE : 0 ), 415 411 st->name, NULL ); 416 412 417 msn_sb_stop_keepalives( msn_sb_by_handle( ic, cmd[2] ) ); 413 msn_sb_stop_keepalives( msn_sb_by_handle( ic, handle ) ); 414 } 415 else if( strcmp( cmd[0], "FLN" ) == 0 ) 416 { 417 const char *handle; 418 419 if( cmd[1] == NULL ) 420 return 1; 421 422 handle = msn_normalize_handle( cmd[1] ); 423 imcb_buddy_status( ic, handle, 0, NULL, NULL ); 424 msn_sb_start_keepalives( msn_sb_by_handle( ic, handle ), TRUE ); 418 425 } 419 426 else if( strcmp( cmd[0], "RNG" ) == 0 ) … … 462 469 else 463 470 { 464 sb->who = g_strdup( cmd[5]);471 sb->who = g_strdup( msn_normalize_handle( cmd[5] ) ); 465 472 } 466 473 } … … 555 562 { 556 563 /* Status message. */ 557 if( num_parts >= 4)558 handler->msglen = atoi( cmd[ 3] );564 if( num_parts >= 3 ) 565 handler->msglen = atoi( cmd[2] ); 559 566 } 560 567 else if( strcmp( cmd[0], "NOT" ) == 0 ) … … 564 571 if( num_parts >= 2 ) 565 572 handler->msglen = atoi( cmd[1] ); 573 } 574 else if( strcmp( cmd[0], "UBM" ) == 0 ) 575 { 576 if( num_parts >= 7 ) 577 handler->msglen = atoi( cmd[6] ); 578 } 579 else if( strcmp( cmd[0], "QNG" ) == 0 ) 580 { 581 ic->flags |= OPT_PONGED; 566 582 } 567 583 else if( isdigit( cmd[0][0] ) ) … … 668 684 else if( g_strncasecmp( ct, "text/x-msmsgsactivemailnotification", 35 ) == 0 ) 669 685 { 670 /* Sorry, but this one really is *USELESS* */ 686 } 687 else if( g_strncasecmp( ct, "text/x-msmsgsinitialmdatanotification", 37 ) == 0 || 688 g_strncasecmp( ct, "text/x-msmsgsoimnotification", 28 ) == 0 ) 689 { 690 /* We received an offline message. Or at least notification 691 that there is one waiting for us. Fetching the message(s) 692 and purging them from the server is a lot of SOAPy work 693 not worth doing IMHO. Also I thought it was possible to 694 have the notification server send them directly, I was 695 pretty sure I saw Pidgin do it.. 696 697 At least give a notification for now, seems like a 698 reasonable thing to do. Only problem is, they'll keep 699 coming back at login time until you read them using a 700 different client. :-( */ 701 702 char *xml = get_rfc822_header( body, "Mail-Data:", blen ); 703 struct xt_node *md, *m; 704 705 if( !xml ) 706 return 1; 707 md = xt_from_string( xml, 0 ); 708 if( !md ) 709 return 1; 710 711 for( m = md->children; ( m = xt_find_node( m, "M" ) ); m = m->next ) 712 { 713 struct xt_node *e = xt_find_node( m->children, "E" ); 714 struct xt_node *rt = xt_find_node( m->children, "RT" ); 715 struct tm tp; 716 time_t msgtime = 0; 717 718 if( !e || !e->text ) 719 continue; 720 721 memset( &tp, 0, sizeof( tp ) ); 722 if( rt && rt->text && 723 sscanf( rt->text, "%4d-%2d-%2dT%2d:%2d:%2d.", 724 &tp.tm_year, &tp.tm_mon, &tp.tm_mday, 725 &tp.tm_hour, &tp.tm_min, &tp.tm_sec ) == 6 ) 726 { 727 tp.tm_year -= 1900; 728 tp.tm_mon --; 729 msgtime = mktime_utc( &tp ); 730 731 } 732 imcb_buddy_msg( ic, e->text, "<< \002BitlBee\002 - Received offline message. BitlBee can't show these. >>", 0, msgtime ); 733 } 734 735 g_free( xml ); 736 xt_free_node( md ); 671 737 } 672 738 else … … 683 749 char *psm_text = NULL; 684 750 685 ubx = xt_from_string( msg );751 ubx = xt_from_string( msg, msglen ); 686 752 if( ubx && strcmp( ubx->name, "Data" ) == 0 && 687 753 ( psm = xt_find_node( ubx->children, "PSM" ) ) ) 688 754 psm_text = psm->text; 689 755 690 imcb_buddy_status_msg( ic, cmd[1], psm_text );756 imcb_buddy_status_msg( ic, msn_normalize_handle( cmd[1] ), psm_text ); 691 757 xt_free_node( ubx ); 692 758 } … … 695 761 struct xt_node *adl, *d, *c; 696 762 697 if( !( adl = xt_from_string( msg ) ) )763 if( !( adl = xt_from_string( msg, msglen ) ) ) 698 764 return 1; 699 765 … … 716 782 continue; 717 783 784 /* FIXME: Use "t" here, guess I should just add it 785 as a prefix like elsewhere in the protocol. */ 718 786 handle = g_strdup_printf( "%s@%s", cn, dn ); 719 787 if( !( ( bu = bee_user_by_handle( ic->bee, ic, handle ) ) || … … 741 809 } 742 810 } 743 744 return( 1 ); 811 else if( strcmp( cmd[0], "UBM" ) == 0 ) 812 { 813 /* This one will give us msgs from federated networks. Technically 814 it should also get us offline messages, but I don't know how 815 I can signal MSN servers to use it. */ 816 char *ct, *handle; 817 818 if( strcmp( cmd[1], ic->acc->user ) == 0 ) 819 { 820 /* With MPOP, you'll get copies of your own msgs from other 821 sessions. Discard those at least for now. */ 822 return 1; 823 } 824 825 ct = get_rfc822_header( msg, "Content-Type", msglen ); 826 if( strncmp( ct, "text/plain", 10 ) != 0 ) 827 { 828 /* Typing notification or something? */ 829 g_free( ct ); 830 return 1; 831 } 832 if( strcmp( cmd[2], "1" ) != 0 ) 833 handle = g_strdup_printf( "%s:%s", cmd[2], cmd[1] ); 834 else 835 handle = g_strdup( cmd[1] ); 836 837 imcb_buddy_msg( ic, handle, body, 0, 0 ); 838 g_free( handle ); 839 } 840 841 return 1; 745 842 } 746 843 … … 757 854 if( token ) 758 855 { 759 msn_ns_write( ic, -1, "USR %d SSO S %s %s \r\n", ++md->trId, md->tokens[0], token);856 msn_ns_write( ic, -1, "USR %d SSO S %s %s {%s}\r\n", ++md->trId, md->tokens[0], token, md->uuid ); 760 857 } 761 858 else … … 809 906 xt_add_attr( c, "n", handle ); 810 907 xt_add_attr( c, "l", l ); 811 xt_add_attr( c, "t", "1" ); /* 1 means normal, 4 means mobile?*/908 xt_add_attr( c, "t", "1" ); /* FIXME: Network type, i.e. 32 for Y!MSG */ 812 909 xt_insert_child( d, c ); 813 910 … … 886 983 return 1; 887 984 } 985 986 int msn_ns_sendmessage( struct im_connection *ic, bee_user_t *bu, const char *text ) 987 { 988 struct msn_data *md = ic->proto_data; 989 int type = 0; 990 char *buf, *handle; 991 992 if( strncmp( text, "\r\r\r", 3 ) == 0 ) 993 /* Err. Shouldn't happen but I guess it can. Don't send others 994 any of the "SHAKE THAT THING" messages. :-D */ 995 return 1; 996 997 /* This might be a federated contact. Get its network number, 998 prefixed to bu->handle with a colon. Default is 1. */ 999 for( handle = bu->handle; isdigit( *handle ); handle ++ ) 1000 type = type * 10 + *handle - '0'; 1001 if( *handle == ':' ) 1002 handle ++; 1003 else 1004 type = 1; 1005 1006 buf = g_strdup_printf( "%s%s", MSN_MESSAGE_HEADERS, text ); 1007 1008 if( msn_ns_write( ic, -1, "UUM %d %s %d %d %zd\r\n%s", 1009 ++md->trId, handle, type, 1010 1, /* type == IM (not nudge/typing) */ 1011 strlen( buf ), buf ) ) 1012 return 1; 1013 else 1014 return 0; 1015 } 1016 1017 void msn_ns_oim_send_queue( struct im_connection *ic, GSList **msgq ) 1018 { 1019 GSList *l; 1020 1021 for( l = *msgq; l; l = l->next ) 1022 { 1023 struct msn_message *m = l->data; 1024 bee_user_t *bu = bee_user_by_handle( ic->bee, ic, m->who ); 1025 1026 if( bu ) 1027 if( !msn_ns_sendmessage( ic, bu, m->text ) ) 1028 return; 1029 } 1030 1031 while( *msgq != NULL ) 1032 { 1033 struct msn_message *m = (*msgq)->data; 1034 1035 g_free( m->who ); 1036 g_free( m->text ); 1037 g_free( m ); 1038 1039 *msgq = g_slist_remove( *msgq, m ); 1040 } 1041 }
Note: See TracChangeset
for help on using the changeset viewer.