Changes in / [136c2bb:07874be]


Ignore:
Files:
2 added
2 deleted
20 edited

Legend:

Unmodified
Added
Removed
  • lib/misc.c

    r136c2bb r07874be  
    298298void http_encode( char *s )
    299299{
    300         char *t;
     300        char t[strlen(s)+1];
    301301        int i, j;
    302302       
    303         t = g_strdup( s );
    304        
     303        strcpy( t, s );
    305304        for( i = j = 0; t[i]; i ++, j ++ )
    306305        {
     
    320319        }
    321320        s[j] = 0;
    322        
    323         g_free( t );
    324321}
    325322
  • lib/sha1.c

    r136c2bb r07874be  
    3636 */
    3737
     38#include <string.h>
    3839#include "sha1.h"
    3940
     
    374375        sha1_process_block(context);
    375376}
     377
     378#define HMAC_BLOCK_SIZE 64
     379
     380/* BitlBee addition: */
     381void 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        else
     403        {
     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

    r136c2bb r07874be  
    6767G_MODULE_EXPORT int sha1_append(sha1_state_t *, const uint8_t *, unsigned int);
    6868G_MODULE_EXPORT int sha1_finish(sha1_state_t *, uint8_t Message_Digest[sha1_hash_size]);
     69G_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]);
    6970
    7071#endif
  • lib/ssl_client.h

    r136c2bb r07874be  
    7878   the same action as the handler that just received the SSL_AGAIN.) */
    7979G_MODULE_EXPORT b_input_condition ssl_getdirection( void *conn );
     80
     81G_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

    r136c2bb r07874be  
    189189                ssl_errno = SSL_AGAIN;
    190190       
     191        if( getenv( "BITLBEE_DEBUG" ) && st > 0 ) write( 1, buf, st );
     192       
    191193        return st;
    192194}
     
    207209        if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED )
    208210                ssl_errno = SSL_AGAIN;
     211       
     212        if( getenv( "BITLBEE_DEBUG" ) && st > 0 ) write( 1, buf, st );
    209213       
    210214        return st;
  • lib/ssl_openssl.c

    r136c2bb r07874be  
    116116        {
    117117                initialized = TRUE;
    118                 SSLeay_add_ssl_algorithms();
     118                SSL_library_init();
     119                //SSLeay_add_ssl_algorithms();
     120                //OpenSSL_add_all_algorithms();
    119121        }
    120122       
     
    205207        }
    206208       
     209        if( getenv( "BITLBEE_DEBUG" ) && st > 0 ) write( 1, buf, st );
     210       
    207211        return st;
    208212}
     
    219223       
    220224        st = SSL_write( ((struct scd*)conn)->ssl, buf, len );
     225       
     226        if( getenv( "BITLBEE_DEBUG" ) && st > 0 ) write( 1, buf, st );
    221227       
    222228        ssl_errno = SSL_OK;
     
    272278        return( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ? B_EV_IO_WRITE : B_EV_IO_READ );
    273279}
     280
     281size_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

    r136c2bb r07874be  
    141141/* Feed the parser, don't execute any handler. Returns -1 on errors, 0 on
    142142   end-of-stream and 1 otherwise. */
    143 int xt_feed( struct xt_parser *xt, char *text, int text_len )
     143int xt_feed( struct xt_parser *xt, const char *text, int text_len )
    144144{
    145145        if( !g_markup_parse_context_parse( xt->parser, text, text_len, &xt->gerr ) )
     
    174174        if( node->flags & XT_COMPLETE && !( node->flags & XT_SEEN ) )
    175175        {
    176                 for( i = 0; xt->handlers[i].func; i ++ )
     176                if( xt->handlers ) for( i = 0; xt->handlers[i].func; i ++ )
    177177                {
    178178                        /* This one is fun! \o/ */
    179179                       
    180                                                 /* If handler.name == NULL it means it should always match. */
     180                            /* If handler.name == NULL it means it should always match. */
    181181                        if( ( xt->handlers[i].name == NULL ||
    182                                                 /* If it's not, compare. There should always be a name. */
     182                              /* If it's not, compare. There should always be a name. */
    183183                              g_strcasecmp( xt->handlers[i].name, node->name ) == 0 ) &&
    184                                                 /* If handler.parent == NULL, it's a match. */
     184                            /* If handler.parent == NULL, it's a match. */
    185185                            ( xt->handlers[i].parent == NULL ||
    186                                                 /* If there's a parent node, see if the name matches. */
     186                              /* If there's a parent node, see if the name matches. */
    187187                              ( node->parent ? g_strcasecmp( xt->handlers[i].parent, node->parent->name ) == 0 :
    188                                                 /* If there's no parent, the handler should mention <root> as a parent. */
    189                                                g_strcasecmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) )
     188                              /* If there's no parent, the handler should mention <root> as a parent. */
     189                                               strcmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) )
    190190                        {
    191191                                st = xt->handlers[i].func( node, xt->data );
     
    260260}
    261261
     262struct 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
    262276static void xt_to_string_real( struct xt_node *node, GString *str )
    263277{
     
    550564}
    551565
     566/* Same, but at the beginning. */
     567void xt_insert_child( struct xt_node *parent, struct xt_node *child )
     568{
     569        struct xt_node *node, *last;
     570       
     571        for( node = child; node; node = node->next )
     572        {
     573                if( node->parent != NULL )
     574                {
     575                        /* ERROR CONDITION: They seem to have a parent already??? */
     576                }
     577               
     578                node->parent = parent;
     579                last = node;
     580        }
     581       
     582        last->next = parent->children;
     583        parent->children = child;
     584}
     585
    552586void xt_add_attr( struct xt_node *node, const char *key, const char *value )
    553587{
  • lib/xmltree.h

    r136c2bb r07874be  
    7979struct xt_parser *xt_new( const struct xt_handler_entry *handlers, gpointer data );
    8080void xt_reset( struct xt_parser *xt );
    81 int xt_feed( struct xt_parser *xt, char *text, int text_len );
     81int xt_feed( struct xt_parser *xt, const char *text, int text_len );
    8282int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth );
    8383void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth );
     84struct xt_node *xt_from_string( const char *in );
    8485char *xt_to_string( struct xt_node *node );
    8586void xt_print( struct xt_node *node );
     
    9293struct xt_node *xt_new_node( char *name, const char *text, struct xt_node *children );
    9394void xt_add_child( struct xt_node *parent, struct xt_node *child );
     95void xt_insert_child( struct xt_node *parent, struct xt_node *child );
    9496void xt_add_attr( struct xt_node *node, const char *key, const char *value );
    9597int xt_remove_attr( struct xt_node *node, const char *key );
  • protocols/bee.h

    r136c2bb r07874be  
    148148 * - 'state' and 'message' can be NULL */
    149149G_MODULE_EXPORT void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message );
     150G_MODULE_EXPORT void imcb_buddy_status_msg( struct im_connection *ic, const char *handle, const char *message );
    150151G_MODULE_EXPORT void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle );
    151152/* Call when a handle says something. 'flags' and 'sent_at may be just 0. */
  • protocols/bee_user.c

    r136c2bb r07874be  
    187187        /* TODO(wilmer): OPT_AWAY, or just state == NULL ? */
    188188        bu->flags = flags;
    189         bu->status = g_strdup( ( flags & OPT_AWAY ) && state == NULL ? "Away" : state );
    190189        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        else
     195                bu->status = NULL;
    191196       
    192197        if( bee->ui->user_status )
     
    198203}
    199204
     205/* Same, but only change the away/status message, not any away/online state info. */
     206void imcb_buddy_status_msg( struct im_connection *ic, const char *handle, const char *message )
     207{
     208        bee_t *bee = ic->bee;
     209        bee_user_t *bu, *old;
     210       
     211        if( !( bu = bee_user_by_handle( bee, ic, handle ) ) )
     212        {
     213                return;
     214        }
     215       
     216        old = g_memdup( bu, sizeof( bee_user_t ) );
     217       
     218        bu->status_msg = g_strdup( message );
     219       
     220        if( bee->ui->user_status )
     221                bee->ui->user_status( bee, bu, old );
     222       
     223        g_free( old->status_msg );
     224        g_free( old );
     225}
     226
    200227void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle )
    201228{
  • protocols/msn/Makefile

    r136c2bb r07874be  
    1313
    1414# [SH] Program variables
    15 objects = msn.o msn_util.o ns.o passport.o sb.o tables.o
     15objects = msn.o msn_util.o ns.o sb.o soap.o tables.o
    1616
    1717LFLAGS += -r
     
    4343        @$(LD) $(LFLAGS) $(objects) -o msn_mod.o
    4444       
    45 
     45soap.o: soap.h soap.c
  • protocols/msn/msn.c

    r136c2bb r07874be  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2004 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2010 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    2525
    2626#include "nogaim.h"
     27#include "soap.h"
    2728#include "msn.h"
    2829
     
    3536static void msn_init( account_t *acc )
    3637{
    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 );
     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       
    3943        set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc );
    4044        set_add( &acc->set, "switchboard_keepalives", "false", set_eval_bool, acc );
     45       
     46        acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE;
    4147}
    4248
     
    6874        md->ic = ic;
    6975        md->away_state = msn_away_state_list;
     76        md->domaintree = g_tree_new( msn_domaintree_cmp );
    7077       
    7178        msn_connections = g_slist_append( msn_connections, ic );
     
    103110                        g_free( md->grouplist[--md->groupcount] );
    104111                g_free( md->grouplist );
     112                g_free( md->tokens[0] );
     113                g_free( md->tokens[1] );
     114                g_free( md->tokens[2] );
     115                g_free( md->lock_key );
     116               
     117                g_tree_destroy( md->domaintree );
     118                md->domaintree = NULL;
    105119               
    106120                while( md->grpq )
     
    174188{
    175189        char buf[1024];
     190        char *uux;
    176191        struct msn_data *md = ic->proto_data;
    177192       
     
    182197       
    183198        g_snprintf( buf, sizeof( buf ), "CHG %d %s\r\n", ++md->trId, md->away_state->code );
    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 );
     199        if( !msn_write( ic, buf, strlen( buf ) ) )
     200                return;
     201       
     202        uux = g_markup_printf_escaped( "<Data><PSM>%s</PSM><CurrentMedia></CurrentMedia>"
     203                                       "</Data>", message ? message : "" );
     204        g_snprintf( buf, sizeof( buf ), "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux );
     205        if( !msn_write( ic, buf, strlen( buf ) ) )
     206                return;
    190207}
    191208
     
    314331        account_t *acc = set->data;
    315332        struct im_connection *ic = acc->ic;
    316        
    317         /* Allow any name if we're offline. */
    318         if( ic == NULL )
    319                 return value;
     333        struct msn_data *md = ic->proto_data;
     334        char buf[512];
     335        char *fn;
    320336       
    321337        if( strlen( value ) > 129 )
     
    325341        }
    326342       
    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;
     343        msn_soap_addressbook_set_display_name( ic, value );
     344
     345        fn = g_malloc( strlen( value ) * 3 + 1 );
     346        strcpy( fn, value );
     347        http_encode( fn );
     348        g_snprintf( buf, sizeof( buf ), "PRP %d MFN %s\r\n",
     349                    ++md->trId, fn );
     350        g_free( fn );
     351       
     352        /* Note: We don't actually know if the server accepted the new name,
     353           and won't give proper feedback yet if it doesn't. */
     354        return msn_write( ic, buf, strlen( buf ) ) ? value : NULL;
     355}
     356
     357static void msn_buddy_data_add( bee_user_t *bu )
     358{
     359        struct msn_data *md = bu->ic->proto_data;
     360        bu->data = g_new0( struct msn_buddy_data, 1 );
     361        g_tree_insert( md->domaintree, bu->handle, bu );
     362}
     363
     364static void msn_buddy_data_free( bee_user_t *bu )
     365{
     366        struct msn_data *md = bu->ic->proto_data;
     367        g_tree_remove( md->domaintree, bu->handle );
     368        g_free( bu->data );
    331369}
    332370
     
    343381        ret->set_away = msn_set_away;
    344382        ret->get_info = msn_get_info;
    345         ret->set_my_name = msn_set_my_name;
    346383        ret->add_buddy = msn_add_buddy;
    347384        ret->remove_buddy = msn_remove_buddy;
     
    357394        ret->send_typing = msn_send_typing;
    358395        ret->handle_cmp = g_strcasecmp;
     396        ret->buddy_data_add = msn_buddy_data_add;
     397        ret->buddy_data_free = msn_buddy_data_free;
     398       
    359399        //ret->transfer_request = msn_ftp_transfer_request;
    360400
  • protocols/msn/msn.h

    r136c2bb r07874be  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2004 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2010 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    3939#endif
    4040
    41 #define QRY_NAME "msmsgs@msnmsgr.com"
    42 #define QRY_CODE "Q1P7W2E4J9R8U3S5"
     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//PK}_A_0N_K%O?A9S"
     53#define MSNP11_PROD_ID  "PROD0119GSJUC$18"
     54//PROD0114ES4Z%Q5W"
     55#define MSNP_VER        "MSNP15"
     56#define MSNP_BUILD      "8.5.1288"
     57//"8.1.0178"
    4358
    4459#define MSN_SB_NEW         -24062002
     
    6984       
    7085        int trId;
     86        char *tokens[3];
     87        char *lock_key;
    7188       
    7289        GSList *msgq, *grpq;
     
    8097        int groupcount;
    8198        char **grouplist;
     99        GTree *domaintree;
    82100};
    83101
     
    140158        int (*exec_command) ( gpointer data, char **cmd, int count );
    141159        int (*exec_message) ( gpointer data, char *msg, int msglen, char **cmd, int count );
     160};
     161
     162typedef enum
     163{
     164        MSN_BUDDY_FL = 1,   /* Warning: FL,AL,BL *must* be 1,2,4. */
     165        MSN_BUDDY_AL = 2,
     166        MSN_BUDDY_BL = 4,
     167        MSN_BUDDY_RL = 8,
     168        MSN_BUDDY_PL = 16,
     169} msn_buddy_flags_t;
     170
     171struct msn_buddy_data
     172{
     173        char *cid;
     174        msn_buddy_flags_t flags;
    142175};
    143176
     
    162195/* ns.c */
    163196gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond );
     197void msn_auth_got_passport_token( struct im_connection *ic, char *token );
     198void msn_auth_got_contact_list( struct im_connection *ic );
    164199
    165200/* msn_util.c */
     
    172207char **msn_linesplit( char *line );
    173208int msn_handler( struct msn_handler_data *h );
    174 char *msn_http_encode( const char *input );
    175209void msn_msgq_purge( struct im_connection *ic, GSList **list );
    176210gboolean msn_set_display_name( struct im_connection *ic, const char *rawname );
     211char *msn_p11_challenge( char *challenge );
     212gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ );
    177213
    178214/* tables.c */
     
    196232void msn_sb_stop_keepalives( struct msn_switchboard *sb );
    197233
    198 /* invitation.c */
    199 void msn_ftp_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who );
    200 
    201234#endif //_MSN_H
  • protocols/msn/msn_util.c

    r136c2bb r07874be  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2004 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2010 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    2626#include "nogaim.h"
    2727#include "msn.h"
     28#include "md5.h"
    2829#include <ctype.h>
    2930
     
    3233        struct msn_data *md = ic->proto_data;
    3334        int st;
     35       
     36        if( getenv( "BITLBEE_DEBUG" ) )
     37        {
     38                write( 2, "->NS:", 5 );
     39                write( 2, s, len );
     40        }
    3441       
    3542        st = write( md->fd, s, len );
     
    5461{
    5562        struct msn_data *md = ic->proto_data;
    56         char buf[1024], *realname, groupid[8];
     63        char buf[1024], realname[strlen(realname_)*3+1], groupid[8];
    5764       
    5865        *groupid = '\0';
     
    8794                        if( l == NULL )
    8895                        {
    89                                 char *groupname = msn_http_encode( group );
     96                                char groupname[strlen(group)+1];
     97                                strcpy( groupname, group );
     98                                http_encode( groupname );
    9099                                g_snprintf( buf, sizeof( buf ), "ADG %d %s %d\r\n", ++md->trId, groupname, 0 );
    91                                 g_free( groupname );
    92100                                return msn_write( ic, buf, strlen( buf ) );
    93101                        }
     
    102110        }
    103111       
    104         realname = msn_http_encode( realname_ );
     112        strcpy( realname, realname_ );
     113        http_encode( realname );
    105114        g_snprintf( buf, sizeof( buf ), "ADD %d %s %s %s%s\r\n", ++md->trId, list, who, realname, groupid );
    106         g_free( realname );
    107115       
    108116        return msn_write( ic, buf, strlen( buf ) );
     
    279287        if( st <= 0 )
    280288                return( -1 );
     289       
     290        if( getenv( "BITLBEE_DEBUG" ) )
     291        {
     292                write( 2, "->C:", 4 );
     293                write( 2, h->rxq + h->rxlen - st, st );
     294        }
    281295       
    282296        while( st )
     
    367381}
    368382
    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 
    395383void msn_msgq_purge( struct im_connection *ic, GSList **list )
    396384{
     
    433421}
    434422
    435 gboolean msn_set_display_name( struct im_connection *ic, const char *rawname )
    436 {
    437         char *fn = msn_http_encode( rawname );
    438         struct msn_data *md = ic->proto_data;
    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 }
     423/* Copied and heavily modified from http://tmsnc.sourceforge.net/chl.c */
     424char *msn_p11_challenge( char *challenge )
     425{
     426        char *output, buf[256];
     427        md5_state_t md5c;
     428        unsigned char md5Hash[16], *newHash;
     429        unsigned int *md5Parts, *chlStringParts, newHashParts[5];
     430        long long nHigh = 0, nLow = 0;
     431        int i, n;
     432
     433        /* Create the MD5 hash */
     434        md5_init(&md5c);
     435        md5_append(&md5c, (unsigned char*) challenge, strlen(challenge));
     436        md5_append(&md5c, (unsigned char*) MSNP11_PROD_KEY, strlen(MSNP11_PROD_KEY));
     437        md5_finish(&md5c, md5Hash);
     438
     439        /* Split it into four integers */
     440        md5Parts = (unsigned int *)md5Hash;
     441        for (i = 0; i < 4; i ++)
     442        { 
     443                md5Parts[i] = GUINT32_TO_LE(md5Parts[i]);
     444               
     445                /* & each integer with 0x7FFFFFFF */
     446                /* and save one unmodified array for later */
     447                newHashParts[i] = md5Parts[i];
     448                md5Parts[i] &= 0x7FFFFFFF;
     449        }
     450       
     451        /* make a new string and pad with '0' */
     452        n = g_snprintf(buf, sizeof(buf)-5, "%s%s00000000", challenge, MSNP11_PROD_ID);
     453        /* truncate at an 8-byte boundary */
     454        buf[n&=~7] = '\0';
     455       
     456        /* split into integers */
     457        chlStringParts = (unsigned int *)buf;
     458       
     459        /* this is magic */
     460        for (i = 0; i < (n / 4) - 1; i += 2)
     461        {
     462                long long temp;
     463
     464                chlStringParts[i]   = GUINT32_TO_LE(chlStringParts[i]);
     465                chlStringParts[i+1] = GUINT32_TO_LE(chlStringParts[i+1]);
     466
     467                temp  = (md5Parts[0] * (((0x0E79A9C1 * (long long)chlStringParts[i]) % 0x7FFFFFFF)+nHigh) + md5Parts[1])%0x7FFFFFFF;
     468                nHigh = (md5Parts[2] * (((long long)chlStringParts[i+1]+temp) % 0x7FFFFFFF) + md5Parts[3]) % 0x7FFFFFFF;
     469                nLow  = nLow + nHigh + temp;
     470        }
     471        nHigh = (nHigh+md5Parts[1]) % 0x7FFFFFFF;
     472        nLow = (nLow+md5Parts[3]) % 0x7FFFFFFF;
     473       
     474        newHashParts[0] ^= nHigh;
     475        newHashParts[1] ^= nLow;
     476        newHashParts[2] ^= nHigh;
     477        newHashParts[3] ^= nLow;
     478       
     479        /* swap more bytes if big endian */
     480        for (i = 0; i < 4; i ++)
     481                newHashParts[i] = GUINT32_TO_LE(newHashParts[i]);
     482       
     483        /* make a string of the parts */
     484        newHash = (unsigned char *)newHashParts;
     485       
     486        /* convert to hexadecimal */
     487        output = g_new(char, 33);
     488        for (i = 0; i < 16; i ++)
     489                sprintf(output + i * 2, "%02x", newHash[i]);
     490       
     491        return output;
     492}
     493
     494gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ )
     495{
     496        const char *a = a_, *b = b_;
     497        gint ret;
     498       
     499        if( !( a = strchr( a, '@' ) ) || !( b = strchr( b, '@' ) ) ||
     500            ( ret = strcmp( a, b ) ) == 0 )
     501                ret = strcmp( a_, b_ );
     502       
     503        return ret;
     504}
  • protocols/msn/ns.c

    r136c2bb r07874be  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2004 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2010 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    2727#include "nogaim.h"
    2828#include "msn.h"
    29 #include "passport.h"
    3029#include "md5.h"
     30#include "soap.h"
     31#include "xmltree.h"
    3132
    3233static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond );
     
    3435static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts );
    3536
    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 );
     37static void msn_ns_send_adl( struct im_connection *ic );
    3838
    3939gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond )
     
    7373        md->handler->rxq = g_new0( char, 1 );
    7474       
    75         g_snprintf( s, sizeof( s ), "VER %d MSNP8 CVR0\r\n", ++md->trId );
     75        g_snprintf( s, sizeof( s ), "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER );
    7676        if( msn_write( ic, s, strlen( s ) ) )
    7777        {
     
    113113        if( strcmp( cmd[0], "VER" ) == 0 )
    114114        {
    115                 if( cmd[2] && strncmp( cmd[2], "MSNP8", 5 ) != 0 )
     115                if( cmd[2] && strncmp( cmd[2], MSNP_VER, 5 ) != 0 )
    116116                {
    117117                        imcb_error( ic, "Unsupported protocol" );
     
    127127        {
    128128                /* 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 );
     129                g_snprintf( buf, sizeof( buf ), "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user );
    130130                return( msn_write( ic, buf, strlen( buf ) ) );
    131131        }
     
    135135                int port;
    136136               
    137                 if( num_parts == 6 && strcmp( cmd[2], "NS" ) == 0 )
     137                if( num_parts >= 6 && strcmp( cmd[2], "NS" ) == 0 )
    138138                {
    139139                        b_event_remove( ic->inpa );
     
    156156                        md->fd = proxy_connect( server, port, msn_ns_connected, ic );
    157157                }
    158                 else if( num_parts == 6 && strcmp( cmd[2], "SB" ) == 0 )
     158                else if( num_parts >= 6 && strcmp( cmd[2], "SB" ) == 0 )
    159159                {
    160160                        struct msn_switchboard *sb;
     
    220220        else if( strcmp( cmd[0], "USR" ) == 0 )
    221221        {
    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                        
     222                if( num_parts >= 6 && strcmp( cmd[2], "SSO" ) == 0 &&
     223                    strcmp( cmd[3], "S" ) == 0 )
     224                {
     225                        msn_soap_passport_sso_request( ic, cmd[4], cmd[5] );
     226                }
     227                else if( strcmp( cmd[2], "OK" ) == 0 )
     228                {
    239229                        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 ) ) );
     230                        msn_soap_memlist_request( ic );
    243231                }
    244232                else
     
    251239        else if( strcmp( cmd[0], "MSG" ) == 0 )
    252240        {
    253                 if( num_parts != 4 )
     241                if( num_parts < 4 )
    254242                {
    255243                        imcb_error( ic, "Syntax error" );
     
    267255                }
    268256        }
    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] );
     257        else if( strcmp( cmd[0], "BLP" ) == 0 )
     258        {
     259                msn_ns_send_adl( ic );
     260        }
     261        else if( strcmp( cmd[0], "ADL" ) == 0 )
     262        {
     263                if( num_parts >= 3 && strcmp( cmd[2], "OK" ) == 0 )
     264                {
     265                        char buf[1024];
     266                        char *fn_raw = set_getstr( &ic->acc->set, "display_name" );
     267                        char *fn;
     268                       
     269                        if( fn_raw == NULL )
     270                                fn_raw = ic->acc->user;
     271                        fn = g_malloc( strlen( fn_raw ) * 3 + 1 );
     272                        strcpy( fn, fn_raw );
     273                        http_encode( fn );
     274                       
     275                        g_snprintf( buf, sizeof( buf ), "PRP %d MFN %s\r\n",
     276                                    ++md->trId, fn );
     277                        g_free( fn );
     278                       
     279                        msn_write( ic, buf, strlen( buf ) );
     280                }
     281        }
     282        else if( strcmp( cmd[0], "PRP" ) == 0 )
     283        {
     284                imcb_connected( ic );
    372285        }
    373286        else if( strcmp( cmd[0], "CHL" ) == 0 )
    374287        {
    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] );
     288                char *resp;
     289               
     290                if( num_parts < 3 )
     291                {
     292                        imcb_error( ic, "Syntax error" );
     293                        imc_logout( ic, TRUE );
     294                        return( 0 );
     295                }
     296               
     297                resp = msn_p11_challenge( cmd[2] );
     298                g_snprintf( buf, sizeof( buf ), "QRY %d %s %zd\r\n%s",
     299                            ++md->trId, MSNP11_PROD_ID,
     300                            strlen( resp ), resp );
     301                g_free( resp );
    394302               
    395303                return( msn_write( ic, buf, strlen( buf ) ) );
     
    399307                const struct msn_away_state *st;
    400308               
    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] );
     309                if( num_parts < 6 )
     310                {
     311                        imcb_error( ic, "Syntax error" );
     312                        imc_logout( ic, TRUE );
     313                        return( 0 );
     314                }
     315               
     316                http_decode( cmd[5] );
     317                imcb_rename_buddy( ic, cmd[3], cmd[5] );
    410318               
    411319                st = msn_away_state_by_code( cmd[2] );
     
    433341                const struct msn_away_state *st;
    434342               
    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] );
     343                if( num_parts < 5 )
     344                {
     345                        imcb_error( ic, "Syntax error" );
     346                        imc_logout( ic, TRUE );
     347                        return( 0 );
     348                }
     349               
     350                http_decode( cmd[4] );
     351                imcb_rename_buddy( ic, cmd[2], cmd[4] );
    444352               
    445353                st = msn_away_state_by_code( cmd[1] );
     
    462370                int session, port;
    463371               
    464                 if( num_parts != 7 )
     372                if( num_parts < 7 )
    465373                {
    466374                        imcb_error( ic, "Syntax error" );
     
    506414        else if( strcmp( cmd[0], "ADD" ) == 0 )
    507415        {
    508                 if( num_parts == 6 && strcmp( cmd[2], "RL" ) == 0 )
     416                if( num_parts >= 6 && strcmp( cmd[2], "RL" ) == 0 )
    509417                {
    510418                        GSList *l;
     
    565473                return( 0 );
    566474        }
    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
    601475        else if( strcmp( cmd[0], "IPG" ) == 0 )
    602476        {
     
    655529                        }
    656530                }
     531        }
     532        else if( strcmp( cmd[0], "GCF" ) == 0 )
     533        {
     534                /* Coming up is cmd[2] bytes of stuff we're supposed to
     535                   censore. Meh. */
     536                md->handler->msglen = atoi( cmd[2] );
     537        }
     538        else if( strcmp( cmd[0], "UBX" ) == 0 )
     539        {
     540                /* Status message. Parser coming soon. */
     541                if( num_parts >= 4 )
     542                        md->handler->msglen = atoi( cmd[3] );
     543        }
     544        else if( strcmp( cmd[0], "NOT" ) == 0 )
     545        {
     546                /* Some kind of notification, not sure if it still exists
     547                   but we have to skip the payload or stuff breaks. */
     548                if( num_parts >= 3 )
     549                        md->handler->msglen = atoi( cmd[2] );
    657550        }
    658551        else if( isdigit( cmd[0][0] ) )
     
    765658                }
    766659        }
     660        else if( strcmp( cmd[0], "UBX" ) == 0 )
     661        {
     662                struct xt_node *psm;
     663                char *psm_text = NULL;
     664               
     665                psm = xt_from_string( msg );
     666                if( psm && strcmp( psm->name, "Data" ) == 0 &&
     667                    ( psm = xt_find_node( psm->children, "PSM" ) ) )
     668                        psm_text = psm->text;
     669               
     670                imcb_buddy_status_msg( ic, cmd[1], psm_text );
     671                xt_free_node( psm );
     672        }
    767673       
    768674        return( 1 );
    769675}
    770676
    771 static void msn_auth_got_passport_token( struct msn_auth_data *mad )
     677void msn_auth_got_passport_token( struct im_connection *ic, char *token )
    772678{
    773         struct im_connection *ic = mad->data;
    774679        struct msn_data *md;
    775680       
     
    779684       
    780685        md = ic->proto_data;
    781         if( mad->token )
     686       
    782687        {
    783688                char buf[1024];
    784689               
    785                 g_snprintf( buf, sizeof( buf ), "USR %d TWN S %s\r\n", ++md->trId, mad->token );
     690                g_snprintf( buf, sizeof( buf ), "USR %d SSO S %s %s\r\n", ++md->trId, md->tokens[0], token );
    786691                msn_write( ic, buf, strlen( buf ) );
    787692        }
    788         else
    789         {
    790                 imcb_error( ic, "Error during Passport authentication: %s", mad->error );
    791                 imc_logout( ic, TRUE );
    792         }
    793693}
    794694
    795 static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name )
     695void msn_auth_got_contact_list( struct im_connection *ic )
    796696{
    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         }
     697        char buf[64];
     698        struct msn_data *md;
     699       
     700        /* Dead connection? */
     701        if( g_slist_find( msn_connections, ic ) == NULL )
     702                return;
     703       
     704        md = ic->proto_data;
     705       
     706       
     707        g_snprintf( buf, sizeof( buf ), "BLP %d %s\r\n", ++md->trId, "BL" );
     708        msn_write( ic, buf, strlen( buf ) );
    838709}
     710
     711static gboolean msn_ns_send_adl_1( gpointer key, gpointer value, gpointer data )
     712{
     713        struct xt_node *adl = data, *d, *c;
     714        struct bee_user *bu = value;
     715        struct msn_buddy_data *bd = bu->data;
     716        char handle[strlen(bu->handle)];
     717        char *domain;
     718        char l[4];
     719       
     720        strcpy( handle, bu->handle );
     721        if( ( domain = strchr( handle, '@' ) ) == NULL ) /* WTF */
     722                return FALSE;
     723        *domain = '\0';
     724        domain ++;
     725       
     726        if( ( d = adl->children ) == NULL ||
     727            g_strcasecmp( xt_find_attr( d, "n" ), domain ) != 0 )
     728        {
     729                d = xt_new_node( "d", NULL, NULL );
     730                xt_add_attr( d, "n", domain );
     731                xt_insert_child( adl, d );
     732        }
     733       
     734        g_snprintf( l, sizeof( l ), "%d", bd->flags & 7 );
     735        c = xt_new_node( "c", NULL, NULL );
     736        xt_add_attr( c, "n", handle );
     737        xt_add_attr( c, "l", l );
     738        xt_add_attr( c, "t", "1" ); /* 1 means normal, 4 means mobile? */
     739        xt_insert_child( d, c );
     740       
     741        return FALSE;
     742}
     743
     744static void msn_ns_send_adl( struct im_connection *ic )
     745{
     746        struct xt_node *adl;
     747        struct msn_data *md;
     748        char *adls, buf[64];
     749       
     750        /* Dead connection? */
     751        if( g_slist_find( msn_connections, ic ) == NULL )
     752                return;
     753       
     754        md = ic->proto_data;
     755       
     756        adl = xt_new_node( "ml", NULL, NULL );
     757        xt_add_attr( adl, "l", "1" );
     758        g_tree_foreach( md->domaintree, msn_ns_send_adl_1, adl );
     759        adls = xt_to_string( adl );
     760       
     761        g_snprintf( buf, sizeof( buf ), "ADL %d %zd\r\n", ++md->trId, strlen( adls ) );
     762        if( msn_write( ic, buf, strlen( buf ) ) )
     763                msn_write( ic, adls, strlen( adls ) );
     764       
     765        g_free( adls );
     766        xt_free_node( adl );
     767}
  • protocols/msn/sb.c

    r136c2bb r07874be  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2005 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2010 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    2727#include "nogaim.h"
    2828#include "msn.h"
    29 #include "passport.h"
    3029#include "md5.h"
     30#include "soap.h"
    3131#include "invitation.h"
    3232
     
    3838{
    3939        int st;
     40       
     41        if( getenv( "BITLBEE_DEBUG" ) )
     42        {
     43                write( 2, "->SB:", 5 );
     44                write( 2, s, len );
     45        }
    4046       
    4147        st = write( sb->fd, s, len );
     
    407413        else if( strcmp( cmd[0], "USR" ) == 0 )
    408414        {
    409                 if( num_parts != 5 )
     415                if( num_parts < 5 )
    410416                {
    411417                        msn_sb_destroy( sb );
     
    433439                int num, tot;
    434440               
    435                 if( num_parts != 6 )
     441                if( num_parts < 6 )
    436442                {
    437443                        msn_sb_destroy( sb );
     
    470476        else if( strcmp( cmd[0], "ANS" ) == 0 )
    471477        {
    472                 if( num_parts != 3 )
     478                if( num_parts < 3 )
    473479                {
    474480                        msn_sb_destroy( sb );
     
    489495        else if( strcmp( cmd[0], "CAL" ) == 0 )
    490496        {
    491                 if( num_parts != 4 || !isdigit( cmd[3][0] ) )
     497                if( num_parts < 4 || !isdigit( cmd[3][0] ) )
    492498                {
    493499                        msn_sb_destroy( sb );
     
    499505        else if( strcmp( cmd[0], "JOI" ) == 0 )
    500506        {
    501                 if( num_parts != 3 )
     507                if( num_parts < 3 )
    502508                {
    503509                        msn_sb_destroy( sb );
     
    560566        else if( strcmp( cmd[0], "MSG" ) == 0 )
    561567        {
    562                 if( num_parts != 4 )
     568                if( num_parts < 4 )
    563569                {
    564570                        msn_sb_destroy( sb );
     
    625631                const struct msn_status_code *err = msn_status_by_number( num );
    626632               
    627                 imcb_error( ic, "Error reported by switchboard server: %s", err->text );
     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 );
    628639               
    629640                if( err->flags & STATUS_SB_FATAL )
  • protocols/msn/tables.c

    r136c2bb r07874be  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2004 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2010 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
  • protocols/nogaim.c

    r136c2bb r07874be  
    326326        imcb_log( ic, "Signing off.." );
    327327       
    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        
    336328        for( l = bee->users; l; )
    337329        {
     
    344336                l = next;
    345337        }
     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;
    346346       
    347347        query_del_by_conn( (irc_t*) ic->bee->ui_data, ic );
  • protocols/nogaim.h

    r136c2bb r07874be  
    194194           this info via imcb_log(). Implementing these are optional. */
    195195        void (* get_info)       (struct im_connection *, char *who);
     196        /* set_my_name is *DEPRECATED*, not used by the UI anymore. Use the
     197           display_name setting instead. */
    196198        void (* set_my_name)    (struct im_connection *, char *name);
    197199        void (* set_name)       (struct im_connection *, char *who, char *name);
  • storage_xml.c

    r136c2bb r07874be  
    320320        else if( g_strcasecmp( g_markup_parse_context_get_element( ctx ), "setting" ) == 0 && xd->current_setting )
    321321        {
     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                }
    322332                set_setstr( xd->current_set_head, xd->current_setting, (char*) text );
    323333                g_free( xd->current_setting );
Note: See TracChangeset for help on using the changeset viewer.