Changes in / [feb1bad:b0a89cc]
- Files:
-
- 2 added
- 4 deleted
- 23 edited
Legend:
- Unmodified
- Added
- Removed
-
configure
rfeb1bad rb0a89cc 423 423 fi; 424 424 425 if [ "$msn" = "1" -a "$ssl" != "openssl" ]; then426 # Needed for MSN only. OpenSSL exports nice cipher functions already,427 # others don't, so use our own 3des code.428 echo 'DES=des.o' >> Makefile.settings429 fi430 431 425 echo 'SSL_CLIENT=ssl_'$ssl'.o' >> Makefile.settings 432 426 -
doc/CHANGES
rfeb1bad rb0a89cc 4 4 http://bugs.bitlbee.org/bitlbee/timeline?daysback=90&changeset=on 5 5 6 Version ...6 Version 1.3dev: 7 7 - For the first time since 2007, a dev snapshot. Like then, this is pretty 8 8 stable already (running on testing.bitlbee.org for weeks by now), but not … … 52 52 for a list of supported protocols (works only in libpurple-enabled 53 53 binaries). 54 - Rewritten MSN module, implementing MSNP15 instead of the old MSNP8:55 * MSNP8 support from MSN was getting pretty unreliable. There were issues56 with remembering display names and adding contacts/auth requests.57 * Support for sending offline messages.58 * Support for setting and reading status messages.59 54 - Support for file transfers, in and out. /DCC SEND a file to a contact and 60 55 it becomes a file transfer, and incoming file transfers become /DCC SENDs … … 64 59 fixes issues with authorization requests. 65 60 66 Finished ...61 Finished 6 Aug 2010 67 62 68 63 Version 1.2.8: -
lib/Makefile
rfeb1bad rb0a89cc 13 13 14 14 # [SH] Program variables 15 objects = arc.o base64.o $( DES) $(EVENT_HANDLER) ftutil.o http_client.o ini.o md5.o misc.o oauth.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o15 objects = arc.o base64.o $(EVENT_HANDLER) ftutil.o http_client.o ini.o md5.o misc.o oauth.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o 16 16 17 17 LFLAGS += -r -
lib/misc.c
rfeb1bad rb0a89cc 298 298 void http_encode( char *s ) 299 299 { 300 char t[strlen(s)+1];300 char *t; 301 301 int i, j; 302 302 303 strcpy( t, s ); 303 t = g_strdup( s ); 304 304 305 for( i = j = 0; t[i]; i ++, j ++ ) 305 306 { … … 319 320 } 320 321 s[j] = 0; 322 323 g_free( t ); 321 324 } 322 325 -
lib/sha1.c
rfeb1bad rb0a89cc 36 36 */ 37 37 38 #include <string.h>39 38 #include "sha1.h" 40 39 … … 375 374 sha1_process_block(context); 376 375 } 377 378 #define HMAC_BLOCK_SIZE 64379 380 /* BitlBee addition: */381 void sha1_hmac(const char *key_, size_t key_len, const char *payload, size_t payload_len, uint8_t Message_Digest[sha1_hash_size])382 {383 sha1_state_t sha1;384 uint8_t hash[sha1_hash_size];385 uint8_t key[HMAC_BLOCK_SIZE+1];386 int i;387 388 if( key_len == 0 )389 key_len = strlen( key_ );390 if( payload_len == 0 )391 payload_len = strlen( payload );392 393 /* Create K. If our current key is >64 chars we have to hash it,394 otherwise just pad. */395 memset( key, 0, HMAC_BLOCK_SIZE + 1 );396 if( key_len > HMAC_BLOCK_SIZE )397 {398 sha1_init( &sha1 );399 sha1_append( &sha1, (uint8_t*) key_, key_len );400 sha1_finish( &sha1, key );401 }402 else403 {404 memcpy( key, key_, key_len );405 }406 407 /* Inner part: H(K XOR 0x36, text) */408 sha1_init( &sha1 );409 for( i = 0; i < HMAC_BLOCK_SIZE; i ++ )410 key[i] ^= 0x36;411 sha1_append( &sha1, key, HMAC_BLOCK_SIZE );412 sha1_append( &sha1, (const uint8_t*) payload, payload_len );413 sha1_finish( &sha1, hash );414 415 /* Final result: H(K XOR 0x5C, inner stuff) */416 sha1_init( &sha1 );417 for( i = 0; i < HMAC_BLOCK_SIZE; i ++ )418 key[i] ^= 0x36 ^ 0x5c;419 sha1_append( &sha1, key, HMAC_BLOCK_SIZE );420 sha1_append( &sha1, hash, sha1_hash_size );421 sha1_finish( &sha1, Message_Digest );422 } -
lib/sha1.h
rfeb1bad rb0a89cc 67 67 G_MODULE_EXPORT int sha1_append(sha1_state_t *, const uint8_t *, unsigned int); 68 68 G_MODULE_EXPORT int sha1_finish(sha1_state_t *, uint8_t Message_Digest[sha1_hash_size]); 69 G_MODULE_EXPORT void sha1_hmac(const char *key_, size_t key_len, const char *payload, size_t payload_len, uint8_t Message_Digest[sha1_hash_size]);70 69 71 70 #endif -
lib/ssl_client.h
rfeb1bad rb0a89cc 78 78 the same action as the handler that just received the SSL_AGAIN.) */ 79 79 G_MODULE_EXPORT b_input_condition ssl_getdirection( void *conn ); 80 81 G_MODULE_EXPORT size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, const unsigned char *input, size_t input_len, const unsigned char *iv, unsigned char **res); -
lib/ssl_gnutls.c
rfeb1bad rb0a89cc 189 189 ssl_errno = SSL_AGAIN; 190 190 191 if( 0 && getenv( "BITLBEE_DEBUG" ) && st > 0 ) write( 1, buf, st );192 193 191 return st; 194 192 } … … 209 207 if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED ) 210 208 ssl_errno = SSL_AGAIN; 211 212 if( 0 && getenv( "BITLBEE_DEBUG" ) && st > 0 ) write( 1, buf, st );213 209 214 210 return st; -
lib/ssl_openssl.c
rfeb1bad rb0a89cc 116 116 { 117 117 initialized = TRUE; 118 SSL_library_init(); 119 //SSLeay_add_ssl_algorithms(); 120 //OpenSSL_add_all_algorithms(); 118 SSLeay_add_ssl_algorithms(); 121 119 } 122 120 … … 207 205 } 208 206 209 if( 0 && getenv( "BITLBEE_DEBUG" ) && st > 0 ) write( 1, buf, st );210 211 207 return st; 212 208 } … … 223 219 224 220 st = SSL_write( ((struct scd*)conn)->ssl, buf, len ); 225 226 if( 0 && getenv( "BITLBEE_DEBUG" ) && st > 0 ) write( 1, buf, st );227 221 228 222 ssl_errno = SSL_OK; … … 278 272 return( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ? B_EV_IO_WRITE : B_EV_IO_READ ); 279 273 } 280 281 size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, const unsigned char *input, size_t input_len, const unsigned char *iv, unsigned char **res)282 {283 int output_length = 0;284 EVP_CIPHER_CTX ctx;285 286 *res = g_new0(unsigned char, 72);287 288 /* Don't set key or IV because we will modify the parameters */289 EVP_CIPHER_CTX_init(&ctx);290 EVP_CipherInit_ex(&ctx, EVP_des_ede3_cbc(), NULL, NULL, NULL, 1);291 EVP_CIPHER_CTX_set_key_length(&ctx, key_len);292 EVP_CIPHER_CTX_set_padding(&ctx, 0);293 /* We finished modifying parameters so now we can set key and IV */294 EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, 1);295 EVP_CipherUpdate(&ctx, *res, &output_length, input, input_len);296 EVP_CipherFinal_ex(&ctx, *res, &output_length);297 EVP_CIPHER_CTX_cleanup(&ctx);298 //EVP_cleanup();299 300 return output_length;301 } -
lib/xmltree.c
rfeb1bad rb0a89cc 141 141 /* Feed the parser, don't execute any handler. Returns -1 on errors, 0 on 142 142 end-of-stream and 1 otherwise. */ 143 int xt_feed( struct xt_parser *xt, c onst char *text, int text_len )143 int xt_feed( struct xt_parser *xt, char *text, int text_len ) 144 144 { 145 145 if( !g_markup_parse_context_parse( xt->parser, text, text_len, &xt->gerr ) ) … … 174 174 if( node->flags & XT_COMPLETE && !( node->flags & XT_SEEN ) ) 175 175 { 176 if( xt->handlers )for( i = 0; xt->handlers[i].func; i ++ )176 for( i = 0; xt->handlers[i].func; i ++ ) 177 177 { 178 178 /* This one is fun! \o/ */ 179 179 180 180 /* If handler.name == NULL it means it should always match. */ 181 181 if( ( xt->handlers[i].name == NULL || 182 182 /* If it's not, compare. There should always be a name. */ 183 183 g_strcasecmp( xt->handlers[i].name, node->name ) == 0 ) && 184 184 /* If handler.parent == NULL, it's a match. */ 185 185 ( xt->handlers[i].parent == NULL || 186 186 /* If there's a parent node, see if the name matches. */ 187 187 ( node->parent ? g_strcasecmp( xt->handlers[i].parent, node->parent->name ) == 0 : 188 189 strcmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) )188 /* If there's no parent, the handler should mention <root> as a parent. */ 189 g_strcasecmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) ) 190 190 { 191 191 st = xt->handlers[i].func( node, xt->data ); … … 260 260 } 261 261 262 struct xt_node *xt_from_string( const char *in )263 {264 struct xt_parser *parser;265 struct xt_node *ret;266 267 parser = xt_new( NULL, NULL );268 xt_feed( parser, in, strlen( in ) );269 ret = parser->root;270 parser->root = NULL;271 xt_free( parser );272 273 return ret;274 }275 276 262 static void xt_to_string_real( struct xt_node *node, GString *str ) 277 263 { … … 331 317 /* Indentation */ 332 318 for( c = node; c->parent; c = c->parent ) 333 printf( " 319 printf( "\t" ); 334 320 335 321 /* Start the tag */ … … 338 324 /* Print the attributes */ 339 325 for( i = 0; node->attr[i].key; i ++ ) 340 { 341 char *v = g_markup_escape_text( node->attr[i].value, -1 ); 342 printf( " %s=\"%s\"", node->attr[i].key, v ); 343 g_free( v ); 344 } 326 printf( " %s=\"%s\"", node->attr[i].key, g_markup_escape_text( node->attr[i].value, -1 ) ); 345 327 346 328 /* /> in case there's really *nothing* inside this tag, otherwise … … 362 344 for( i = 0; node->text[i] && isspace( node->text[i] ); i ++ ); 363 345 if( node->text[i] ) 364 { 365 char *v = g_markup_escape_text( node->text, -1 ); 366 printf( "%s", v ); 367 g_free( v ); 368 } 346 printf( "%s", g_markup_escape_text( node->text, -1 ) ); 369 347 } 370 348 … … 377 355 if( node->children ) 378 356 for( c = node; c->parent; c = c->parent ) 379 printf( " 357 printf( "\t" ); 380 358 381 359 /* Non-empty tag is now finished. */ … … 482 460 483 461 node = node->next; 484 }485 486 return node;487 }488 489 /* More advanced than the one above, understands something like490 ../foo/bar to find a subnode bar of a node foo which is a child491 of node's parent. Pass the node directly, not its list of children. */492 struct xt_node *xt_find_path( struct xt_node *node, const char *name )493 {494 while( name && *name && node )495 {496 char *colon, *slash;497 int n;498 499 if( ( slash = strchr( name, '/' ) ) )500 n = slash - name;501 else502 n = strlen( name );503 504 if( strncmp( name, "..", n ) == 0 )505 {506 node = node->parent;507 }508 else509 {510 node = node->children;511 512 while( node )513 {514 if( g_strncasecmp( node->name, name, n ) == 0 ||515 ( ( colon = strchr( node->name, ':' ) ) &&516 g_strncasecmp( colon + 1, name, n ) == 0 ) )517 break;518 519 node = node->next;520 }521 }522 523 name = slash ? slash + 1 : NULL;524 462 } 525 463 … … 612 550 } 613 551 614 /* Same, but at the beginning. */615 void xt_insert_child( struct xt_node *parent, struct xt_node *child )616 {617 struct xt_node *node, *last;618 619 for( node = child; node; node = node->next )620 {621 if( node->parent != NULL )622 {623 /* ERROR CONDITION: They seem to have a parent already??? */624 }625 626 node->parent = parent;627 last = node;628 }629 630 last->next = parent->children;631 parent->children = child;632 }633 634 552 void xt_add_attr( struct xt_node *node, const char *key, const char *value ) 635 553 { -
lib/xmltree.h
rfeb1bad rb0a89cc 79 79 struct xt_parser *xt_new( const struct xt_handler_entry *handlers, gpointer data ); 80 80 void xt_reset( struct xt_parser *xt ); 81 int xt_feed( struct xt_parser *xt, c onst char *text, int text_len );81 int xt_feed( struct xt_parser *xt, char *text, int text_len ); 82 82 int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ); 83 83 void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth ); 84 struct xt_node *xt_from_string( const char *in );85 84 char *xt_to_string( struct xt_node *node ); 86 85 void xt_print( struct xt_node *node ); … … 89 88 void xt_free( struct xt_parser *xt ); 90 89 struct xt_node *xt_find_node( struct xt_node *node, const char *name ); 91 struct xt_node *xt_find_path( struct xt_node *node, const char *name );92 90 char *xt_find_attr( struct xt_node *node, const char *key ); 93 91 94 92 struct xt_node *xt_new_node( char *name, const char *text, struct xt_node *children ); 95 93 void xt_add_child( struct xt_node *parent, struct xt_node *child ); 96 void xt_insert_child( struct xt_node *parent, struct xt_node *child );97 94 void xt_add_attr( struct xt_node *node, const char *key, const char *value ); 98 95 int xt_remove_attr( struct xt_node *node, const char *key ); -
protocols/bee.h
rfeb1bad rb0a89cc 151 151 * - 'state' and 'message' can be NULL */ 152 152 G_MODULE_EXPORT void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message ); 153 G_MODULE_EXPORT void imcb_buddy_status_msg( struct im_connection *ic, const char *handle, const char *message );154 153 G_MODULE_EXPORT void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle ); 155 154 /* Call when a handle says something. 'flags' and 'sent_at may be just 0. */ -
protocols/bee_user.c
rfeb1bad rb0a89cc 187 187 /* TODO(wilmer): OPT_AWAY, or just state == NULL ? */ 188 188 bu->flags = flags; 189 bu->status = g_strdup( ( flags & OPT_AWAY ) && state == NULL ? "Away" : state ); 189 190 bu->status_msg = g_strdup( message ); 190 if( state && *state )191 bu->status = g_strdup( state );192 else if( flags & OPT_AWAY )193 bu->status = g_strdup( "Away" );194 else195 bu->status = NULL;196 191 197 192 if( bu->status == NULL && ( flags & OPT_MOBILE ) && … … 207 202 g_free( old->status_msg ); 208 203 g_free( old->status ); 209 g_free( old );210 }211 212 /* Same, but only change the away/status message, not any away/online state info. */213 void imcb_buddy_status_msg( struct im_connection *ic, const char *handle, const char *message )214 {215 bee_t *bee = ic->bee;216 bee_user_t *bu, *old;217 218 if( !( bu = bee_user_by_handle( bee, ic, handle ) ) )219 {220 return;221 }222 223 old = g_memdup( bu, sizeof( bee_user_t ) );224 225 bu->status_msg = message && *message ? g_strdup( message ) : NULL;226 227 if( bee->ui->user_status )228 bee->ui->user_status( bee, bu, old );229 230 g_free( old->status_msg );231 204 g_free( old ); 232 205 } -
protocols/msn/Makefile
rfeb1bad rb0a89cc 13 13 14 14 # [SH] Program variables 15 objects = msn.o msn_util.o ns.o sb.o soap.o tables.o15 objects = msn.o msn_util.o ns.o passport.o sb.o tables.o 16 16 17 17 LFLAGS += -r -
protocols/msn/msn.c
rfeb1bad rb0a89cc 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * 4 * Copyright 2002-20 10Wilmer van der Gaast and others *4 * Copyright 2002-2004 Wilmer van der Gaast and others * 5 5 \********************************************************************/ 6 6 … … 25 25 26 26 #include "nogaim.h" 27 #include "soap.h"28 27 #include "msn.h" 29 28 … … 36 35 static void msn_init( account_t *acc ) 37 36 { 38 set_t *s; 39 40 s = set_add( &acc->set, "display_name", NULL, set_eval_display_name, acc ); 41 s->flags |= ACC_SET_NOSAVE | ACC_SET_ONLINE_ONLY; 42 37 set_add( &acc->set, "display_name", NULL, set_eval_display_name, acc ); 38 set_add( &acc->set, "local_display_name", "false", set_eval_bool, acc ); 43 39 set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc ); 44 40 set_add( &acc->set, "switchboard_keepalives", "false", set_eval_bool, acc ); 45 46 acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE;47 41 } 48 42 … … 74 68 md->ic = ic; 75 69 md->away_state = msn_away_state_list; 76 md->domaintree = g_tree_new( msn_domaintree_cmp );77 70 78 71 msn_connections = g_slist_append( msn_connections, ic ); … … 83 76 struct msn_data *md = ic->proto_data; 84 77 GSList *l; 85 int i;86 78 87 79 if( md ) … … 108 100 msn_msgq_purge( ic, &md->msgq ); 109 101 110 for( i = 0; i < sizeof( md->tokens ) / sizeof( md->tokens[0] ); i ++ ) 111 g_free( md->tokens[i] ); 112 g_free( md->lock_key ); 113 114 while( md->groups ) 115 { 116 struct msn_group *mg = md->groups->data; 117 g_free( mg->id ); 118 g_free( mg->name ); 119 g_free( mg ); 120 md->groups = g_slist_remove( md->groups, mg ); 121 } 122 123 g_tree_destroy( md->domaintree ); 124 md->domaintree = NULL; 102 while( md->groupcount > 0 ) 103 g_free( md->grouplist[--md->groupcount] ); 104 g_free( md->grouplist ); 125 105 126 106 while( md->grpq ) … … 194 174 { 195 175 char buf[1024]; 196 char *uux;197 176 struct msn_data *md = ic->proto_data; 198 177 … … 203 182 204 183 g_snprintf( buf, sizeof( buf ), "CHG %d %s\r\n", ++md->trId, md->away_state->code ); 205 if( !msn_write( ic, buf, strlen( buf ) ) ) 206 return; 207 208 uux = g_markup_printf_escaped( "<Data><PSM>%s</PSM><CurrentMedia></CurrentMedia>" 209 "</Data>", message ? message : "" ); 210 g_snprintf( buf, sizeof( buf ), "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux ); 211 if( !msn_write( ic, buf, strlen( buf ) ) ) 212 return; 184 msn_write( ic, buf, strlen( buf ) ); 185 } 186 187 static void msn_set_my_name( struct im_connection *ic, char *info ) 188 { 189 msn_set_display_name( ic, info ); 213 190 } 214 191 … … 223 200 struct bee_user *bu = bee_user_by_handle( ic->bee, ic, who ); 224 201 225 msn_buddy_list_add( ic, MSN_BUDDY_FL, who, who, group );202 msn_buddy_list_add( ic, "FL", who, who, group ); 226 203 if( bu && bu->group ) 227 msn_buddy_list_remove( ic, MSN_BUDDY_FL, who, bu->group->name );204 msn_buddy_list_remove( ic, "FL", who, bu->group->name ); 228 205 } 229 206 230 207 static void msn_remove_buddy( struct im_connection *ic, char *who, char *group ) 231 208 { 232 msn_buddy_list_remove( ic, MSN_BUDDY_FL, who, NULL );209 msn_buddy_list_remove( ic, "FL", who, NULL ); 233 210 } 234 211 … … 295 272 static void msn_add_permit( struct im_connection *ic, char *who ) 296 273 { 297 msn_buddy_list_add( ic, MSN_BUDDY_AL, who, who, NULL );274 msn_buddy_list_add( ic, "AL", who, who, NULL ); 298 275 } 299 276 300 277 static void msn_rem_permit( struct im_connection *ic, char *who ) 301 278 { 302 msn_buddy_list_remove( ic, MSN_BUDDY_AL, who, NULL );279 msn_buddy_list_remove( ic, "AL", who, NULL ); 303 280 } 304 281 … … 307 284 struct msn_switchboard *sb; 308 285 309 msn_buddy_list_add( ic, MSN_BUDDY_BL, who, who, NULL );286 msn_buddy_list_add( ic, "BL", who, who, NULL ); 310 287 311 288 /* If there's still a conversation with this person, close it. */ … … 318 295 static void msn_rem_deny( struct im_connection *ic, char *who ) 319 296 { 320 msn_buddy_list_remove( ic, MSN_BUDDY_BL, who, NULL );297 msn_buddy_list_remove( ic, "BL", who, NULL ); 321 298 } 322 299 … … 337 314 account_t *acc = set->data; 338 315 struct im_connection *ic = acc->ic; 339 struct msn_data *md = ic->proto_data; 316 317 /* Allow any name if we're offline. */ 318 if( ic == NULL ) 319 return value; 340 320 341 321 if( strlen( value ) > 129 ) … … 345 325 } 346 326 347 if( md->flags & MSN_GOT_PROFILE_DN ) 348 imcb_log( ic, "Warning: Persistent name changes for this account have to be done " 349 "in the profile. BitlBee doesn't currently support this." ); 350 351 msn_soap_addressbook_set_display_name( ic, value ); 352 return msn_ns_set_display_name( ic, value ) ? value : NULL; 353 } 354 355 static void msn_buddy_data_add( bee_user_t *bu ) 356 { 357 struct msn_data *md = bu->ic->proto_data; 358 bu->data = g_new0( struct msn_buddy_data, 1 ); 359 g_tree_insert( md->domaintree, bu->handle, bu ); 360 } 361 362 static void msn_buddy_data_free( bee_user_t *bu ) 363 { 364 struct msn_data *md = bu->ic->proto_data; 365 g_tree_remove( md->domaintree, bu->handle ); 366 g_free( bu->data ); 327 /* Returning NULL would be better, because the server still has to 328 confirm the name change. However, it looks a bit confusing to the 329 user. */ 330 return msn_set_display_name( ic, value ) ? value : NULL; 367 331 } 368 332 … … 379 343 ret->set_away = msn_set_away; 380 344 ret->get_info = msn_get_info; 345 ret->set_my_name = msn_set_my_name; 381 346 ret->add_buddy = msn_add_buddy; 382 347 ret->remove_buddy = msn_remove_buddy; … … 392 357 ret->send_typing = msn_send_typing; 393 358 ret->handle_cmp = g_strcasecmp; 394 ret->buddy_data_add = msn_buddy_data_add;395 ret->buddy_data_free = msn_buddy_data_free;396 397 359 //ret->transfer_request = msn_ftp_transfer_request; 398 360 -
protocols/msn/msn.h
rfeb1bad rb0a89cc 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * 4 * Copyright 2002-20 10Wilmer van der Gaast and others *4 * Copyright 2002-2004 Wilmer van der Gaast and others * 5 5 \********************************************************************/ 6 6 … … 39 39 #endif 40 40 41 /* This should be MSN Messenger 7.0.0813 42 #define MSNP11_PROD_KEY "CFHUR$52U_{VIX5T" 43 #define MSNP11_PROD_ID "PROD0101{0RM?UBW" 44 */ 45 46 /* Some other version. 47 #define MSNP11_PROD_KEY "O4BG@C7BWLYQX?5G" 48 #define MSNP11_PROD_ID "PROD01065C%ZFN6F" 49 */ 50 51 #define MSNP11_PROD_KEY "ILTXC!4IXB5FB*PX" 52 #define MSNP11_PROD_ID "PROD0119GSJUC$18" 53 #define MSNP_VER "MSNP15" 54 #define MSNP_BUILD "8.5.1288" 41 #define QRY_NAME "msmsgs@msnmsgr.com" 42 #define QRY_CODE "Q1P7W2E4J9R8U3S5" 55 43 56 44 #define MSN_SB_NEW -24062002 … … 73 61 #define PROFILE_URL "http://members.msn.com/" 74 62 75 typedef enum76 {77 MSN_GOT_PROFILE = 1,78 MSN_GOT_PROFILE_DN = 2,79 MSN_DONE_ADL = 4,80 } msn_flags_t;81 82 63 struct msn_data 83 64 { … … 86 67 int fd; 87 68 struct msn_handler_data *handler; 88 msn_flags_t flags;89 69 90 70 int trId; 91 char *tokens[4];92 char *lock_key;93 71 94 72 GSList *msgq, *grpq; … … 96 74 int sb_failures; 97 75 time_t first_sb_failure; 76 GSList *filetransfers; 98 77 99 78 const struct msn_away_state *away_state; 100 GSList *groups; 101 102 /* Mostly used for sending the ADL command; since MSNP13 the client 103 is responsible for downloading the contact list and then sending 104 it to the MSNP server. */ 105 GTree *domaintree; 106 int adl_todo; 79 int buddycount; 80 int groupcount; 81 char **grouplist; 107 82 }; 108 83 … … 165 140 int (*exec_command) ( gpointer data, char **cmd, int count ); 166 141 int (*exec_message) ( gpointer data, char *msg, int msglen, char **cmd, int count ); 167 };168 169 typedef enum170 {171 MSN_BUDDY_FL = 1, /* Warning: FL,AL,BL *must* be 1,2,4. */172 MSN_BUDDY_AL = 2,173 MSN_BUDDY_BL = 4,174 MSN_BUDDY_RL = 8,175 MSN_BUDDY_PL = 16,176 MSN_BUDDY_ADL_SYNCED = 256,177 } msn_buddy_flags_t;178 179 struct msn_buddy_data180 {181 char *cid;182 msn_buddy_flags_t flags;183 };184 185 struct msn_group186 {187 char *name;188 char *id;189 142 }; 190 143 … … 209 162 /* ns.c */ 210 163 gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ); 211 void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error );212 void msn_auth_got_contact_list( struct im_connection *ic );213 int msn_ns_finish_login( struct im_connection *ic );214 164 215 165 /* msn_util.c */ 216 166 int msn_write( struct im_connection *ic, char *s, int len ); 217 167 int msn_logged_in( struct im_connection *ic ); 218 int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_tlist, const char *who, const char *realname_, const char *group );219 int msn_buddy_list_remove( struct im_connection *ic, msn_buddy_flags_tlist, const char *who, const char *group );220 void msn_buddy_ask( bee_user_t *bu);168 int msn_buddy_list_add( struct im_connection *ic, const char *list, const char *who, const char *realname_, const char *group ); 169 int msn_buddy_list_remove( struct im_connection *ic, char *list, const char *who, const char *group ); 170 void msn_buddy_ask( struct im_connection *ic, char *handle, char *realname ); 221 171 char *msn_findheader( char *text, char *header, int len ); 222 172 char **msn_linesplit( char *line ); 223 173 int msn_handler( struct msn_handler_data *h ); 174 char *msn_http_encode( const char *input ); 224 175 void msn_msgq_purge( struct im_connection *ic, GSList **list ); 225 char *msn_p11_challenge( char *challenge ); 226 gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ ); 227 struct msn_group *msn_group_by_name( struct im_connection *ic, const char *name ); 228 struct msn_group *msn_group_by_id( struct im_connection *ic, const char *id ); 229 int msn_ns_set_display_name( struct im_connection *ic, const char *value ); 176 gboolean msn_set_display_name( struct im_connection *ic, const char *rawname ); 230 177 231 178 /* tables.c */ … … 249 196 void msn_sb_stop_keepalives( struct msn_switchboard *sb ); 250 197 198 /* invitation.c */ 199 void msn_ftp_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who ); 200 251 201 #endif //_MSN_H -
protocols/msn/msn_util.c
rfeb1bad rb0a89cc 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * 4 * Copyright 2002-20 10Wilmer van der Gaast and others *4 * Copyright 2002-2004 Wilmer van der Gaast and others * 5 5 \********************************************************************/ 6 6 … … 26 26 #include "nogaim.h" 27 27 #include "msn.h" 28 #include "md5.h"29 #include "soap.h"30 28 #include <ctype.h> 31 29 … … 34 32 struct msn_data *md = ic->proto_data; 35 33 int st; 36 37 if( getenv( "BITLBEE_DEBUG" ) )38 {39 write( 2, "->NS:", 5 );40 write( 2, s, len );41 }42 34 43 35 st = write( md->fd, s, len ); … … 59 51 } 60 52 61 static char *adlrml_entry( const char *handle_, msn_buddy_flags_t list ) 62 { 63 char *domain, handle[strlen(handle_)+1]; 64 65 strcpy( handle, handle_ ); 66 if( ( domain = strchr( handle, '@' ) ) ) 67 *(domain++) = '\0'; 68 else 69 return NULL; 70 71 return g_markup_printf_escaped( "<ml><d n=\"%s\"><c n=\"%s\" l=\"%d\" t=\"1\"/></d></ml>", 72 domain, handle, list ); 73 } 74 75 int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname, const char *group ) 53 int msn_buddy_list_add( struct im_connection *ic, const char *list, const char *who, const char *realname_, const char *group ) 76 54 { 77 55 struct msn_data *md = ic->proto_data; 78 char buf[1024], groupid[8]; 79 bee_user_t *bu; 80 struct msn_buddy_data *bd; 81 char *adl; 56 char buf[1024], *realname, groupid[8]; 82 57 83 58 *groupid = '\0'; 84 #if 085 59 if( group ) 86 60 { … … 113 87 if( l == NULL ) 114 88 { 115 char groupname[strlen(group)+1]; 116 strcpy( groupname, group ); 117 http_encode( groupname ); 89 char *groupname = msn_http_encode( group ); 118 90 g_snprintf( buf, sizeof( buf ), "ADG %d %s %d\r\n", ++md->trId, groupname, 0 ); 91 g_free( groupname ); 119 92 return msn_write( ic, buf, strlen( buf ) ); 120 93 } … … 128 101 } 129 102 } 130 #endif 131 132 if( !( ( bu = bee_user_by_handle( ic->bee, ic, who ) ) || 133 ( bu = bee_user_new( ic->bee, ic, who, 0 ) ) ) || 134 !( bd = bu->data ) || bd->flags & list ) 135 return 1; 136 137 bd->flags |= list; 138 139 if( list == MSN_BUDDY_FL ) 140 msn_soap_ab_contact_add( ic, bu ); 141 else 142 msn_soap_memlist_edit( ic, who, TRUE, list ); 143 144 if( ( adl = adlrml_entry( who, list ) ) ) 145 { 146 g_snprintf( buf, sizeof( buf ), "ADL %d %zd\r\n%s", 147 ++md->trId, strlen( adl ), adl ); 148 g_free( adl ); 149 150 return msn_write( ic, buf, strlen( buf ) ); 151 } 152 153 return 1; 154 } 155 156 int msn_buddy_list_remove( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *group ) 103 104 realname = msn_http_encode( realname_ ); 105 g_snprintf( buf, sizeof( buf ), "ADD %d %s %s %s%s\r\n", ++md->trId, list, who, realname, groupid ); 106 g_free( realname ); 107 108 return msn_write( ic, buf, strlen( buf ) ); 109 } 110 111 int msn_buddy_list_remove( struct im_connection *ic, char *list, const char *who, const char *group ) 157 112 { 158 113 struct msn_data *md = ic->proto_data; 159 114 char buf[1024], groupid[8]; 160 bee_user_t *bu;161 struct msn_buddy_data *bd;162 char *adl;163 115 164 116 *groupid = '\0'; 165 #if 0166 117 if( group ) 167 118 { … … 174 125 } 175 126 } 176 #endif 177 178 if( !( bu = bee_user_by_handle( ic->bee, ic, who ) ) || 179 !( bd = bu->data ) || !( bd->flags & list ) ) 180 return 1; 181 182 bd->flags &= ~list; 183 184 if( list == MSN_BUDDY_FL ) 185 msn_soap_ab_contact_del( ic, bu ); 186 else 187 msn_soap_memlist_edit( ic, who, FALSE, list ); 188 189 if( ( adl = adlrml_entry( who, list ) ) ) 190 { 191 g_snprintf( buf, sizeof( buf ), "RML %d %zd\r\n%s", 192 ++md->trId, strlen( adl ), adl ); 193 g_free( adl ); 194 195 return msn_write( ic, buf, strlen( buf ) ); 196 } 197 198 return 1; 127 128 g_snprintf( buf, sizeof( buf ), "REM %d %s %s%s\r\n", ++md->trId, list, who, groupid ); 129 if( msn_write( ic, buf, strlen( buf ) ) ) 130 return( 1 ); 131 132 return( 0 ); 199 133 } 200 134 … … 210 144 struct msn_buddy_ask_data *bla = data; 211 145 212 msn_buddy_list_add( bla->ic, MSN_BUDDY_AL, bla->handle, bla->realname, NULL );146 msn_buddy_list_add( bla->ic, "AL", bla->handle, bla->realname, NULL ); 213 147 214 148 imcb_ask_add( bla->ic, bla->handle, NULL ); … … 223 157 struct msn_buddy_ask_data *bla = data; 224 158 225 msn_buddy_list_add( bla->ic, MSN_BUDDY_BL, bla->handle, bla->realname, NULL );159 msn_buddy_list_add( bla->ic, "BL", bla->handle, bla->realname, NULL ); 226 160 227 161 g_free( bla->handle ); … … 230 164 } 231 165 232 void msn_buddy_ask( bee_user_t *bu ) 233 { 234 struct msn_buddy_ask_data *bla; 235 struct msn_buddy_data *bd = bu->data; 166 void msn_buddy_ask( struct im_connection *ic, char *handle, char *realname ) 167 { 168 struct msn_buddy_ask_data *bla = g_new0( struct msn_buddy_ask_data, 1 ); 236 169 char buf[1024]; 237 170 238 if( ( bd->flags & 30 ) != 8 && ( bd->flags & 30 ) != 16 ) 239 return; 240 241 bla = g_new0( struct msn_buddy_ask_data, 1 ); 242 bla->ic = bu->ic; 243 bla->handle = g_strdup( bu->handle ); 244 bla->realname = g_strdup( bu->fullname ); 171 bla->ic = ic; 172 bla->handle = g_strdup( handle ); 173 bla->realname = g_strdup( realname ); 245 174 246 175 g_snprintf( buf, sizeof( buf ), 247 176 "The user %s (%s) wants to add you to his/her buddy list.", 248 bu->handle, bu->fullname );249 imcb_ask( bu->ic, buf, bla, msn_buddy_ask_yes, msn_buddy_ask_no );177 handle, realname ); 178 imcb_ask( ic, buf, bla, msn_buddy_ask_yes, msn_buddy_ask_no ); 250 179 } 251 180 … … 350 279 if( st <= 0 ) 351 280 return( -1 ); 352 353 if( getenv( "BITLBEE_DEBUG" ) )354 {355 write( 2, "->C:", 4 );356 write( 2, h->rxq + h->rxlen - st, st );357 }358 281 359 282 while( st ) … … 444 367 } 445 368 369 /* The difference between this function and the normal http_encode() function 370 is that this one escapes every 7-bit ASCII character because this is said 371 to avoid some lame server-side checks when setting a real-name. Also, 372 non-ASCII characters are not escaped because MSN servers don't seem to 373 appreciate that! */ 374 char *msn_http_encode( const char *input ) 375 { 376 char *ret, *s; 377 int i; 378 379 ret = s = g_new0( char, strlen( input ) * 3 + 1 ); 380 for( i = 0; input[i]; i ++ ) 381 if( input[i] & 128 ) 382 { 383 *s = input[i]; 384 s ++; 385 } 386 else 387 { 388 g_snprintf( s, 4, "%%%02X", input[i] ); 389 s += 3; 390 } 391 392 return ret; 393 } 394 446 395 void msn_msgq_purge( struct im_connection *ic, GSList **list ) 447 396 { … … 484 433 } 485 434 486 /* Copied and heavily modified from http://tmsnc.sourceforge.net/chl.c */ 487 char *msn_p11_challenge( char *challenge ) 488 { 489 char *output, buf[256]; 490 md5_state_t md5c; 491 unsigned char md5Hash[16], *newHash; 492 unsigned int *md5Parts, *chlStringParts, newHashParts[5]; 493 long long nHigh = 0, nLow = 0; 494 int i, n; 495 496 /* Create the MD5 hash */ 497 md5_init(&md5c); 498 md5_append(&md5c, (unsigned char*) challenge, strlen(challenge)); 499 md5_append(&md5c, (unsigned char*) MSNP11_PROD_KEY, strlen(MSNP11_PROD_KEY)); 500 md5_finish(&md5c, md5Hash); 501 502 /* Split it into four integers */ 503 md5Parts = (unsigned int *)md5Hash; 504 for (i = 0; i < 4; i ++) 505 { 506 md5Parts[i] = GUINT32_TO_LE(md5Parts[i]); 507 508 /* & each integer with 0x7FFFFFFF */ 509 /* and save one unmodified array for later */ 510 newHashParts[i] = md5Parts[i]; 511 md5Parts[i] &= 0x7FFFFFFF; 512 } 513 514 /* make a new string and pad with '0' */ 515 n = g_snprintf(buf, sizeof(buf)-5, "%s%s00000000", challenge, MSNP11_PROD_ID); 516 /* truncate at an 8-byte boundary */ 517 buf[n&=~7] = '\0'; 518 519 /* split into integers */ 520 chlStringParts = (unsigned int *)buf; 521 522 /* this is magic */ 523 for (i = 0; i < (n / 4) - 1; i += 2) 524 { 525 long long temp; 526 527 chlStringParts[i] = GUINT32_TO_LE(chlStringParts[i]); 528 chlStringParts[i+1] = GUINT32_TO_LE(chlStringParts[i+1]); 529 530 temp = (md5Parts[0] * (((0x0E79A9C1 * (long long)chlStringParts[i]) % 0x7FFFFFFF)+nHigh) + md5Parts[1])%0x7FFFFFFF; 531 nHigh = (md5Parts[2] * (((long long)chlStringParts[i+1]+temp) % 0x7FFFFFFF) + md5Parts[3]) % 0x7FFFFFFF; 532 nLow = nLow + nHigh + temp; 533 } 534 nHigh = (nHigh+md5Parts[1]) % 0x7FFFFFFF; 535 nLow = (nLow+md5Parts[3]) % 0x7FFFFFFF; 536 537 newHashParts[0] ^= nHigh; 538 newHashParts[1] ^= nLow; 539 newHashParts[2] ^= nHigh; 540 newHashParts[3] ^= nLow; 541 542 /* swap more bytes if big endian */ 543 for (i = 0; i < 4; i ++) 544 newHashParts[i] = GUINT32_TO_LE(newHashParts[i]); 545 546 /* make a string of the parts */ 547 newHash = (unsigned char *)newHashParts; 548 549 /* convert to hexadecimal */ 550 output = g_new(char, 33); 551 for (i = 0; i < 16; i ++) 552 sprintf(output + i * 2, "%02x", newHash[i]); 553 554 return output; 555 } 556 557 gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ ) 558 { 559 const char *a = a_, *b = b_; 560 gint ret; 561 562 if( !( a = strchr( a, '@' ) ) || !( b = strchr( b, '@' ) ) || 563 ( ret = strcmp( a, b ) ) == 0 ) 564 ret = strcmp( a_, b_ ); 565 566 return ret; 567 } 568 569 struct msn_group *msn_group_by_name( struct im_connection *ic, const char *name ) 570 { 435 gboolean msn_set_display_name( struct im_connection *ic, const char *rawname ) 436 { 437 char *fn = msn_http_encode( rawname ); 571 438 struct msn_data *md = ic->proto_data; 572 GSList *l; 573 574 for( l = md->groups; l; l = l->next ) 575 { 576 struct msn_group *mg = l->data; 577 578 if( g_strcasecmp( mg->name, name ) == 0 ) 579 return mg; 580 } 581 582 return NULL; 583 } 584 585 struct msn_group *msn_group_by_id( struct im_connection *ic, const char *id ) 586 { 587 struct msn_data *md = ic->proto_data; 588 GSList *l; 589 590 for( l = md->groups; l; l = l->next ) 591 { 592 struct msn_group *mg = l->data; 593 594 if( g_strcasecmp( mg->id, id ) == 0 ) 595 return mg; 596 } 597 598 return NULL; 599 } 600 601 int msn_ns_set_display_name( struct im_connection *ic, const char *value ) 602 { 603 struct msn_data *md = ic->proto_data; 604 char fn[strlen(value)*3+1]; 605 char buf[512]; 606 607 strcpy( fn, value ); 608 http_encode( fn ); 609 g_snprintf( buf, sizeof( buf ), "PRP %d MFN %s\r\n", 610 ++md->trId, fn ); 611 612 /* Note: We don't actually know if the server accepted the new name, 613 and won't give proper feedback yet if it doesn't. */ 614 return msn_write( ic, buf, strlen( buf ) ); 615 } 439 char buf[1024]; 440 441 g_snprintf( buf, sizeof( buf ), "REA %d %s %s\r\n", ++md->trId, ic->acc->user, fn ); 442 g_free( fn ); 443 444 return msn_write( ic, buf, strlen( buf ) ) != 0; 445 } -
protocols/msn/ns.c
rfeb1bad rb0a89cc 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * 4 * Copyright 2002-20 10Wilmer van der Gaast and others *4 * Copyright 2002-2004 Wilmer van der Gaast and others * 5 5 \********************************************************************/ 6 6 … … 27 27 #include "nogaim.h" 28 28 #include "msn.h" 29 #include "passport.h" 29 30 #include "md5.h" 30 #include "soap.h"31 #include "xmltree.h"32 31 33 32 static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond ); … … 35 34 static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ); 36 35 37 static void msn_ ns_send_adl_start( struct im_connection *ic);38 static void msn_ns_send_adl( struct im_connection *ic);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 ); 39 38 40 39 gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) … … 74 73 md->handler->rxq = g_new0( char, 1 ); 75 74 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 ); 77 76 if( msn_write( ic, s, strlen( s ) ) ) 78 77 { … … 114 113 if( strcmp( cmd[0], "VER" ) == 0 ) 115 114 { 116 if( cmd[2] && strncmp( cmd[2], MSNP_VER, 5 ) != 0 )115 if( cmd[2] && strncmp( cmd[2], "MSNP8", 5 ) != 0 ) 117 116 { 118 117 imcb_error( ic, "Unsupported protocol" ); … … 128 127 { 129 128 /* We don't give a damn about the information we just received */ 130 g_snprintf( buf, sizeof( buf ), "USR %d SSOI %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 ); 131 130 return( msn_write( ic, buf, strlen( buf ) ) ); 132 131 } … … 136 135 int port; 137 136 138 if( num_parts >= 6 && strcmp( cmd[2], "NS" ) == 0 )137 if( num_parts == 6 && strcmp( cmd[2], "NS" ) == 0 ) 139 138 { 140 139 b_event_remove( ic->inpa ); … … 157 156 md->fd = proxy_connect( server, port, msn_ns_connected, ic ); 158 157 } 159 else if( num_parts >= 6 && strcmp( cmd[2], "SB" ) == 0 )158 else if( num_parts == 6 && strcmp( cmd[2], "SB" ) == 0 ) 160 159 { 161 160 struct msn_switchboard *sb; … … 221 220 else if( strcmp( cmd[0], "USR" ) == 0 ) 222 221 { 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 230 239 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 ) ) ); 232 243 } 233 244 else … … 240 251 else if( strcmp( cmd[0], "MSG" ) == 0 ) 241 252 { 242 if( num_parts <4 )253 if( num_parts != 4 ) 243 254 { 244 255 imcb_error( ic, "Syntax error" ); … … 256 267 } 257 268 } 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] ); 278 372 } 279 373 else if( strcmp( cmd[0], "CHL" ) == 0 ) 280 374 { 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] ); 295 394 296 395 return( msn_write( ic, buf, strlen( buf ) ) ); … … 300 399 const struct msn_away_state *st; 301 400 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] ); 311 410 312 411 st = msn_away_state_by_code( cmd[2] ); … … 333 432 { 334 433 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] ); 347 444 348 445 st = msn_away_state_by_code( cmd[1] ); … … 354 451 355 452 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 ), 358 454 st->name, NULL ); 359 455 … … 366 462 int session, port; 367 463 368 if( num_parts <7 )464 if( num_parts != 7 ) 369 465 { 370 466 imcb_error( ic, "Syntax error" ); … … 408 504 } 409 505 } 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 } 410 546 else if( strcmp( cmd[0], "OUT" ) == 0 ) 411 547 { … … 429 565 return( 0 ); 430 566 } 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 431 601 else if( strcmp( cmd[0], "IPG" ) == 0 ) 432 602 { … … 442 612 } 443 613 } 444 #if 0445 614 else if( strcmp( cmd[0], "ADG" ) == 0 ) 446 615 { … … 486 655 } 487 656 } 488 }489 #endif490 else if( strcmp( cmd[0], "GCF" ) == 0 )491 {492 /* Coming up is cmd[2] bytes of stuff we're supposed to493 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 but505 apparently used to announce address book changes. */506 if( num_parts >= 2 )507 md->handler->msglen = atoi( cmd[1] );508 657 } 509 658 else if( isdigit( cmd[0][0] ) ) … … 616 765 } 617 766 } 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 }681 767 682 768 return( 1 ); 683 769 } 684 770 685 void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error)771 static void msn_auth_got_passport_token( struct msn_auth_data *mad ) 686 772 { 773 struct im_connection *ic = mad->data; 687 774 struct msn_data *md; 688 775 … … 692 779 693 780 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 ); 700 786 msn_write( ic, buf, strlen( buf ) ); 701 787 } 702 788 else 703 789 { 704 imcb_error( ic, "Error during Passport authentication: %s", error );790 imcb_error( ic, "Error during Passport authentication: %s", mad->error ); 705 791 imc_logout( ic, TRUE ); 706 792 } 707 793 } 708 794 709 void msn_auth_got_contact_list( struct im_connection *ic)795 static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name ) 710 796 { 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 } 723 838 } 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 else828 return 1;829 } -
protocols/msn/sb.c
rfeb1bad rb0a89cc 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * 4 * Copyright 2002-20 10Wilmer van der Gaast and others *4 * Copyright 2002-2005 Wilmer van der Gaast and others * 5 5 \********************************************************************/ 6 6 … … 27 27 #include "nogaim.h" 28 28 #include "msn.h" 29 #include "passport.h" 29 30 #include "md5.h" 30 #include "soap.h"31 31 #include "invitation.h" 32 32 … … 38 38 { 39 39 int st; 40 41 if( getenv( "BITLBEE_DEBUG" ) )42 {43 write( 2, "->SB:", 5 );44 write( 2, s, len );45 }46 40 47 41 st = write( sb->fd, s, len ); … … 413 407 else if( strcmp( cmd[0], "USR" ) == 0 ) 414 408 { 415 if( num_parts <5 )409 if( num_parts != 5 ) 416 410 { 417 411 msn_sb_destroy( sb ); … … 439 433 int num, tot; 440 434 441 if( num_parts <6 )435 if( num_parts != 6 ) 442 436 { 443 437 msn_sb_destroy( sb ); … … 476 470 else if( strcmp( cmd[0], "ANS" ) == 0 ) 477 471 { 478 if( num_parts <3 )472 if( num_parts != 3 ) 479 473 { 480 474 msn_sb_destroy( sb ); … … 495 489 else if( strcmp( cmd[0], "CAL" ) == 0 ) 496 490 { 497 if( num_parts <4 || !isdigit( cmd[3][0] ) )491 if( num_parts != 4 || !isdigit( cmd[3][0] ) ) 498 492 { 499 493 msn_sb_destroy( sb ); … … 505 499 else if( strcmp( cmd[0], "JOI" ) == 0 ) 506 500 { 507 if( num_parts <3 )501 if( num_parts != 3 ) 508 502 { 509 503 msn_sb_destroy( sb ); … … 566 560 else if( strcmp( cmd[0], "MSG" ) == 0 ) 567 561 { 568 if( num_parts <4 )562 if( num_parts != 4 ) 569 563 { 570 564 msn_sb_destroy( sb ); … … 631 625 const struct msn_status_code *err = msn_status_by_number( num ); 632 626 633 /* If the person is offline, send an offline message instead, 634 and don't report an error. */ 635 if( num == 217 ) 636 msn_soap_oim_send_queue( ic, &sb->msgq ); 637 else 638 imcb_error( ic, "Error reported by switchboard server: %s", err->text ); 627 imcb_error( ic, "Error reported by switchboard server: %s", err->text ); 639 628 640 629 if( err->flags & STATUS_SB_FATAL ) … … 752 741 else if( g_strncasecmp( ct, "application/x-msnmsgrp2p", 24 ) == 0 ) 753 742 { 754 /* Not currently implemented. Don't warn about it since755 this seems to be used for avatars now. */743 imcb_error( sb->ic, "Cannot receive file from %s: BitlBee does not " 744 "support msnmsgrp2p yet.", sb->who ); 756 745 g_free( ct ); 757 746 } -
protocols/msn/tables.c
rfeb1bad rb0a89cc 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * 4 * Copyright 2002-20 10Wilmer van der Gaast and others *4 * Copyright 2002-2004 Wilmer van der Gaast and others * 5 5 \********************************************************************/ 6 6 … … 83 83 { 230, "Cannot remove that group", 0 }, 84 84 { 231, "Invalid group", 0 }, 85 { 240, "ADL/RML command with corrupted payload", STATUS_FATAL },86 { 241, "ADL/RML command with invalid modification", 0 },87 85 { 280, "Switchboard failed", STATUS_SB_FATAL }, 88 86 { 281, "Transfer to switchboard failed", 0 }, -
protocols/nogaim.c
rfeb1bad rb0a89cc 326 326 imcb_log( ic, "Signing off.." ); 327 327 328 b_event_remove( ic->keepalive ); 329 ic->keepalive = 0; 330 ic->acc->prpl->logout( ic ); 331 b_event_remove( ic->inpa ); 332 333 g_free( ic->away ); 334 ic->away = NULL; 335 328 336 for( l = bee->users; l; ) 329 337 { … … 336 344 l = next; 337 345 } 338 339 b_event_remove( ic->keepalive );340 ic->keepalive = 0;341 ic->acc->prpl->logout( ic );342 b_event_remove( ic->inpa );343 344 g_free( ic->away );345 ic->away = NULL;346 346 347 347 query_del_by_conn( (irc_t*) ic->bee->ui_data, ic ); -
protocols/nogaim.h
rfeb1bad rb0a89cc 195 195 this info via imcb_log(). Implementing these are optional. */ 196 196 void (* get_info) (struct im_connection *, char *who); 197 /* set_my_name is *DEPRECATED*, not used by the UI anymore. Use the198 display_name setting instead. */199 197 void (* set_my_name) (struct im_connection *, char *name); 200 198 void (* set_name) (struct im_connection *, char *who, char *name); -
storage_xml.c
rfeb1bad rb0a89cc 320 320 else if( g_strcasecmp( g_markup_parse_context_get_element( ctx ), "setting" ) == 0 && xd->current_setting ) 321 321 { 322 if( xd->current_account )323 {324 set_t *s = set_find( xd->current_set_head, xd->current_setting );325 if( s && ( s->flags & ACC_SET_ONLINE_ONLY ) )326 {327 g_free( xd->current_setting );328 xd->current_setting = NULL;329 return;330 }331 }332 322 set_setstr( xd->current_set_head, xd->current_setting, (char*) text ); 333 323 g_free( xd->current_setting );
Note: See TracChangeset
for help on using the changeset viewer.