Ignore:
Timestamp:
2010-10-02T05:34:53Z (14 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
2af3e23
Parents:
05bf2a0 (diff), 04cd284 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merging msnp13 branch which, confusingly, upgrades the msn module to use
MSNP15. (The reason for this is that A) IMHO MSNP13 is what causes most of
the pain in this upgade and B) I initially intended to only implement MSNP13
but then discovered MS doesn't support it anymore.)

This fixes issues with display names being forgotten, adding contacts (and
them automatically getting blocked sometimes!!), and adds support for
away/status messages and some support for sending offline messages.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • protocols/msn/msn_util.c

    r05bf2a0 r62f53b50  
    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"
     29#include "soap.h"
    2830#include <ctype.h>
    2931
    30 int msn_write( struct im_connection *ic, char *s, int len )
     32int msn_logged_in( struct im_connection *ic )
     33{
     34        imcb_connected( ic );
     35       
     36        return( 0 );
     37}
     38
     39static char *adlrml_entry( const char *handle_, msn_buddy_flags_t list )
     40{
     41        char *domain, handle[strlen(handle_)+1];
     42       
     43        strcpy( handle, handle_ );
     44        if( ( domain = strchr( handle, '@' ) ) )
     45                *(domain++) = '\0';
     46        else
     47                return NULL;
     48       
     49        return g_markup_printf_escaped( "<ml><d n=\"%s\"><c n=\"%s\" l=\"%d\" t=\"1\"/></d></ml>",
     50                domain, handle, list );
     51}
     52
     53int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname, const char *group )
    3154{
    3255        struct msn_data *md = ic->proto_data;
    33         int st;
    34        
    35         st = write( md->fd, s, len );
    36         if( st != len )
    37         {
    38                 imcb_error( ic, "Short write() to main server" );
    39                 imc_logout( ic, TRUE );
    40                 return 0;
    41         }
    42        
    43         return 1;
    44 }
    45 
    46 int msn_logged_in( struct im_connection *ic )
    47 {
    48         imcb_connected( ic );
    49        
    50         return( 0 );
    51 }
    52 
    53 int msn_buddy_list_add( struct im_connection *ic, const char *list, const char *who, const char *realname_, const char *group )
    54 {
    55         struct msn_data *md = ic->proto_data;
    56         char buf[1024], *realname, groupid[8];
     56        char groupid[8];
     57        bee_user_t *bu;
     58        struct msn_buddy_data *bd;
     59        char *adl;
    5760       
    5861        *groupid = '\0';
     62#if 0
    5963        if( group )
    6064        {
     
    8791                        if( l == NULL )
    8892                        {
    89                                 char *groupname = msn_http_encode( group );
     93                                char groupname[strlen(group)+1];
     94                                strcpy( groupname, group );
     95                                http_encode( groupname );
    9096                                g_snprintf( buf, sizeof( buf ), "ADG %d %s %d\r\n", ++md->trId, groupname, 0 );
    91                                 g_free( groupname );
    9297                                return msn_write( ic, buf, strlen( buf ) );
    9398                        }
     
    101106                }
    102107        }
    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 )
     108#endif
     109       
     110        if( !( ( bu = bee_user_by_handle( ic->bee, ic, who ) ) ||
     111               ( bu = bee_user_new( ic->bee, ic, who, 0 ) ) ) ||
     112            !( bd = bu->data ) || bd->flags & list )
     113                return 1;
     114       
     115        bd->flags |= list;
     116       
     117        if( list == MSN_BUDDY_FL )
     118                msn_soap_ab_contact_add( ic, bu );
     119        else
     120                msn_soap_memlist_edit( ic, who, TRUE, list );
     121       
     122        if( ( adl = adlrml_entry( who, list ) ) )
     123        {
     124                int st = msn_ns_write( ic, -1, "ADL %d %zd\r\n%s",
     125                                       ++md->trId, strlen( adl ), adl );
     126                g_free( adl );
     127               
     128                return st;
     129        }
     130       
     131        return 1;
     132}
     133
     134int msn_buddy_list_remove( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *group )
    112135{
    113136        struct msn_data *md = ic->proto_data;
    114         char buf[1024], groupid[8];
     137        char groupid[8];
     138        bee_user_t *bu;
     139        struct msn_buddy_data *bd;
     140        char *adl;
    115141       
    116142        *groupid = '\0';
     143#if 0
    117144        if( group )
    118145        {
     
    125152                        }
    126153        }
    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 );
     154#endif
     155       
     156        if( !( bu = bee_user_by_handle( ic->bee, ic, who ) ) ||
     157            !( bd = bu->data ) || !( bd->flags & list ) )
     158                return 1;
     159       
     160        bd->flags &= ~list;
     161       
     162        if( list == MSN_BUDDY_FL )
     163                msn_soap_ab_contact_del( ic, bu );
     164        else
     165                msn_soap_memlist_edit( ic, who, FALSE, list );
     166       
     167        if( ( adl = adlrml_entry( who, list ) ) )
     168        {
     169                int st = msn_ns_write( ic, -1, "RML %d %zd\r\n%s",
     170                                       ++md->trId, strlen( adl ), adl );
     171                g_free( adl );
     172               
     173                return st;
     174        }
     175       
     176        return 1;
    133177}
    134178
     
    144188        struct msn_buddy_ask_data *bla = data;
    145189       
    146         msn_buddy_list_add( bla->ic, "AL", bla->handle, bla->realname, NULL );
     190        msn_buddy_list_add( bla->ic, MSN_BUDDY_AL, bla->handle, bla->realname, NULL );
    147191       
    148192        imcb_ask_add( bla->ic, bla->handle, NULL );
     
    157201        struct msn_buddy_ask_data *bla = data;
    158202       
    159         msn_buddy_list_add( bla->ic, "BL", bla->handle, bla->realname, NULL );
     203        msn_buddy_list_add( bla->ic, MSN_BUDDY_BL, bla->handle, bla->realname, NULL );
    160204       
    161205        g_free( bla->handle );
     
    164208}
    165209
    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 );
     210void msn_buddy_ask( bee_user_t *bu )
     211{
     212        struct msn_buddy_ask_data *bla;
     213        struct msn_buddy_data *bd = bu->data;
    169214        char buf[1024];
    170215       
    171         bla->ic = ic;
    172         bla->handle = g_strdup( handle );
    173         bla->realname = g_strdup( realname );
     216        if( ( bd->flags & 30 ) != 8 && ( bd->flags & 30 ) != 16 )
     217                return;
     218       
     219        bla = g_new0( struct msn_buddy_ask_data, 1 );
     220        bla->ic = bu->ic;
     221        bla->handle = g_strdup( bu->handle );
     222        bla->realname = g_strdup( bu->fullname );
    174223       
    175224        g_snprintf( buf, sizeof( buf ),
    176225                    "The user %s (%s) wants to add you to his/her buddy list.",
    177                     handle, realname );
    178         imcb_ask( ic, buf, bla, msn_buddy_ask_yes, msn_buddy_ask_no );
     226                    bu->handle, bu->fullname );
     227        imcb_ask( bu->ic, buf, bla, msn_buddy_ask_yes, msn_buddy_ask_no );
    179228}
    180229
     
    279328        if( st <= 0 )
    280329                return( -1 );
     330       
     331        if( getenv( "BITLBEE_DEBUG" ) )
     332        {
     333                write( 2, "->C:", 4 );
     334                write( 2, h->rxq + h->rxlen - st, st );
     335        }
    281336       
    282337        while( st )
     
    296351                                        cmd = msn_linesplit( cmd_text );
    297352                                        for( count = 0; cmd[count]; count ++ );
    298                                         st = h->exec_command( h->data, cmd, count );
     353                                        st = h->exec_command( h, cmd, count );
    299354                                        g_free( cmd_text );
    300355                                       
     
    331386                        for( count = 0; cmd[count]; count ++ );
    332387                       
    333                         st = h->exec_message( h->data, msg, h->msglen, cmd, count );
     388                        st = h->exec_message( h, msg, h->msglen, cmd, count );
    334389                        g_free( msg );
    335390                        g_free( h->cmd_text );
     
    367422}
    368423
    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 
    395424void msn_msgq_purge( struct im_connection *ic, GSList **list )
    396425{
     
    433462}
    434463
    435 gboolean msn_set_display_name( struct im_connection *ic, const char *rawname )
    436 {
    437         char *fn = msn_http_encode( rawname );
     464/* Copied and heavily modified from http://tmsnc.sourceforge.net/chl.c */
     465char *msn_p11_challenge( char *challenge )
     466{
     467        char *output, buf[256];
     468        md5_state_t md5c;
     469        unsigned char md5Hash[16], *newHash;
     470        unsigned int *md5Parts, *chlStringParts, newHashParts[5];
     471        long long nHigh = 0, nLow = 0;
     472        int i, n;
     473
     474        /* Create the MD5 hash */
     475        md5_init(&md5c);
     476        md5_append(&md5c, (unsigned char*) challenge, strlen(challenge));
     477        md5_append(&md5c, (unsigned char*) MSNP11_PROD_KEY, strlen(MSNP11_PROD_KEY));
     478        md5_finish(&md5c, md5Hash);
     479
     480        /* Split it into four integers */
     481        md5Parts = (unsigned int *)md5Hash;
     482        for (i = 0; i < 4; i ++)
     483        { 
     484                md5Parts[i] = GUINT32_TO_LE(md5Parts[i]);
     485               
     486                /* & each integer with 0x7FFFFFFF */
     487                /* and save one unmodified array for later */
     488                newHashParts[i] = md5Parts[i];
     489                md5Parts[i] &= 0x7FFFFFFF;
     490        }
     491       
     492        /* make a new string and pad with '0' */
     493        n = g_snprintf(buf, sizeof(buf)-5, "%s%s00000000", challenge, MSNP11_PROD_ID);
     494        /* truncate at an 8-byte boundary */
     495        buf[n&=~7] = '\0';
     496       
     497        /* split into integers */
     498        chlStringParts = (unsigned int *)buf;
     499       
     500        /* this is magic */
     501        for (i = 0; i < (n / 4) - 1; i += 2)
     502        {
     503                long long temp;
     504
     505                chlStringParts[i]   = GUINT32_TO_LE(chlStringParts[i]);
     506                chlStringParts[i+1] = GUINT32_TO_LE(chlStringParts[i+1]);
     507
     508                temp  = (md5Parts[0] * (((0x0E79A9C1 * (long long)chlStringParts[i]) % 0x7FFFFFFF)+nHigh) + md5Parts[1])%0x7FFFFFFF;
     509                nHigh = (md5Parts[2] * (((long long)chlStringParts[i+1]+temp) % 0x7FFFFFFF) + md5Parts[3]) % 0x7FFFFFFF;
     510                nLow  = nLow + nHigh + temp;
     511        }
     512        nHigh = (nHigh+md5Parts[1]) % 0x7FFFFFFF;
     513        nLow = (nLow+md5Parts[3]) % 0x7FFFFFFF;
     514       
     515        newHashParts[0] ^= nHigh;
     516        newHashParts[1] ^= nLow;
     517        newHashParts[2] ^= nHigh;
     518        newHashParts[3] ^= nLow;
     519       
     520        /* swap more bytes if big endian */
     521        for (i = 0; i < 4; i ++)
     522                newHashParts[i] = GUINT32_TO_LE(newHashParts[i]);
     523       
     524        /* make a string of the parts */
     525        newHash = (unsigned char *)newHashParts;
     526       
     527        /* convert to hexadecimal */
     528        output = g_new(char, 33);
     529        for (i = 0; i < 16; i ++)
     530                sprintf(output + i * 2, "%02x", newHash[i]);
     531       
     532        return output;
     533}
     534
     535gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ )
     536{
     537        const char *a = a_, *b = b_;
     538        gint ret;
     539       
     540        if( !( a = strchr( a, '@' ) ) || !( b = strchr( b, '@' ) ) ||
     541            ( ret = strcmp( a, b ) ) == 0 )
     542                ret = strcmp( a_, b_ );
     543       
     544        return ret;
     545}
     546
     547struct msn_group *msn_group_by_name( struct im_connection *ic, const char *name )
     548{
    438549        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 }
     550        GSList *l;
     551       
     552        for( l = md->groups; l; l = l->next )
     553        {
     554                struct msn_group *mg = l->data;
     555               
     556                if( g_strcasecmp( mg->name, name ) == 0 )
     557                        return mg;
     558        }
     559       
     560        return NULL;
     561}
     562
     563struct msn_group *msn_group_by_id( struct im_connection *ic, const char *id )
     564{
     565        struct msn_data *md = ic->proto_data;
     566        GSList *l;
     567       
     568        for( l = md->groups; l; l = l->next )
     569        {
     570                struct msn_group *mg = l->data;
     571               
     572                if( g_strcasecmp( mg->id, id ) == 0 )
     573                        return mg;
     574        }
     575       
     576        return NULL;
     577}
     578
     579int msn_ns_set_display_name( struct im_connection *ic, const char *value )
     580{
     581        struct msn_data *md = ic->proto_data;
     582        char fn[strlen(value)*3+1];
     583       
     584        strcpy( fn, value );
     585        http_encode( fn );
     586       
     587        /* Note: We don't actually know if the server accepted the new name,
     588           and won't give proper feedback yet if it doesn't. */
     589        return msn_ns_write( ic, -1, "PRP %d MFN %s\r\n", ++md->trId, fn );
     590}
Note: See TracChangeset for help on using the changeset viewer.