Changes in / [508588a:3ad8036]


Ignore:
Files:
2 added
4 deleted
46 edited

Legend:

Unmodified
Added
Removed
  • bitlbee.c

    r508588a r3ad8036  
    136136               
    137137                setsid();
    138                 i = chdir( "/" );
    139                 /* Don't use i, just make gcc happy. :-/ */
     138                chdir( "/" );
    140139               
    141140                if( getenv( "_BITLBEE_RESTART_STATE" ) == NULL )
  • bitlbee.h

    r508588a r3ad8036  
    137137#include "log.h"
    138138#include "ini.h"
     139#include "help.h"
    139140#include "query.h"
    140141#include "sock.h"
     
    146147        int listen_socket;
    147148        gint listen_watch_source_id;
    148         struct help *help;
     149        help_t *help;
    149150        char *conf_file;
    150151        conf_t *conf;
  • configure

    r508588a r3ad8036  
    3434gcov=0
    3535plugins=1
    36 otr=0
     36otr=auto
    3737
    3838events=glib
     
    7373
    7474--purple=0/1    Disable/enable libpurple support        $purple
    75                 (automatically disables other protocol modules)
    7675
    7776--debug=0/1     Disable/enable debugging                $debug
     
    7978--gcov=0/1      Disable/enable test coverage reporting  $gcov
    8079--plugins=0/1   Disable/enable plugins support          $plugins
    81 --otr=0/1/auto/plugin
    82                 Disable/enable OTR encryption support   $otr
     80--otr=0/1       Disable/enable OTR encryption support   $otr
    8381
    8482--events=...    Event handler (glib, libevent)          $events
     
    427425fi;
    428426
    429 if [ "$msn" = "1" -a "$ssl" != "openssl" ]; then
    430         # Needed for MSN only. OpenSSL exports nice cipher functions already,
    431         # others don't, so use our own 3des code.
    432         echo 'DES=des.o' >> Makefile.settings
    433 fi
    434 
    435427echo 'SSL_CLIENT=ssl_'$ssl'.o' >> Makefile.settings
    436428
  • doc/CHANGES

    r508588a r3ad8036  
    44http://bugs.bitlbee.org/bitlbee/timeline?daysback=90&changeset=on
    55
    6 Version
    7 - Important: This version drops backward compatibility with the file format
    8   used for user settings in versions before 1.2. If you're upgrading from
    9   very old BitlBee versions (like 1.0.x), you'll have to recreate your
    10   BitlBee account - or use an 1.2.x BitlBee once to do the conversion.
     6Version 1.3dev:
     7- For the first time since 2007, a dev snapshot. Like then, this is pretty
     8  stable already (running on testing.bitlbee.org for weeks by now), but not
     9  all planned features for the next major release are ready yet, and there
     10  may be some rough edges in the interface and documentation.
     11- Loads of new stuff, mostly ready for a new major release, but starting with
     12  a dev snapshot. A few changes that were planned for a long time already:
    1113- Rewrote the IRC core, which brings:
    1214  * Support for multiple (control) channels, so you can have one channel per
     
    5052    for a list of supported protocols (works only in libpurple-enabled
    5153    binaries).
    52 - Rewritten MSN module, implementing MSNP15 instead of the old MSNP8:
    53   * MSNP8 support from MSN was getting pretty unreliable. There were issues
    54     with remembering display names and adding contacts/auth requests (or
    55     even contacts silently getting blocked!). This upgrade should fix all
    56     of that.
    57   * Support for sending offline messages.
    58   * Support for setting and reading status messages.
    5954- Support for file transfers, in and out. /DCC SEND a file to a contact and
    6055  it becomes a file transfer, and incoming file transfers become /DCC SENDs
     
    6358- Updated Yahoo! module to be in sync again with libyahoo2. This mostly
    6459  fixes issues with authorization requests.
    65 - Show if a contact is mobile or not. See "help set mobile_is_away".
    66 - Easier handling of XMPP chatroom invitations.
    67 - The chatroom mode of the Twitter module is now enabled by default, since
    68   this was by far the most popular. To disable it, see "help set mode".
    69 - Added some Twitter-specific commands that can only be used in the Twitter
    70   window. Most important addition: Retweets. See "help set commands".
    71 - Removed some ancient account/nick migration scripts and added one for
    72   easier switching from Pidgin and other libpurple-based clients to BitlBee.
    73 - Many bug fixes in both the core and IM modules, small feature enhancements
    74   and other minor changes.
    75 
    76 Finished ...
     60
     61Finished 6 Aug 2010
    7762
    7863Version 1.2.8:
  • doc/FAQ

    r508588a r3ad8036  
    6262   These days, we replaced the Yahoo! code with libyahoo2 (which is a
    6363   separate Yahoo! module. It's derived from Gaim, but separately
    64    maintained) and wrote our own MSN, Jabber and Twitter modules from
    65    scratch. Most of the API has also been changed, so by now the only traces
    66    of Gaim left are in the "nogaim" filename.
     64   maintained) and wrote our own MSN module. More modules are probably going
     65   to be changed, so in the near future, the API might be the only thing
     66   left from Gaim.
     67
     68Q: What's that Gaim doing in BitlBee error messages and my Jabber resource?
     69A: Ah, well, as you probably know we use some of Gaim's IM-modules, and we
     70   don't think it's worth our time to do a search-and-replace over the whole
     71   source to get rid of every reference to Gaim. In fact, we don't want to,
     72   since we don't want to pretend we wrote all that code.
    6773   
    68    There is good news for Gaim (or now Pidgin, of course) fans though:
    69    BitlBee can now be compiled to use libpurple for all IM interactions.
    70    This makes BitlBee a bit more resource-hungry, but adds support for many
    71    IM protocols/networks that couldn't be used from BitlBee so far.
     74   About Jabber: If you want a different resource string, you can set it
     75   when logging in by appending it to your Jabber ID, like:
     76   lintux@jabber.com/BitlBee
  • doc/README

    r508588a r3ad8036  
    6767platform. Any recent version of GLib (2.4 or higher) will work.
    6868
    69 Off-the-Record encryption support can be included if libotr is available on
    70 your machine. Pass --otr=1 to configure to build it into BitlBee, or
    71 --otr=plugin to build it as a separate loadable plugin (mostly meant for
    72 distro packages).
     69Off-the-Record encryption support will be included by default if the
     70configure script finds libotr in one of the usual places. You can pass
     71--otr=1 or --otr=0 to force it on or off, respectively.
    7372
    74 These days, many IM protocols use SSL/TLS connections (for authentication
    75 or for the whole session). BitlBee can use several SSL libraries for this:
    76 GnuTLS, NSS (which comes with Mozilla) and OpenSSL. OpenSSL is not GPL-
    77 compatible in some situations, so using GnuTLS is preferred. However,
    78 especially on *BSD, OpenSSL can be considered part of the operating system,
    79 which eliminates the GPL incompatibility.
     73These days, MSN Messenger clients have to connect to the MS Passport servers
     74through HTTPS. BitlBee can use several SSL libraries for this: GnuTLS, NSS
     75(which comes with Mozilla) and OpenSSL. OpenSSL is not GPL-compatible in some
     76situations, so using GnuTLS or NSS is preferred. However, especially on *BSD,
     77OpenSSL can be considered part of the operating system, which eliminates the
     78GPL incompatibility.
    8079
    8180The incompatibility is also the reason why the SSL library detection code
  • doc/user-guide/commands.xml

    r508588a r3ad8036  
    16671667                                Only the <emphasis>group list</emphasis> command is supported at the moment, which shows a list of all groups defined so far.
    16681668                        </para>
    1669                        
    1670                         <para>
    1671                                 If you want to move contacts between groups, you can use the IRC <emphasis>/invite</emphasis> command. Also, if you use the <emphasis>add</emphasis> command in a control channel configured to show just one group, the new contact will automatically be added to that group.
    1672                         </para>
    16731669                </description>
    16741670        </bitlbee-command>
  • doc/user-guide/misc.xml

    r508588a r3ad8036  
    175175
    176176<para>
    177 If you want to configure your own channels, you can use the <emphasis>channel set</emphasis> command. See <emphasis>help channels3</emphasis> for more information.
    178 </para>
    179 
    180 </sect1>
    181 
    182 <sect1 id="channels3">
    183 <title>Configuring a control channel</title>
    184 
    185 <para>
    186 The most important setting for a control channel is <emphasis>fill_by</emphasis>. It
    187 tells BitlBee what information should be used to decide if someone should be shown
    188 in the channel or not. After setting this setting to, for example, <emphasis>account</emphasis>, you
    189 also have to set the <emphasis>account</emphasis> setting. Example:
    190 </para>
    191 
    192 <ircexample>
    193         <ircline nick="wilmer">chan set &amp;wlm fill_by account</ircline>
    194         <ircline nick="root">fill_by = `account'</ircline>
    195         <ircline nick="wilmer">chan set &amp;wlm account msn</ircline>
    196         <ircline nick="root">account = `msn'</ircline>
    197 </ircexample>
    198 
    199 <para>
    200 Also, each channel has a <emphasis>show_users</emphasis> setting which lets you
    201 choose, for example, if you want to see only online contacts in a channel, or
    202 also/just offline contacts. Example:
    203 </para>
    204 
    205 <ircexample>
    206         <ircline nick="wilmer">chan set &amp;offline show_users offline</ircline>
    207         <ircline nick="root">show_users = `offline'</ircline>
    208 </ircexample>
    209 
    210 <para>
    211 See the help information for all these settings for more information.
     177If you want to configure your own channels, you can use the <emphasis>channel set</emphasis>.
    212178</para>
    213179
     
    268234</sect1>
    269235
    270 <sect1 id="whatsnew010206">
    271 <title>New stuff in BitlBee 1.2.6</title>
    272 
    273 <para>
    274 Twitter support. See <emphasis>help account add twitter</emphasis>.
    275 </para>
    276 </sect1>
    277 
    278 <sect1 id="whatsnew010300">
     236<sect1 id="news1.3">
    279237<title>New stuff in BitlBee 1.3dev</title>
    280 
    281 <para>
    282 Support for multiple configurable control channels, each with a subset of
    283 your contact list. See <emphasis>help channels</emphasis> for more
    284 information.
    285 </para>
    286 
    287 <para>
    288 File transfer support for some protocols (more if you use libpurple). Just
    289 /DCC SEND stuff. Incoming files also become DCC transfers.
    290 </para>
    291 
    292 <para>
    293 Only if you run your own BitlBee instance: You can build a BitlBee that uses
    294 libpurple for connecting to IM networks instead of its own code, adding
    295 support for some of the more obscure IM protocols and features.
    296 </para>
    297 
    298 <para>
    299 Many more things, briefly described in <emphasis>help news1.3</emphasis>.
    300 </para>
    301 </sect1>
    302 
    303 <sect1 id="news1.3">
    304 <title>New stuff in BitlBee 1.3dev (details)</title>
    305238
    306239<para>
  • help.c

    r508588a r3ad8036  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2010 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2009 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    2626#define BITLBEE_CORE
    2727#include "bitlbee.h"
    28 #include "help.h"
    2928#undef read
    3029#undef write
     
    158157                        }
    159158                       
    160                         if( lseek( h->fd, h->offset.file_offset, SEEK_SET ) == -1 ||
    161                             read( h->fd, s, h->length ) != h->length )
    162                                 return NULL;
     159                        lseek( h->fd, h->offset.file_offset, SEEK_SET );
     160                        read( h->fd, s, h->length );
    163161                }
    164162                else
     
    195193        return 1;
    196194}
    197 
    198 char *help_get_whatsnew( help_t **help, int old )
    199 {
    200         GString *ret = NULL;
    201         help_t *h;
    202         int v;
    203        
    204         for( h = *help; h; h = h->next )
    205                 if( h->title != NULL && strncmp( h->title, "whatsnew", 8 ) == 0 &&
    206                     sscanf( h->title + 8, "%x", &v ) == 1 && v > old )
    207                 {
    208                         char *s = help_get( &h, h->title );
    209                         if( ret == NULL )
    210                                 ret = g_string_new( s );
    211                         else
    212                                 g_string_append_printf( ret, "\n\n%s", s );
    213                         g_free( s );
    214                 }
    215        
    216         return ret ? g_string_free( ret, FALSE ) : NULL;
    217 }
  • help.h

    r508588a r3ad8036  
    4747char *help_get( help_t **help, char *title );
    4848int help_add_mem( help_t **help, const char *title, const char *content_ );
    49 char *help_get_whatsnew( help_t **help, int old );
    5049
    5150#endif
  • irc.c

    r508588a r3ad8036  
    114114        s = set_add( &b->set, "last_version", NULL, NULL, irc );
    115115        s->flags |= SET_HIDDEN;
    116         s->value = g_strdup_printf( "%d", BITLBEE_VERSION_CODE );
    117116        s = set_add( &b->set, "lcnicks", "true", set_eval_bool, irc );
    118117        s = set_add( &b->set, "nick_format", "%-@nick", NULL, irc );
  • irc_channel.c

    r508588a r3ad8036  
    192192        if( strcmp( value, "control" ) == 0 )
    193193                new = &control_channel_funcs;
    194         else if( ic != ic->irc->default_channel && strcmp( value, "chat" ) == 0 )
     194        else if( strcmp( value, "chat" ) == 0 )
    195195                new = &irc_channel_im_chat_funcs;
    196196        else
  • irc_commands.c

    r508588a r3ad8036  
    2626#define BITLBEE_CORE
    2727#include "bitlbee.h"
    28 #include "help.h"
    2928#include "ipc.h"
    3029
  • irc_im.c

    r508588a r3ad8036  
    590590        irc_channel_t *ic = c->ui_data;
    591591       
    592         if( ic == NULL || bu == NULL )
     592        if( ic == NULL )
    593593                return FALSE;
    594594       
     
    753753                {
    754754                        *s = '\0';
    755                         if( ( iu = irc_user_by_name( ic->irc, nick ) ) && iu->bu &&
     755                        if( ( iu = irc_user_by_name( ic->irc, nick ) ) &&
    756756                            iu->bu->nick && irc_channel_has_user( ic, iu ) )
    757757                        {
     
    858858                c->ic->acc->prpl->chat_topic( c, topic );
    859859                g_free( topic );
    860         }
    861                
    862         /* Whatever happened, the IM module should ack the topic change. */
     860                return TRUE;
     861        }
     862               
    863863        return FALSE;
    864864}
  • irc_send.c

    r508588a r3ad8036  
    5353void irc_send_motd( irc_t *irc )
    5454{
    55         char motd[2048];
    56         size_t len;
    5755        int fd;
    5856       
    5957        fd = open( global.conf->motdfile, O_RDONLY );
    60         if( fd == -1 || ( len = read( fd, motd, sizeof( motd ) - 1 ) ) <= 0 )
     58        if( fd == -1 )
    6159        {
    6260                irc_send_num( irc, 422, ":We don't need MOTDs." );
     
    6462        else
    6563        {
    66                 char linebuf[80];
    67                 char *add = "", max, *in;
    68                
    69                 in = motd;
    70                 motd[len] = '\0';
     64                char linebuf[80];       /* Max. line length for MOTD's is 79 chars. It's what most IRC networks seem to do. */
     65                char *add, max;
     66                int len;
     67               
    7168                linebuf[79] = len = 0;
    7269                max = sizeof( linebuf ) - 1;
    7370               
    7471                irc_send_num( irc, 375, ":- %s Message Of The Day - ", irc->root->host );
    75                 while( ( linebuf[len] = *(in++) ) )
     72                while( read( fd, linebuf + len, 1 ) == 1 )
    7673                {
    7774                        if( linebuf[len] == '\n' || len == max )
     
    8380                        else if( linebuf[len] == '%' )
    8481                        {
    85                                 linebuf[len] = *(in++);
     82                                read( fd, linebuf + len, 1 );
    8683                                if( linebuf[len] == 'h' )
    8784                                        add = irc->root->host;
     
    9087                                else if( linebuf[len] == 'n' )
    9188                                        add = irc->user->nick;
    92                                 else if( linebuf[len] == '\0' )
    93                                         in --;
    9489                                else
    9590                                        add = "%";
     
    10499                }
    105100                irc_send_num( irc, 376, ":End of MOTD" );
    106         }
    107        
    108         if( fd != -1 )
    109101                close( fd );
     102        }
    110103}
    111104
     
    114107        irc_channel_t *ic = NULL;
    115108        irc_user_t *iu = irc->root;
    116         char text[1100];
     109        char text[1024];
    117110        va_list params;
    118111        char *dst;
  • lib/Makefile

    r508588a r3ad8036  
    1313
    1414# [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.o
     15objects = 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
    1616
    1717LFLAGS += -r
  • lib/events.h

    r508588a r3ad8036  
    8181G_MODULE_EXPORT void b_event_remove(gint id);
    8282
    83 /* With libevent, this one also cleans up event handlers if that wasn't already
    84    done (the caller is expected to do so but may miss it sometimes). */
     83/* For now, closesocket() is only a function when using libevent. With GLib
     84   it's a preprocessor macro. */
     85#ifdef EVENTS_LIBEVENT
    8586G_MODULE_EXPORT void closesocket(int fd);
     87#endif
    8688
    8789#endif /* _EVENTS_H_ */
  • lib/events_glib.c

    r508588a r3ad8036  
    147147                g_source_remove(tag);
    148148}
    149 
    150 void closesocket( int fd )
    151 {
    152         close( fd );
    153 }
  • lib/misc.c

    r508588a r3ad8036  
    308308void http_encode( char *s )
    309309{
    310         char t[strlen(s)+1];
     310        char *t;
    311311        int i, j;
    312312       
    313         strcpy( t, s );
     313        t = g_strdup( s );
     314       
    314315        for( i = j = 0; t[i]; i ++, j ++ )
    315316        {
     
    329330        }
    330331        s[j] = 0;
     332       
     333        g_free( t );
    331334}
    332335
  • lib/sha1.c

    r508588a r3ad8036  
    3636 */
    3737
    38 #include <string.h>
    3938#include "sha1.h"
    4039
     
    375374        sha1_process_block(context);
    376375}
    377 
    378 #define HMAC_BLOCK_SIZE 64
    379 
    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         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

    r508588a r3ad8036  
    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]);
    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]);
    7069
    7170#endif
  • lib/ssl_client.h

    r508588a r3ad8036  
    8181   the same action as the handler that just received the SSL_AGAIN.) */
    8282G_MODULE_EXPORT b_input_condition ssl_getdirection( void *conn );
    83 
    84 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

    r508588a r3ad8036  
    194194                ssl_errno = SSL_AGAIN;
    195195       
    196         if( 0 && getenv( "BITLBEE_DEBUG" ) && st > 0 ) write( 1, buf, st );
    197        
    198196        return st;
    199197}
     
    214212        if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED )
    215213                ssl_errno = SSL_AGAIN;
    216        
    217         if( 0 && getenv( "BITLBEE_DEBUG" ) && st > 0 ) write( 1, buf, st );
    218214       
    219215        return st;
  • lib/ssl_openssl.c

    r508588a r3ad8036  
    6060{
    6161        initialized = TRUE;
    62         SSL_library_init();
    63         // SSLeay_add_ssl_algorithms();
     62        SSLeay_add_ssl_algorithms();
    6463}
    6564
     
    211210        }
    212211       
    213         if( 0 && getenv( "BITLBEE_DEBUG" ) && st > 0 ) write( 1, buf, st );
    214        
    215212        return st;
    216213}
     
    227224       
    228225        st = SSL_write( ((struct scd*)conn)->ssl, buf, len );
    229        
    230         if( 0 && getenv( "BITLBEE_DEBUG" ) && st > 0 ) write( 1, buf, st );
    231226       
    232227        ssl_errno = SSL_OK;
     
    282277        return( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ? B_EV_IO_WRITE : B_EV_IO_READ );
    283278}
    284 
    285 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)
    286 {
    287         int output_length = 0;   
    288         EVP_CIPHER_CTX ctx;
    289        
    290         *res = g_new0(unsigned char, 72);
    291        
    292         /* Don't set key or IV because we will modify the parameters */
    293         EVP_CIPHER_CTX_init(&ctx);
    294         EVP_CipherInit_ex(&ctx, EVP_des_ede3_cbc(), NULL, NULL, NULL, 1);
    295         EVP_CIPHER_CTX_set_key_length(&ctx, key_len);
    296         EVP_CIPHER_CTX_set_padding(&ctx, 0);
    297         /* We finished modifying parameters so now we can set key and IV */
    298         EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, 1);
    299         EVP_CipherUpdate(&ctx, *res, &output_length, input, input_len);
    300         EVP_CipherFinal_ex(&ctx, *res, &output_length);
    301         EVP_CIPHER_CTX_cleanup(&ctx);   
    302         //EVP_cleanup();
    303        
    304         return output_length;
    305 }
  • lib/xmltree.c

    r508588a r3ad8036  
    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, const char *text, int text_len )
     143int xt_feed( struct xt_parser *xt, 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                 if( xt->handlers ) for( i = 0; xt->handlers[i].func; i ++ )
     176                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                                                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 ) ) )
    190190                        {
    191191                                st = xt->handlers[i].func( node, xt->data );
     
    260260}
    261261
    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 
    276262static void xt_to_string_real( struct xt_node *node, GString *str )
    277263{
     
    331317        /* Indentation */
    332318        for( c = node; c->parent; c = c->parent )
    333                 printf( "    " );
     319                printf( "\t" );
    334320       
    335321        /* Start the tag */
     
    338324        /* Print the attributes */
    339325        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 ) );
    345327       
    346328        /* /> in case there's really *nothing* inside this tag, otherwise
     
    362344                for( i = 0; node->text[i] && isspace( node->text[i] ); i ++ );
    363345                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 ) );
    369347        }
    370348       
     
    377355        if( node->children )
    378356                for( c = node; c->parent; c = c->parent )
    379                         printf( "    " );
     357                        printf( "\t" );
    380358       
    381359        /* Non-empty tag is now finished. */
     
    482460               
    483461                node = node->next;
    484         }
    485        
    486         return node;
    487 }
    488 
    489 /* More advanced than the one above, understands something like
    490    ../foo/bar to find a subnode bar of a node foo which is a child
    491    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                 else
    502                         n = strlen( name );
    503                
    504                 if( strncmp( name, "..", n ) == 0 )
    505                 {
    506                         node = node->parent;
    507                 }
    508                 else
    509                 {
    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;
    524462        }
    525463       
     
    612550}
    613551
    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 
    634552void xt_add_attr( struct xt_node *node, const char *key, const char *value )
    635553{
  • lib/xmltree.h

    r508588a r3ad8036  
    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, const char *text, int text_len );
     81int xt_feed( struct xt_parser *xt, 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 );
    84 struct xt_node *xt_from_string( const char *in );
    8584char *xt_to_string( struct xt_node *node );
    8685void xt_print( struct xt_node *node );
     
    8988void xt_free( struct xt_parser *xt );
    9089struct 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 );
    9290char *xt_find_attr( struct xt_node *node, const char *key );
    9391
    9492struct xt_node *xt_new_node( char *name, const char *text, struct xt_node *children );
    9593void xt_add_child( struct xt_node *parent, struct xt_node *child );
    96 void xt_insert_child( struct xt_node *parent, struct xt_node *child );
    9794void xt_add_attr( struct xt_node *node, const char *key, const char *value );
    9895int xt_remove_attr( struct xt_node *node, const char *key );
  • protocols/bee.h

    r508588a r3ad8036  
    151151 * - 'state' and 'message' can be NULL */
    152152G_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 );
    154153G_MODULE_EXPORT void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle );
    155154/* Call when a handle says something. 'flags' and 'sent_at may be just 0. */
  • protocols/bee_chat.c

    r508588a r3ad8036  
    196196        }
    197197       
    198         if( bee->ui->chat_remove_user && bu )
     198        if( bee->ui->chat_remove_user )
    199199                bee->ui->chat_remove_user( bee, c, bu );
    200200}
  • protocols/bee_user.c

    r508588a r3ad8036  
    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 );
    189190        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;
    196191       
    197192        if( bu->status == NULL && ( flags & OPT_MOBILE ) &&
     
    207202        g_free( old->status_msg );
    208203        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 );
    231204        g_free( old );
    232205}
  • protocols/jabber/conference.c

    r508588a r3ad8036  
    312312        char *s;
    313313       
    314         if( subject && chat )
    315         {
    316                 s = bud ? strchr( bud->ext_jid, '/' ) : NULL;
    317                 if( s ) *s = 0;
    318                 imcb_chat_topic( chat, bud ? bud->ext_jid : NULL, subject->text_len > 0 ?
    319                                  subject->text : NULL, jabber_get_timestamp( node ) );
    320                 if( s ) *s = '/';
    321         }
    322        
    323314        if( bud == NULL || ( jc && ~jc->flags & JCFLAG_MESSAGE_SENT && bud == jc->me ) )
    324315        {
     
    375366                return;
    376367        }
     368       
     369        if( subject )
     370        {
     371                s = strchr( bud->ext_jid, '/' );
     372                if( s ) *s = 0;
     373                imcb_chat_topic( chat, bud->ext_jid, subject->text_len > 0 ?
     374                                 subject->text : NULL, jabber_get_timestamp( node ) );
     375                if( s ) *s = '/';
     376        }
    377377        if( body && body->text_len > 0 )
    378378        {
  • protocols/msn/Makefile

    r508588a r3ad8036  
    1313
    1414# [SH] Program variables
    15 objects = msn.o msn_util.o ns.o sb.o soap.o tables.o
     15objects = msn.o msn_util.o ns.o passport.o sb.o tables.o
    1616
    1717LFLAGS += -r
  • protocols/msn/msn.c

    r508588a r3ad8036  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2010 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2004 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    2525
    2626#include "nogaim.h"
    27 #include "soap.h"
    2827#include "msn.h"
    2928
     
    3635static void msn_init( account_t *acc )
    3736{
    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 );
    4339        set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc );
    4440        set_add( &acc->set, "switchboard_keepalives", "false", set_eval_bool, acc );
    45        
    46         acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE;
    4741}
    4842
     
    5347       
    5448        ic->proto_data = md;
     49        md->fd = -1;
    5550       
    5651        if( strchr( acc->user, '@' ) == NULL )
     
    6156        }
    6257       
     58        imcb_log( ic, "Connecting" );
     59       
     60        md->fd = proxy_connect( "messenger.hotmail.com", 1863, msn_ns_connected, ic );
     61        if( md->fd < 0 )
     62        {
     63                imcb_error( ic, "Could not connect to server" );
     64                imc_logout( ic, TRUE );
     65                return;
     66        }
     67       
    6368        md->ic = ic;
    6469        md->away_state = msn_away_state_list;
    65         md->domaintree = g_tree_new( msn_domaintree_cmp );
    66         md->ns->fd = -1;
    67        
    68         msn_connections = g_slist_prepend( msn_connections, ic );
    69        
    70         imcb_log( ic, "Connecting" );
    71         msn_ns_connect( ic, md->ns, MSN_NS_HOST, MSN_NS_PORT );
     70       
     71        msn_connections = g_slist_append( msn_connections, ic );
    7272}
    7373
     
    7676        struct msn_data *md = ic->proto_data;
    7777        GSList *l;
    78         int i;
    7978       
    8079        if( md )
     
    8685                */
    8786               
    88                 msn_ns_close( md->ns );
     87                if( md->fd >= 0 )
     88                        closesocket( md->fd );
     89               
     90                if( md->handler )
     91                {
     92                        if( md->handler->rxq ) g_free( md->handler->rxq );
     93                        if( md->handler->cmd_text ) g_free( md->handler->cmd_text );
     94                        g_free( md->handler );
     95                }
    8996               
    9097                while( md->switchboards )
     
    9299               
    93100                msn_msgq_purge( ic, &md->msgq );
    94                 msn_soapq_flush( ic, FALSE );
    95                
    96                 for( i = 0; i < sizeof( md->tokens ) / sizeof( md->tokens[0] ); i ++ )
    97                         g_free( md->tokens[i] );
    98                 g_free( md->lock_key );
    99                 g_free( md->pp_policy );
    100                
    101                 while( md->groups )
    102                 {
    103                         struct msn_group *mg = md->groups->data;
    104                         g_free( mg->id );
    105                         g_free( mg->name );
    106                         g_free( mg );
    107                         md->groups = g_slist_remove( md->groups, mg );
    108                 }
    109                
    110                 g_tree_destroy( md->domaintree );
    111                 md->domaintree = NULL;
     101               
     102                while( md->groupcount > 0 )
     103                        g_free( md->grouplist[--md->groupcount] );
     104                g_free( md->grouplist );
    112105               
    113106                while( md->grpq )
     
    141134        if( strcmp( who, "raw" ) == 0 )
    142135        {
    143                 msn_ns_write( ic, -1, "%s\r\n", message );
     136                msn_write( ic, message, strlen( message ) );
     137                msn_write( ic, "\r\n", 2 );
    144138        }
    145139        else
     
    179173static void msn_set_away( struct im_connection *ic, char *state, char *message )
    180174{
    181         char *uux;
     175        char buf[1024];
    182176        struct msn_data *md = ic->proto_data;
    183177       
     
    187181                md->away_state = msn_away_state_list + 1;
    188182       
    189         if( !msn_ns_write( ic, -1, "CHG %d %s\r\n", ++md->trId, md->away_state->code ) )
    190                 return;
    191        
    192         uux = g_markup_printf_escaped( "<Data><PSM>%s</PSM><CurrentMedia></CurrentMedia>"
    193                                        "</Data>", message ? message : "" );
    194         msn_ns_write( ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux );
    195         g_free( uux );
     183        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
     187static void msn_set_my_name( struct im_connection *ic, char *info )
     188{
     189        msn_set_display_name( ic, info );
    196190}
    197191
     
    206200        struct bee_user *bu = bee_user_by_handle( ic->bee, ic, who );
    207201       
    208         msn_buddy_list_add( ic, MSN_BUDDY_FL, who, who, group );
     202        msn_buddy_list_add( ic, "FL", who, who, group );
    209203        if( bu && bu->group )
    210                 msn_buddy_list_remove( ic, MSN_BUDDY_FL, who, bu->group->name );
     204                msn_buddy_list_remove( ic, "FL", who, bu->group->name );
    211205}
    212206
    213207static void msn_remove_buddy( struct im_connection *ic, char *who, char *group )
    214208{
    215         msn_buddy_list_remove( ic, MSN_BUDDY_FL, who, NULL );
     209        msn_buddy_list_remove( ic, "FL", who, NULL );
    216210}
    217211
     
    273267static void msn_keepalive( struct im_connection *ic )
    274268{
    275         msn_ns_write( ic, -1, "PNG\r\n" );
     269        msn_write( ic, "PNG\r\n", strlen( "PNG\r\n" ) );
    276270}
    277271
    278272static void msn_add_permit( struct im_connection *ic, char *who )
    279273{
    280         msn_buddy_list_add( ic, MSN_BUDDY_AL, who, who, NULL );
     274        msn_buddy_list_add( ic, "AL", who, who, NULL );
    281275}
    282276
    283277static void msn_rem_permit( struct im_connection *ic, char *who )
    284278{
    285         msn_buddy_list_remove( ic, MSN_BUDDY_AL, who, NULL );
     279        msn_buddy_list_remove( ic, "AL", who, NULL );
    286280}
    287281
     
    290284        struct msn_switchboard *sb;
    291285       
    292         msn_buddy_list_add( ic, MSN_BUDDY_BL, who, who, NULL );
     286        msn_buddy_list_add( ic, "BL", who, who, NULL );
    293287       
    294288        /* If there's still a conversation with this person, close it. */
     
    301295static void msn_rem_deny( struct im_connection *ic, char *who )
    302296{
    303         msn_buddy_list_remove( ic, MSN_BUDDY_BL, who, NULL );
     297        msn_buddy_list_remove( ic, "BL", who, NULL );
    304298}
    305299
     
    320314        account_t *acc = set->data;
    321315        struct im_connection *ic = acc->ic;
    322         struct msn_data *md = ic->proto_data;
     316       
     317        /* Allow any name if we're offline. */
     318        if( ic == NULL )
     319                return value;
    323320       
    324321        if( strlen( value ) > 129 )
     
    328325        }
    329326       
    330         if( md->flags & MSN_GOT_PROFILE_DN )
    331                 imcb_log( ic, "Warning: Persistent name changes for this account have to be done "
    332                               "in the profile. BitlBee doesn't currently support this." );
    333        
    334         msn_soap_addressbook_set_display_name( ic, value );
    335         return msn_ns_set_display_name( ic, value ) ? value : NULL;
    336 }
    337 
    338 static void msn_buddy_data_add( bee_user_t *bu )
    339 {
    340         struct msn_data *md = bu->ic->proto_data;
    341         bu->data = g_new0( struct msn_buddy_data, 1 );
    342         g_tree_insert( md->domaintree, bu->handle, bu );
    343 }
    344 
    345 static void msn_buddy_data_free( bee_user_t *bu )
    346 {
    347         struct msn_data *md = bu->ic->proto_data;
    348         g_tree_remove( md->domaintree, bu->handle );
    349         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;
    350331}
    351332
     
    363344        ret->set_away = msn_set_away;
    364345        ret->get_info = msn_get_info;
     346        ret->set_my_name = msn_set_my_name;
    365347        ret->add_buddy = msn_add_buddy;
    366348        ret->remove_buddy = msn_remove_buddy;
     
    376358        ret->send_typing = msn_send_typing;
    377359        ret->handle_cmp = g_strcasecmp;
    378         ret->buddy_data_add = msn_buddy_data_add;
    379         ret->buddy_data_free = msn_buddy_data_free;
    380        
    381360        //ret->transfer_request = msn_ftp_transfer_request;
    382361
  • protocols/msn/msn.h

    r508588a r3ad8036  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2010 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2004 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    3939#endif
    4040
    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 #define MSN_NS_HOST "messenger.hotmail.com"
    47 #define MSN_NS_PORT 1863
    48 
    49 /* Some other version.
    50 #define MSNP11_PROD_KEY "O4BG@C7BWLYQX?5G"
    51 #define MSNP11_PROD_ID  "PROD01065C%ZFN6F"
    52 */
    53 
    54 #define MSNP11_PROD_KEY "ILTXC!4IXB5FB*PX"
    55 #define MSNP11_PROD_ID  "PROD0119GSJUC$18"
    56 #define MSNP_VER        "MSNP15"
    57 #define MSNP_BUILD      "8.5.1288"
     41#define QRY_NAME "msmsgs@msnmsgr.com"
     42#define QRY_CODE "Q1P7W2E4J9R8U3S5"
    5843
    5944#define MSN_SB_NEW         -24062002
     
    7661#define PROFILE_URL "http://members.msn.com/"
    7762
    78 typedef enum
    79 {
    80         MSN_GOT_PROFILE = 1,
    81         MSN_GOT_PROFILE_DN = 2,
    82         MSN_DONE_ADL = 4,
    83         MSN_REAUTHING = 8,
    84 } msn_flags_t;
    85 
    86 struct msn_handler_data
    87 {
    88         int fd, inpa;
    89         int rxlen;
    90         char *rxq;
    91        
    92         int msglen;
    93         char *cmd_text;
    94        
    95         /* Either ic or sb */
    96         gpointer data;
    97        
    98         int (*exec_command) ( struct msn_handler_data *handler, char **cmd, int count );
    99         int (*exec_message) ( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int count );
    100 };
    101 
    10263struct msn_data
    10364{
    10465        struct im_connection *ic;
    10566       
    106         struct msn_handler_data ns[1];
    107         msn_flags_t flags;
     67        int fd;
     68        struct msn_handler_data *handler;
    10869       
    10970        int trId;
    110         char *tokens[4];
    111         char *lock_key, *pp_policy;
    112        
    113         GSList *msgq, *grpq, *soapq;
     71       
     72        GSList *msgq, *grpq;
    11473        GSList *switchboards;
    11574        int sb_failures;
    11675        time_t first_sb_failure;
     76        GSList *filetransfers;
    11777       
    11878        const struct msn_away_state *away_state;
    119         GSList *groups;
    120        
    121         /* Mostly used for sending the ADL command; since MSNP13 the client
    122            is responsible for downloading the contact list and then sending
    123            it to the MSNP server. */
    124         GTree *domaintree;
    125         int adl_todo;
     79        int buddycount;
     80        int groupcount;
     81        char **grouplist;
    12682};
    12783
     
    13086        struct im_connection *ic;
    13187       
    132         /* The following two are also in the handler. TODO: Clean up. */
    13388        int fd;
    13489        gint inp;
     
    172127};
    173128
    174 typedef enum
    175 {
    176         MSN_BUDDY_FL = 1,   /* Warning: FL,AL,BL *must* be 1,2,4. */
    177         MSN_BUDDY_AL = 2,
    178         MSN_BUDDY_BL = 4,
    179         MSN_BUDDY_RL = 8,
    180         MSN_BUDDY_PL = 16,
    181         MSN_BUDDY_ADL_SYNCED = 256,
    182 } msn_buddy_flags_t;
    183 
    184 struct msn_buddy_data
    185 {
    186         char *cid;
    187         msn_buddy_flags_t flags;
    188 };
    189 
    190 struct msn_group
    191 {
    192         char *name;
    193         char *id;
     129struct msn_handler_data
     130{
     131        int fd;
     132        int rxlen;
     133        char *rxq;
     134       
     135        int msglen;
     136        char *cmd_text;
     137       
     138        gpointer data;
     139       
     140        int (*exec_command) ( gpointer data, char **cmd, int count );
     141        int (*exec_message) ( gpointer data, char *msg, int msglen, char **cmd, int count );
    194142};
    195143
     
    213161
    214162/* ns.c */
    215 int msn_ns_write( struct im_connection *ic, int fd, const char *fmt, ... );
    216 gboolean msn_ns_connect( struct im_connection *ic, struct msn_handler_data *handler, const char *host, int port );
    217 void msn_ns_close( struct msn_handler_data *handler );
    218 void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error );
    219 void msn_auth_got_contact_list( struct im_connection *ic );
    220 int msn_ns_finish_login( struct im_connection *ic );
     163gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond );
    221164
    222165/* msn_util.c */
     166int msn_write( struct im_connection *ic, char *s, int len );
    223167int msn_logged_in( struct im_connection *ic );
    224 int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname_, const char *group );
    225 int msn_buddy_list_remove( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *group );
    226 void msn_buddy_ask( bee_user_t *bu );
     168int msn_buddy_list_add( struct im_connection *ic, const char *list, const char *who, const char *realname_, const char *group );
     169int msn_buddy_list_remove( struct im_connection *ic, char *list, const char *who, const char *group );
     170void msn_buddy_ask( struct im_connection *ic, char *handle, char *realname );
    227171char *msn_findheader( char *text, char *header, int len );
    228172char **msn_linesplit( char *line );
    229173int msn_handler( struct msn_handler_data *h );
     174char *msn_http_encode( const char *input );
    230175void msn_msgq_purge( struct im_connection *ic, GSList **list );
    231 char *msn_p11_challenge( char *challenge );
    232 gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ );
    233 struct msn_group *msn_group_by_name( struct im_connection *ic, const char *name );
    234 struct msn_group *msn_group_by_id( struct im_connection *ic, const char *id );
    235 int msn_ns_set_display_name( struct im_connection *ic, const char *value );
     176gboolean msn_set_display_name( struct im_connection *ic, const char *rawname );
    236177
    237178/* tables.c */
     
    242183
    243184/* sb.c */
    244 int msn_sb_write( struct msn_switchboard *sb, const char *fmt, ... );
     185int msn_sb_write( struct msn_switchboard *sb, char *s, int len );
    245186struct msn_switchboard *msn_sb_create( struct im_connection *ic, char *host, int port, char *key, int session );
    246187struct msn_switchboard *msn_sb_by_handle( struct im_connection *ic, char *handle );
     
    255196void msn_sb_stop_keepalives( struct msn_switchboard *sb );
    256197
     198/* invitation.c */
     199void msn_ftp_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who );
     200
    257201#endif //_MSN_H
  • protocols/msn/msn_util.c

    r508588a r3ad8036  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2010 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2004 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    2626#include "nogaim.h"
    2727#include "msn.h"
    28 #include "md5.h"
    29 #include "soap.h"
    3028#include <ctype.h>
    3129
     30int msn_write( struct im_connection *ic, char *s, int len )
     31{
     32        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
    3246int msn_logged_in( struct im_connection *ic )
    3347{
     
    3751}
    3852
    39 static 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 
    53 int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname, const char *group )
     53int msn_buddy_list_add( struct im_connection *ic, const char *list, const char *who, const char *realname_, const char *group )
    5454{
    5555        struct msn_data *md = ic->proto_data;
    56         char groupid[8];
    57         bee_user_t *bu;
    58         struct msn_buddy_data *bd;
    59         char *adl;
     56        char buf[1024], *realname, groupid[8];
    6057       
    6158        *groupid = '\0';
    62 #if 0
    6359        if( group )
    6460        {
     
    9187                        if( l == NULL )
    9288                        {
    93                                 char groupname[strlen(group)+1];
    94                                 strcpy( groupname, group );
    95                                 http_encode( groupname );
     89                                char *groupname = msn_http_encode( group );
    9690                                g_snprintf( buf, sizeof( buf ), "ADG %d %s %d\r\n", ++md->trId, groupname, 0 );
     91                                g_free( groupname );
    9792                                return msn_write( ic, buf, strlen( buf ) );
    9893                        }
     
    106101                }
    107102        }
    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 
    134 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
     111int msn_buddy_list_remove( struct im_connection *ic, char *list, const char *who, const char *group )
    135112{
    136113        struct msn_data *md = ic->proto_data;
    137         char groupid[8];
    138         bee_user_t *bu;
    139         struct msn_buddy_data *bd;
    140         char *adl;
     114        char buf[1024], groupid[8];
    141115       
    142116        *groupid = '\0';
    143 #if 0
    144117        if( group )
    145118        {
     
    152125                        }
    153126        }
    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;
     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 );
    177133}
    178134
     
    188144        struct msn_buddy_ask_data *bla = data;
    189145       
    190         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 );
    191147       
    192148        imcb_ask_add( bla->ic, bla->handle, NULL );
     
    201157        struct msn_buddy_ask_data *bla = data;
    202158       
    203         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 );
    204160       
    205161        g_free( bla->handle );
     
    208164}
    209165
    210 void msn_buddy_ask( bee_user_t *bu )
    211 {
    212         struct msn_buddy_ask_data *bla;
    213         struct msn_buddy_data *bd = bu->data;
     166void 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 );
    214169        char buf[1024];
    215170       
    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 );
     171        bla->ic = ic;
     172        bla->handle = g_strdup( handle );
     173        bla->realname = g_strdup( realname );
    223174       
    224175        g_snprintf( buf, sizeof( buf ),
    225176                    "The user %s (%s) wants to add you to his/her buddy list.",
    226                     bu->handle, bu->fullname );
    227         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 );
    228179}
    229180
     
    328279        if( st <= 0 )
    329280                return( -1 );
    330        
    331         if( getenv( "BITLBEE_DEBUG" ) )
    332         {
    333                 write( 2, "->C:", 4 );
    334                 write( 2, h->rxq + h->rxlen - st, st );
    335         }
    336281       
    337282        while( st )
     
    351296                                        cmd = msn_linesplit( cmd_text );
    352297                                        for( count = 0; cmd[count]; count ++ );
    353                                         st = h->exec_command( h, cmd, count );
     298                                        st = h->exec_command( h->data, cmd, count );
    354299                                        g_free( cmd_text );
    355300                                       
     
    386331                        for( count = 0; cmd[count]; count ++ );
    387332                       
    388                         st = h->exec_message( h, msg, h->msglen, cmd, count );
     333                        st = h->exec_message( h->data, msg, h->msglen, cmd, count );
    389334                        g_free( msg );
    390335                        g_free( h->cmd_text );
     
    422367}
    423368
     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! */
     374char *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
    424395void msn_msgq_purge( struct im_connection *ic, GSList **list )
    425396{
     
    462433}
    463434
    464 /* Copied and heavily modified from http://tmsnc.sourceforge.net/chl.c */
    465 char *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 
    535 gint 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 
    547 struct msn_group *msn_group_by_name( struct im_connection *ic, const char *name )
    548 {
     435gboolean msn_set_display_name( struct im_connection *ic, const char *rawname )
     436{
     437        char *fn = msn_http_encode( rawname );
    549438        struct msn_data *md = ic->proto_data;
    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 
    563 struct 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 
    579 int 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 }
     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

    r508588a r3ad8036  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2010 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2004 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    2727#include "nogaim.h"
    2828#include "msn.h"
     29#include "passport.h"
    2930#include "md5.h"
    30 #include "soap.h"
    31 #include "xmltree.h"
    32 
    33 static gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond );
     31
    3432static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond );
    35 static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num_parts );
    36 static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts );
    37 
    38 static void msn_ns_send_adl_start( struct im_connection *ic );
    39 static void msn_ns_send_adl( struct im_connection *ic );
    40 
    41 int msn_ns_write( struct im_connection *ic, int fd, const char *fmt, ... )
     33static int msn_ns_command( gpointer data, char **cmd, int num_parts );
     34static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts );
     35
     36static void msn_auth_got_passport_token( struct msn_auth_data *mad );
     37static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name );
     38
     39gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond )
    4240{
    43         struct msn_data *md = ic->proto_data;
    44         va_list params;
    45         char *out;
    46         size_t len;
    47         int st;
    48        
    49         va_start( params, fmt );
    50         out = g_strdup_vprintf( fmt, params );
    51         va_end( params );
    52        
    53         if( fd < 0 )
    54                 fd = md->ns->fd;
    55        
    56         if( getenv( "BITLBEE_DEBUG" ) )
    57                 fprintf( stderr, "->NS%d:%s", fd, out );
    58        
    59         len = strlen( out );
    60         st = write( fd, out, len );
    61         g_free( out );
    62         if( st != len )
    63         {
    64                 imcb_error( ic, "Short write() to main server" );
    65                 imc_logout( ic, TRUE );
    66                 return 0;
    67         }
    68        
    69         return 1;
    70 }
    71 
    72 gboolean msn_ns_connect( struct im_connection *ic, struct msn_handler_data *handler, const char *host, int port )
    73 {
    74         if( handler->fd >= 0 )
    75                 closesocket( handler->fd );
    76        
    77         handler->exec_command = msn_ns_command;
    78         handler->exec_message = msn_ns_message;
    79         handler->data = ic;
    80         handler->fd = proxy_connect( host, port, msn_ns_connected, handler );
    81         if( handler->fd < 0 )
     41        struct im_connection *ic = data;
     42        struct msn_data *md;
     43        char s[1024];
     44       
     45        if( !g_slist_find( msn_connections, ic ) )
     46                return FALSE;
     47       
     48        if( source == -1 )
    8249        {
    8350                imcb_error( ic, "Could not connect to server" );
     
    8653        }
    8754       
    88         return TRUE;
    89 }
    90 
    91 static gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond )
    92 {
    93         struct msn_handler_data *handler = data;
    94         struct im_connection *ic = handler->data;
    95         struct msn_data *md;
    96        
    97         if( !g_slist_find( msn_connections, ic ) )
    98                 return FALSE;
    99        
    10055        md = ic->proto_data;
    10156       
    102         if( source == -1 )
    103         {
    104                 imcb_error( ic, "Could not connect to server" );
    105                 imc_logout( ic, TRUE );
    106                 return FALSE;
    107         }
    108        
    109         g_free( handler->rxq );
    110         handler->rxlen = 0;
    111         handler->rxq = g_new0( char, 1 );
    112        
    113         if( msn_ns_write( ic, source, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER ) )
    114         {
    115                 handler->inpa = b_input_add( handler->fd, B_EV_IO_READ, msn_ns_callback, handler );
     57        if( !md->handler )
     58        {
     59                md->handler = g_new0( struct msn_handler_data, 1 );
     60                md->handler->data = ic;
     61                md->handler->exec_command = msn_ns_command;
     62                md->handler->exec_message = msn_ns_message;
     63        }
     64        else
     65        {
     66                if( md->handler->rxq )
     67                        g_free( md->handler->rxq );
     68               
     69                md->handler->rxlen = 0;
     70        }
     71       
     72        md->handler->fd = md->fd;
     73        md->handler->rxq = g_new0( char, 1 );
     74       
     75        g_snprintf( s, sizeof( s ), "VER %d MSNP8 CVR0\r\n", ++md->trId );
     76        if( msn_write( ic, s, strlen( s ) ) )
     77        {
     78                ic->inpa = b_input_add( md->fd, B_EV_IO_READ, msn_ns_callback, ic );
    11679                imcb_log( ic, "Connected to server, waiting for reply" );
    11780        }
     
    12083}
    12184
    122 void msn_ns_close( struct msn_handler_data *handler )
    123 {
    124         if( handler->fd >= 0 )
    125         {
    126                 closesocket( handler->fd );
    127                 b_event_remove( handler->inpa );
    128         }
    129        
    130         handler->fd = handler->inpa = -1;
    131         g_free( handler->rxq );
    132         g_free( handler->cmd_text );
    133        
    134         handler->rxlen = 0;
    135         handler->rxq = NULL;
    136         handler->cmd_text = NULL;
    137 }
    138 
    13985static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond )
    14086{
    141         struct msn_handler_data *handler = data;
    142         struct im_connection *ic = handler->data;
    143        
    144         if( msn_handler( handler ) == -1 ) /* Don't do this on ret == 0, it's already done then. */
     87        struct im_connection *ic = data;
     88        struct msn_data *md = ic->proto_data;
     89       
     90        if( msn_handler( md->handler ) == -1 ) /* Don't do this on ret == 0, it's already done then. */
    14591        {
    14692                imcb_error( ic, "Error while reading from server" );
     
    15399}
    154100
    155 static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num_parts )
     101static int msn_ns_command( gpointer data, char **cmd, int num_parts )
    156102{
    157         struct im_connection *ic = handler->data;
     103        struct im_connection *ic = data;
    158104        struct msn_data *md = ic->proto_data;
     105        char buf[1024];
    159106       
    160107        if( num_parts == 0 )
     
    166113        if( strcmp( cmd[0], "VER" ) == 0 )
    167114        {
    168                 if( cmd[2] && strncmp( cmd[2], MSNP_VER, 5 ) != 0 )
     115                if( cmd[2] && strncmp( cmd[2], "MSNP8", 5 ) != 0 )
    169116                {
    170117                        imcb_error( ic, "Unsupported protocol" );
     
    173120                }
    174121               
    175                 return( msn_ns_write( ic, handler->fd, "CVR %d 0x0409 mac 10.2.0 ppc macmsgs 3.5.1 macmsgs %s\r\n",
    176                                       ++md->trId, ic->acc->user ) );
     122                g_snprintf( buf, sizeof( buf ), "CVR %d 0x0409 mac 10.2.0 ppc macmsgs 3.5.1 macmsgs %s\r\n",
     123                                                ++md->trId, ic->acc->user );
     124                return( msn_write( ic, buf, strlen( buf ) ) );
    177125        }
    178126        else if( strcmp( cmd[0], "CVR" ) == 0 )
    179127        {
    180128                /* We don't give a damn about the information we just received */
    181                 return msn_ns_write( ic, handler->fd, "USR %d SSO I %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 );
     130                return( msn_write( ic, buf, strlen( buf ) ) );
    182131        }
    183132        else if( strcmp( cmd[0], "XFR" ) == 0 )
     
    186135                int port;
    187136               
    188                 if( num_parts >= 6 && strcmp( cmd[2], "NS" ) == 0 )
    189                 {
    190                         b_event_remove( handler->inpa );
    191                         handler->inpa = -1;
     137                if( num_parts == 6 && strcmp( cmd[2], "NS" ) == 0 )
     138                {
     139                        b_event_remove( ic->inpa );
     140                        ic->inpa = 0;
     141                        closesocket( md->fd );
    192142                       
    193143                        server = strchr( cmd[3], ':' );
     
    203153                       
    204154                        imcb_log( ic, "Transferring to other server" );
    205                         return msn_ns_connect( ic, handler, server, port );
    206                 }
    207                 else if( num_parts >= 6 && strcmp( cmd[2], "SB" ) == 0 )
     155                       
     156                        md->fd = proxy_connect( server, port, msn_ns_connected, ic );
     157                }
     158                else if( num_parts == 6 && strcmp( cmd[2], "SB" ) == 0 )
    208159                {
    209160                        struct msn_switchboard *sb;
     
    269220        else if( strcmp( cmd[0], "USR" ) == 0 )
    270221        {
    271                 if( num_parts >= 6 && strcmp( cmd[2], "SSO" ) == 0 &&
    272                     strcmp( cmd[3], "S" ) == 0 )
    273                 {
    274                         g_free( md->pp_policy );
    275                         md->pp_policy = g_strdup( cmd[4] );
    276                         msn_soap_passport_sso_request( ic, cmd[5] );
    277                 }
    278                 else if( strcmp( cmd[2], "OK" ) == 0 )
    279                 {
     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                       
    280239                        imcb_log( ic, "Authenticated, getting buddy list" );
    281                         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 ) ) );
    282243                }
    283244                else
     
    290251        else if( strcmp( cmd[0], "MSG" ) == 0 )
    291252        {
    292                 if( num_parts < 4 )
    293                 {
    294                         imcb_error( ic, "Syntax error" );
    295                         imc_logout( ic, TRUE );
    296                         return( 0 );
    297                 }
    298                
    299                 handler->msglen = atoi( cmd[3] );
    300                
    301                 if( handler->msglen <= 0 )
    302                 {
    303                         imcb_error( ic, "Syntax error" );
    304                         imc_logout( ic, TRUE );
    305                         return( 0 );
    306                 }
    307         }
    308         else if( strcmp( cmd[0], "BLP" ) == 0 )
    309         {
    310                 msn_ns_send_adl_start( ic );
    311                 return msn_ns_finish_login( ic );
    312         }
    313         else if( strcmp( cmd[0], "ADL" ) == 0 )
    314         {
    315                 if( num_parts >= 3 && strcmp( cmd[2], "OK" ) == 0 )
    316                 {
    317                         msn_ns_send_adl( ic );
    318                         return msn_ns_finish_login( ic );
    319                 }
    320                 else if( num_parts >= 3 )
    321                 {
    322                         handler->msglen = atoi( cmd[2] );
    323                 }
    324         }
    325         else if( strcmp( cmd[0], "PRP" ) == 0 )
    326         {
    327                 imcb_connected( ic );
     253                if( num_parts != 4 )
     254                {
     255                        imcb_error( ic, "Syntax error" );
     256                        imc_logout( ic, TRUE );
     257                        return( 0 );
     258                }
     259               
     260                md->handler->msglen = atoi( cmd[3] );
     261               
     262                if( md->handler->msglen <= 0 )
     263                {
     264                        imcb_error( ic, "Syntax error" );
     265                        imc_logout( ic, TRUE );
     266                        return( 0 );
     267                }
     268        }
     269        else if( strcmp( cmd[0], "SYN" ) == 0 )
     270        {
     271                if( num_parts == 5 )
     272                {
     273                        int i, groupcount;
     274                       
     275                        groupcount = atoi( cmd[4] );
     276                        if( groupcount > 0 )
     277                        {
     278                                /* valgrind says this is leaking memory, I'm guessing
     279                                   that this happens during server redirects. */
     280                                if( md->grouplist )
     281                                {
     282                                        for( i = 0; i < md->groupcount; i ++ )
     283                                                g_free( md->grouplist[i] );
     284                                        g_free( md->grouplist );
     285                                }
     286                               
     287                                md->groupcount = groupcount;
     288                                md->grouplist = g_new0( char *, md->groupcount );
     289                        }
     290                       
     291                        md->buddycount = atoi( cmd[3] );
     292                        if( !*cmd[3] || md->buddycount == 0 )
     293                                msn_logged_in( ic );
     294                }
     295                else
     296                {
     297                        /* Hrrm... This SYN reply doesn't really look like something we expected.
     298                           Let's assume everything is okay. */
     299                       
     300                        msn_logged_in( ic );
     301                }
     302        }
     303        else if( strcmp( cmd[0], "LST" ) == 0 )
     304        {
     305                int list;
     306               
     307                if( num_parts != 4 && num_parts != 5 )
     308                {
     309                        imcb_error( ic, "Syntax error" );
     310                        imc_logout( ic, TRUE );
     311                        return( 0 );
     312                }
     313               
     314                http_decode( cmd[2] );
     315                list = atoi( cmd[3] );
     316               
     317                if( list & 1 ) /* FL */
     318                {
     319                        char *group = NULL;
     320                        int num;
     321                       
     322                        if( cmd[4] != NULL && sscanf( cmd[4], "%d", &num ) == 1 && num < md->groupcount )
     323                                group = md->grouplist[num];
     324                       
     325                        imcb_add_buddy( ic, cmd[1], group );
     326                        imcb_rename_buddy( ic, cmd[1], cmd[2] );
     327                }
     328                if( list & 2 ) /* AL */
     329                {
     330                        ic->permit = g_slist_append( ic->permit, g_strdup( cmd[1] ) );
     331                }
     332                if( list & 4 ) /* BL */
     333                {
     334                        ic->deny = g_slist_append( ic->deny, g_strdup( cmd[1] ) );
     335                }
     336                if( list & 8 ) /* RL */
     337                {
     338                        if( ( list & 6 ) == 0 )
     339                                msn_buddy_ask( ic, cmd[1], cmd[2] );
     340                }
     341               
     342                if( --md->buddycount == 0 )
     343                {
     344                        if( ic->flags & OPT_LOGGED_IN )
     345                        {
     346                                imcb_log( ic, "Successfully transferred to different server" );
     347                                g_snprintf( buf, sizeof( buf ), "CHG %d %s %d\r\n", ++md->trId, md->away_state->code, 0 );
     348                                return( msn_write( ic, buf, strlen( buf ) ) );
     349                        }
     350                        else
     351                        {
     352                                msn_logged_in( ic );
     353                        }
     354                }
     355        }
     356        else if( strcmp( cmd[0], "LSG" ) == 0 )
     357        {
     358                int num;
     359               
     360                if( num_parts != 4 )
     361                {
     362                        imcb_error( ic, "Syntax error" );
     363                        imc_logout( ic, TRUE );
     364                        return( 0 );
     365                }
     366               
     367                http_decode( cmd[2] );
     368                num = atoi( cmd[1] );
     369               
     370                if( num < md->groupcount )
     371                        md->grouplist[num] = g_strdup( cmd[2] );
    328372        }
    329373        else if( strcmp( cmd[0], "CHL" ) == 0 )
    330374        {
    331                 char *resp;
    332                 int st;
    333                
    334                 if( num_parts < 3 )
    335                 {
    336                         imcb_error( ic, "Syntax error" );
    337                         imc_logout( ic, TRUE );
    338                         return( 0 );
    339                 }
    340                
    341                 resp = msn_p11_challenge( cmd[2] );
    342                
    343                 st =  msn_ns_write( ic, -1, "QRY %d %s %zd\r\n%s",
    344                                     ++md->trId, MSNP11_PROD_ID,
    345                                     strlen( resp ), resp );
    346                 g_free( resp );
    347                 return st;
     375                md5_state_t state;
     376                md5_byte_t digest[16];
     377                int i;
     378               
     379                if( num_parts != 3 )
     380                {
     381                        imcb_error( ic, "Syntax error" );
     382                        imc_logout( ic, TRUE );
     383                        return( 0 );
     384                }
     385               
     386                md5_init( &state );
     387                md5_append( &state, (const md5_byte_t *) cmd[2], strlen( cmd[2] ) );
     388                md5_append( &state, (const md5_byte_t *) QRY_CODE, strlen( QRY_CODE ) );
     389                md5_finish( &state, digest );
     390               
     391                g_snprintf( buf, sizeof( buf ), "QRY %d %s %d\r\n", ++md->trId, QRY_NAME, 32 );
     392                for( i = 0; i < 16; i ++ )
     393                        g_snprintf( buf + strlen( buf ), 3, "%02x", digest[i] );
     394               
     395                return( msn_write( ic, buf, strlen( buf ) ) );
    348396        }
    349397        else if( strcmp( cmd[0], "ILN" ) == 0 )
     
    351399                const struct msn_away_state *st;
    352400               
    353                 if( num_parts < 6 )
    354                 {
    355                         imcb_error( ic, "Syntax error" );
    356                         imc_logout( ic, TRUE );
    357                         return( 0 );
    358                 }
    359                
    360                 http_decode( cmd[5] );
    361                 imcb_rename_buddy( ic, cmd[3], cmd[5] );
     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] );
    362410               
    363411                st = msn_away_state_by_code( cmd[2] );
     
    384432        {
    385433                const struct msn_away_state *st;
    386                 int cap;
    387                
    388                 if( num_parts < 6 )
    389                 {
    390                         imcb_error( ic, "Syntax error" );
    391                         imc_logout( ic, TRUE );
    392                         return( 0 );
    393                 }
    394                
    395                 http_decode( cmd[4] );
    396                 cap = atoi( cmd[5] );
    397                 imcb_rename_buddy( ic, cmd[2], cmd[4] );
     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] );
    398444               
    399445                st = msn_away_state_by_code( cmd[1] );
     
    405451               
    406452                imcb_buddy_status( ic, cmd[2], OPT_LOGGED_IN |
    407                                    ( st != msn_away_state_list ? OPT_AWAY : 0 ) |
    408                                    ( cap & 1 ? OPT_MOBILE : 0 ),
     453                                   ( st != msn_away_state_list ? OPT_AWAY : 0 ),
    409454                                   st->name, NULL );
    410455               
     
    417462                int session, port;
    418463               
    419                 if( num_parts < 7 )
     464                if( num_parts != 7 )
    420465                {
    421466                        imcb_error( ic, "Syntax error" );
     
    459504                }
    460505        }
     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        }
    461546        else if( strcmp( cmd[0], "OUT" ) == 0 )
    462547        {
     
    480565                return( 0 );
    481566        }
     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
    482601        else if( strcmp( cmd[0], "IPG" ) == 0 )
    483602        {
    484603                imcb_error( ic, "Received IPG command, we don't handle them yet." );
    485604               
    486                 handler->msglen = atoi( cmd[1] );
    487                
    488                 if( handler->msglen <= 0 )
    489                 {
    490                         imcb_error( ic, "Syntax error" );
    491                         imc_logout( ic, TRUE );
    492                         return( 0 );
    493                 }
    494         }
    495 #if 0
     605                md->handler->msglen = atoi( cmd[1] );
     606               
     607                if( md->handler->msglen <= 0 )
     608                {
     609                        imcb_error( ic, "Syntax error" );
     610                        imc_logout( ic, TRUE );
     611                        return( 0 );
     612                }
     613        }
    496614        else if( strcmp( cmd[0], "ADG" ) == 0 )
    497615        {
     
    538656                }
    539657        }
    540 #endif
    541         else if( strcmp( cmd[0], "GCF" ) == 0 )
    542         {
    543                 /* Coming up is cmd[2] bytes of stuff we're supposed to
    544                    censore. Meh. */
    545                 handler->msglen = atoi( cmd[2] );
    546         }
    547         else if( strcmp( cmd[0], "UBX" ) == 0 )
    548         {
    549                 /* Status message. */
    550                 if( num_parts >= 4 )
    551                         handler->msglen = atoi( cmd[3] );
    552         }
    553         else if( strcmp( cmd[0], "NOT" ) == 0 )
    554         {
    555                 /* Some kind of notification, poorly documented but
    556                    apparently used to announce address book changes. */
    557                 if( num_parts >= 2 )
    558                         handler->msglen = atoi( cmd[1] );
    559         }
    560658        else if( isdigit( cmd[0][0] ) )
    561659        {
     
    570668                        return( 0 );
    571669                }
    572                
    573                 /* Oh yes, errors can have payloads too now. Discard them for now. */
    574                 if( num_parts >= 3 )
    575                         handler->msglen = atoi( cmd[2] );
    576670        }
    577671        else
     
    583677}
    584678
    585 static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts )
     679static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts )
    586680{
    587         struct im_connection *ic = handler->data;
     681        struct im_connection *ic = data;
    588682        char *body;
    589683        int blen = 0;
     
    671765                }
    672766        }
    673         else if( strcmp( cmd[0], "UBX" ) == 0 )
    674         {
    675                 struct xt_node *psm;
    676                 char *psm_text = NULL;
    677                
    678                 psm = xt_from_string( msg );
    679                 if( psm && strcmp( psm->name, "Data" ) == 0 &&
    680                     ( psm = xt_find_node( psm->children, "PSM" ) ) )
    681                         psm_text = psm->text;
    682                
    683                 imcb_buddy_status_msg( ic, cmd[1], psm_text );
    684                 xt_free_node( psm );
    685         }
    686         else if( strcmp( cmd[0], "ADL" ) == 0 )
    687         {
    688                 struct xt_node *adl, *d, *c;
    689                
    690                 if( !( adl = xt_from_string( msg ) ) )
    691                         return 1;
    692                
    693                 for( d = adl->children; d; d = d->next )
    694                 {
    695                         char *dn;
    696                         if( strcmp( d->name, "d" ) != 0 ||
    697                             ( dn = xt_find_attr( d, "n" ) ) == NULL )
    698                                 continue;
    699                         for( c = d->children; c; c = c->next )
    700                         {
    701                                 bee_user_t *bu;
    702                                 struct msn_buddy_data *bd;
    703                                 char *cn, *handle, *f, *l;
    704                                 int flags;
    705                                
    706                                 if( strcmp( c->name, "c" ) != 0 ||
    707                                     ( l = xt_find_attr( c, "l" ) ) == NULL ||
    708                                     ( cn = xt_find_attr( c, "n" ) ) == NULL )
    709                                         continue;
    710                                
    711                                 handle = g_strdup_printf( "%s@%s", cn, dn );
    712                                 if( !( ( bu = bee_user_by_handle( ic->bee, ic, handle ) ) ||
    713                                        ( bu = bee_user_new( ic->bee, ic, handle, 0 ) ) ) )
    714                                 {
    715                                         g_free( handle );
    716                                         continue;
    717                                 }
    718                                 g_free( handle );
    719                                 bd = bu->data;
    720                                
    721                                 if( ( f = xt_find_attr( c, "f" ) ) )
    722                                 {
    723                                         http_decode( f );
    724                                         imcb_rename_buddy( ic, bu->handle, f );
    725                                 }
    726                                
    727                                 flags = atoi( l ) & 15;
    728                                 if( bd->flags != flags )
    729                                 {
    730                                         bd->flags = flags;
    731                                         msn_buddy_ask( bu );
    732                                 }
    733                         }
    734                 }
    735         }
    736767       
    737768        return( 1 );
    738769}
    739770
    740 void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error )
     771static void msn_auth_got_passport_token( struct msn_auth_data *mad )
    741772{
     773        struct im_connection *ic = mad->data;
    742774        struct msn_data *md;
    743775       
     
    747779       
    748780        md = ic->proto_data;
    749        
    750         if( token )
    751         {
    752                 msn_ns_write( ic, -1, "USR %d SSO S %s %s\r\n", ++md->trId, md->tokens[0], token );
     781        if( mad->token )
     782        {
     783                char buf[1024];
     784               
     785                g_snprintf( buf, sizeof( buf ), "USR %d TWN S %s\r\n", ++md->trId, mad->token );
     786                msn_write( ic, buf, strlen( buf ) );
    753787        }
    754788        else
    755789        {
    756                 imcb_error( ic, "Error during Passport authentication: %s", error );
     790                imcb_error( ic, "Error during Passport authentication: %s", mad->error );
    757791                imc_logout( ic, TRUE );
    758792        }
    759793}
    760794
    761 void msn_auth_got_contact_list( struct im_connection *ic )
     795static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name )
    762796{
    763         struct msn_data *md;
    764        
    765         /* Dead connection? */
    766         if( g_slist_find( msn_connections, ic ) == NULL )
    767                 return;
    768        
    769         md = ic->proto_data;
    770         msn_ns_write( ic, -1, "BLP %d %s\r\n", ++md->trId, "BL" );
     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        }
    771838}
    772 
    773 static gboolean msn_ns_send_adl_1( gpointer key, gpointer value, gpointer data )
    774 {
    775         struct xt_node *adl = data, *d, *c;
    776         struct bee_user *bu = value;
    777         struct msn_buddy_data *bd = bu->data;
    778         struct msn_data *md = bu->ic->proto_data;
    779         char handle[strlen(bu->handle)];
    780         char *domain;
    781         char l[4];
    782        
    783         if( ( bd->flags & 7 ) == 0 || ( bd->flags & MSN_BUDDY_ADL_SYNCED ) )
    784                 return FALSE;
    785        
    786         strcpy( handle, bu->handle );
    787         if( ( domain = strchr( handle, '@' ) ) == NULL ) /* WTF */
    788                 return FALSE;
    789         *domain = '\0';
    790         domain ++;
    791        
    792         if( ( d = adl->children ) == NULL ||
    793             g_strcasecmp( xt_find_attr( d, "n" ), domain ) != 0 )
    794         {
    795                 d = xt_new_node( "d", NULL, NULL );
    796                 xt_add_attr( d, "n", domain );
    797                 xt_insert_child( adl, d );
    798         }
    799        
    800         g_snprintf( l, sizeof( l ), "%d", bd->flags & 7 );
    801         c = xt_new_node( "c", NULL, NULL );
    802         xt_add_attr( c, "n", handle );
    803         xt_add_attr( c, "l", l );
    804         xt_add_attr( c, "t", "1" ); /* 1 means normal, 4 means mobile? */
    805         xt_insert_child( d, c );
    806        
    807         /* Do this in batches of 100. */
    808         bd->flags |= MSN_BUDDY_ADL_SYNCED;
    809         return (--md->adl_todo % 140) == 0;
    810 }
    811 
    812 static void msn_ns_send_adl( struct im_connection *ic )
    813 {
    814         struct xt_node *adl;
    815         struct msn_data *md = ic->proto_data;
    816         char *adls;
    817        
    818         adl = xt_new_node( "ml", NULL, NULL );
    819         xt_add_attr( adl, "l", "1" );
    820         g_tree_foreach( md->domaintree, msn_ns_send_adl_1, adl );
    821         if( adl->children == NULL )
    822         {
    823                 /* This tells the caller that we're done now. */
    824                 md->adl_todo = -1;
    825                 xt_free_node( adl );
    826                 return;
    827         }
    828        
    829         adls = xt_to_string( adl );
    830         msn_ns_write( ic, -1, "ADL %d %zd\r\n%s", ++md->trId, strlen( adls ), adls );
    831         g_free( adls );
    832 }
    833 
    834 static void msn_ns_send_adl_start( struct im_connection *ic )
    835 {
    836         struct msn_data *md;
    837         GSList *l;
    838        
    839         /* Dead connection? */
    840         if( g_slist_find( msn_connections, ic ) == NULL )
    841                 return;
    842        
    843         md = ic->proto_data;
    844         md->adl_todo = 0;
    845         for( l = ic->bee->users; l; l = l->next )
    846         {
    847                 bee_user_t *bu = l->data;
    848                 struct msn_buddy_data *bd = bu->data;
    849                
    850                 if( bu->ic != ic || ( bd->flags & 7 ) == 0 )
    851                         continue;
    852                
    853                 bd->flags &= ~MSN_BUDDY_ADL_SYNCED;
    854                 md->adl_todo++;
    855         }
    856        
    857         msn_ns_send_adl( ic );
    858 }
    859 
    860 int msn_ns_finish_login( struct im_connection *ic )
    861 {
    862         struct msn_data *md = ic->proto_data;
    863        
    864         if( ic->flags & OPT_LOGGED_IN )
    865                 return 1;
    866        
    867         if( md->adl_todo < 0 )
    868                 md->flags |= MSN_DONE_ADL;
    869        
    870         if( ( md->flags & MSN_DONE_ADL ) && ( md->flags & MSN_GOT_PROFILE ) )
    871                 return msn_ns_set_display_name( ic, set_getstr( &ic->acc->set, "display_name" ) );
    872         else
    873                 return 1;
    874 }
  • protocols/msn/sb.c

    r508588a r3ad8036  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2010 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2005 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    2727#include "nogaim.h"
    2828#include "msn.h"
     29#include "passport.h"
    2930#include "md5.h"
    30 #include "soap.h"
    3131#include "invitation.h"
    3232
    3333static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond );
    34 static int msn_sb_command( struct msn_handler_data *handler, char **cmd, int num_parts );
    35 static int msn_sb_message( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts );
    36 
    37 int msn_sb_write( struct msn_switchboard *sb, const char *fmt, ... )
    38 {
    39         va_list params;
    40         char *out;
    41         size_t len;
     34static int msn_sb_command( gpointer data, char **cmd, int num_parts );
     35static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts );
     36
     37int msn_sb_write( struct msn_switchboard *sb, char *s, int len )
     38{
    4239        int st;
    4340       
    44         va_start( params, fmt );
    45         out = g_strdup_vprintf( fmt, params );
    46         va_end( params );
    47        
    48         if( getenv( "BITLBEE_DEBUG" ) )
    49                 fprintf( stderr, "->SB%d:%s", sb->fd, out );
    50        
    51         len = strlen( out );
    52         st = write( sb->fd, out, len );
    53         g_free( out );
     41        st = write( sb->fd, s, len );
    5442        if( st != len )
    5543        {
    5644                msn_sb_destroy( sb );
    57                 return 0;
    58         }
    59        
    60         return 1;
     45                return( 0 );
     46        }
     47       
     48        return( 1 );
    6149}
    6250
     
    6553        struct msn_data *md = ic->proto_data;
    6654        struct msn_switchboard *sb;
     55        char buf[1024];
    6756
    6857        /* FIXME: *CHECK* the reliability of using spare sb's! */
     
    7261               
    7362                sb->who = g_strdup( m->who );
    74                 if( msn_sb_write( sb, "CAL %d %s\r\n", ++sb->trId, m->who ) )
     63                g_snprintf( buf, sizeof( buf ), "CAL %d %s\r\n", ++sb->trId, m->who );
     64                if( msn_sb_write( sb, buf, strlen( buf ) ) )
    7565                {
    7666                        /* He/She should join the switchboard soon, let's queue the message. */
     
    8373       
    8474        /* If we reach this line, there was no spare switchboard, so let's make one. */
    85         if( !msn_ns_write( ic, -1, "XFR %d SB\r\n", ++md->trId ) )
     75        g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId );
     76        if( !msn_write( ic, buf, strlen( buf ) ) )
    8677        {
    8778                g_free( m->who );
     
    174165        if( sb->ready )
    175166        {
    176                 char *buf;
     167                char *packet, *buf;
    177168                int i, j;
    178169               
     
    210201               
    211202                /* Build the final packet (MSG command + the message). */
    212                 if( msn_sb_write( sb, "MSG %d N %d\r\n%s", ++sb->trId, i, buf ) )
    213                 {
    214                         g_free( buf );
    215                         return 1;
     203                packet = g_strdup_printf( "MSG %d N %d\r\n%s", ++sb->trId, i, buf );
     204                g_free( buf );
     205                if( msn_sb_write( sb, packet, strlen( packet ) ) )
     206                {
     207                        g_free( packet );
     208                        return( 1 );
    216209                }
    217210                else
    218211                {
    219                         g_free( buf );
    220                         return 0;
     212                        g_free( packet );
     213                        return( 0 );
    221214                }
    222215        }
     
    333326                g_snprintf( buf, sizeof( buf ), "ANS %d %s %s %d\r\n", ++sb->trId, ic->acc->user, sb->key, sb->session );
    334327       
    335         if( msn_sb_write( sb, "%s", buf ) )
     328        if( msn_sb_write( sb, buf, strlen( buf ) ) )
    336329                sb->inp = b_input_add( sb->fd, B_EV_IO_READ, msn_sb_callback, sb );
    337330        else
     
    353346        {
    354347                time_t now = time( NULL );
     348                char buf[1024];
    355349               
    356350                if( now - md->first_sb_failure > 600 )
     
    384378                debug( "Moved queued messages back to the main queue, "
    385379                       "creating a new switchboard to retry." );
    386                 if( !msn_ns_write( ic, -1, "XFR %d SB\r\n", ++md->trId ) )
     380                g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId );
     381                if( !msn_write( ic, buf, strlen( buf ) ) )
    387382                        return FALSE;
    388383        }
     
    392387}
    393388
    394 static int msn_sb_command( struct msn_handler_data *handler, char **cmd, int num_parts )
    395 {
    396         struct msn_switchboard *sb = handler->data;
     389static int msn_sb_command( gpointer data, char **cmd, int num_parts )
     390{
     391        struct msn_switchboard *sb = data;
    397392        struct im_connection *ic = sb->ic;
     393        char buf[1024];
    398394       
    399395        if( !num_parts )
     
    411407        else if( strcmp( cmd[0], "USR" ) == 0 )
    412408        {
    413                 if( num_parts < 5 )
     409                if( num_parts != 5 )
    414410                {
    415411                        msn_sb_destroy( sb );
     
    424420               
    425421                if( sb->who )
    426                         return msn_sb_write( sb, "CAL %d %s\r\n", ++sb->trId, sb->who );
     422                {
     423                        g_snprintf( buf, sizeof( buf ), "CAL %d %s\r\n", ++sb->trId, sb->who );
     424                        return( msn_sb_write( sb, buf, strlen( buf ) ) );
     425                }
    427426                else
     427                {
    428428                        debug( "Just created a switchboard, but I don't know what to do with it." );
     429                }
    429430        }
    430431        else if( strcmp( cmd[0], "IRO" ) == 0 )
     
    432433                int num, tot;
    433434               
    434                 if( num_parts < 6 )
     435                if( num_parts != 6 )
    435436                {
    436437                        msn_sb_destroy( sb );
     
    469470        else if( strcmp( cmd[0], "ANS" ) == 0 )
    470471        {
    471                 if( num_parts < 3 )
     472                if( num_parts != 3 )
    472473                {
    473474                        msn_sb_destroy( sb );
     
    488489        else if( strcmp( cmd[0], "CAL" ) == 0 )
    489490        {
    490                 if( num_parts < 4 || !isdigit( cmd[3][0] ) )
     491                if( num_parts != 4 || !isdigit( cmd[3][0] ) )
    491492                {
    492493                        msn_sb_destroy( sb );
     
    498499        else if( strcmp( cmd[0], "JOI" ) == 0 )
    499500        {
    500                 if( num_parts < 3 )
     501                if( num_parts != 3 )
    501502                {
    502503                        msn_sb_destroy( sb );
     
    559560        else if( strcmp( cmd[0], "MSG" ) == 0 )
    560561        {
    561                 if( num_parts < 4 )
     562                if( num_parts != 4 )
    562563                {
    563564                        msn_sb_destroy( sb );
     
    624625                const struct msn_status_code *err = msn_status_by_number( num );
    625626               
    626                 /* If the person is offline, send an offline message instead,
    627                    and don't report an error. */
    628                 if( num == 217 )
    629                         msn_soap_oim_send_queue( ic, &sb->msgq );
    630                 else
    631                         imcb_error( ic, "Error reported by switchboard server: %s", err->text );
     627                imcb_error( ic, "Error reported by switchboard server: %s", err->text );
    632628               
    633629                if( err->flags & STATUS_SB_FATAL )
     
    665661}
    666662
    667 static int msn_sb_message( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts )
    668 {
    669         struct msn_switchboard *sb = handler->data;
     663static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts )
     664{
     665        struct msn_switchboard *sb = data;
    670666        struct im_connection *ic = sb->ic;
    671667        char *body;
     
    745741                else if( g_strncasecmp( ct, "application/x-msnmsgrp2p", 24 ) == 0 )
    746742                {
    747                         /* Not currently implemented. Don't warn about it since
    748                            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 );
    749745                        g_free( ct );
    750746                }
  • protocols/msn/tables.c

    r508588a r3ad8036  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2010 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2004 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    8383        { 230, "Cannot remove that group",                              0 },
    8484        { 231, "Invalid group",                                         0 },
    85         { 240, "ADL/RML command with corrupted payload",                STATUS_FATAL },
    86         { 241, "ADL/RML command with invalid modification",             0 },
    8785        { 280, "Switchboard failed",                                    STATUS_SB_FATAL },
    8886        { 281, "Transfer to switchboard failed",                        0 },
  • protocols/nogaim.c

    r508588a r3ad8036  
    252252                serv_got_crap( ic, "Error: %s", text );
    253253        else
    254                 serv_got_crap( ic, "Login error: %s", text );
     254                serv_got_crap( ic, "Couldn't log in: %s", text );
    255255       
    256256        g_free( text );
     
    325325       
    326326        imcb_log( ic, "Signing off.." );
     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;
    327335       
    328336        for( l = bee->users; l; )
     
    336344                l = next;
    337345        }
    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

    r508588a r3ad8036  
    200200           this info via imcb_log(). Implementing these are optional. */
    201201        void (* get_info)       (struct im_connection *, char *who);
    202         /* set_my_name is *DEPRECATED*, not used by the UI anymore. Use the
    203            display_name setting instead. */
    204202        void (* set_my_name)    (struct im_connection *, char *name);
    205203        void (* set_name)       (struct im_connection *, char *who, char *name);
  • protocols/oscar/ssi.c

    r508588a r3ad8036  
    415415                if (!parentgroup) {
    416416                        char *newgroup;
    417                         newgroup = (char*)g_malloc(strlen("Unknown")+1);
     417                        newgroup = (char*)g_malloc(strlen("Unknown")*sizeof(char));
    418418                        strcpy(newgroup, "Unknown");
    419419                        aim_ssi_addgroups(sess, conn, &newgroup, 1);
  • protocols/purple/purple.c

    r508588a r3ad8036  
    8080        char help_title[64];
    8181        GString *help;
    82         static gboolean dir_fixed = FALSE;
    83        
    84         /* Layer violation coming up: Making an exception for libpurple here.
    85            Dig in the IRC state a bit to get a username. Ideally we should
    86            check if s/he identified but this info doesn't seem *that* important.
    87            It's just that fecking libpurple can't *not* store this shit.
    88            
    89            Remember that libpurple is not really meant to be used on public
    90            servers anyway! */
    91         if( !dir_fixed )
    92         {
    93                 irc_t *irc = acc->bee->ui_data;
    94                 char *dir;
    95                
    96                 dir = g_strdup_printf( "%s/purple/%s", global.conf->configdir, irc->user->nick );
    97                 purple_util_set_user_dir( dir );
    98                 g_free( dir );
    99                
    100                 purple_blist_load();
    101                 purple_prefs_load();
    102                 dir_fixed = TRUE;
    103         }
    10482       
    10583        help = g_string_new( "" );
     
    276254        PurpleAccount *pa;
    277255       
    278         if( ( local_bee != NULL && local_bee != acc->bee ) ||
    279             ( global.conf->runmode == RUNMODE_DAEMON && !getenv( "BITLBEE_DEBUG" ) ) )
     256        if( local_bee != NULL && local_bee != acc->bee )
    280257        {
    281258                imcb_error( ic,  "Daemon mode detected. Do *not* try to use libpurple in daemon mode! "
     
    374351        account_t *acc = set->data;
    375352        struct im_connection *ic = acc->ic;
    376        
    377         if( ic )
    378                 imcb_log( ic, "Changing display_name not currently supported with libpurple!" );
    379353       
    380354        return NULL;
     
    543517}
    544518
    545 struct groupchat *purple_chat_join( struct im_connection *ic, const char *room, const char *nick, const char *password, set_t **sets )
     519struct groupchat *purple_chat_join( struct im_connection *ic, const char *room, const char *nick, const char *password )
    546520{
    547521        PurpleAccount *pa = ic->proto_data;
     
    11581132        GList *prots;
    11591133        GString *help;
    1160         char *dir;
    11611134       
    11621135        if( B_EV_IO_READ != PURPLE_INPUT_READ ||
     
    11671140        }
    11681141       
    1169         dir = g_strdup_printf( "%s/purple", global.conf->configdir );
    1170         purple_util_set_user_dir( dir );
    1171         g_free( dir );
    1172        
     1142        purple_util_set_user_dir( "/tmp" );
    11731143        purple_debug_set_enabled( FALSE );
    11741144        purple_core_set_ui_ops( &bee_core_uiops );
     
    11811151        }
    11821152       
     1153        /* This seems like stateful shit we don't want... */
    11831154        purple_set_blist( purple_blist_new() );
     1155        purple_blist_load();
     1156       
     1157        /* Meh? */
     1158        purple_prefs_load();
    11841159       
    11851160        /* No, really. So far there were ui_ops for everything, but now suddenly
     
    12461221       
    12471222        g_string_append( help, "\n\nFor used protocols, more information about available "
    1248                          "settings can be found using \x02help purple <protocol name>\x02 "
    1249                          "(create an account using that protocol first!)" );
     1223                         "settings can be found using \x02help purple <protocol name>\x02" );
    12501224       
    12511225        /* Add a simple dynamically-generated help item listing all
  • protocols/twitter/twitter.c

    r508588a r3ad8036  
    2929#include "url.h"
    3030
    31 #define twitter_msg( ic, fmt... ) \
    32         do {                                                        \
    33                 struct twitter_data *td = ic->proto_data;           \
    34                 if( td->home_timeline_gc )                          \
    35                         imcb_chat_log( td->home_timeline_gc, fmt ); \
    36                 else                                                \
    37                         imcb_log( ic, fmt );                        \
    38         } while( 0 );
    39                
    40 
    4131/**
    4232 * Main loop function
     
    446436                if( id )
    447437                        twitter_status_destroy( ic, id );
    448                 else
    449                         twitter_msg( ic, "Could not undo last action" );
    450438               
    451439                g_free( cmds );
     
    479467                if( id )
    480468                        twitter_status_retweet( ic, id );
    481                 else
    482                         twitter_msg( ic, "User `%s' does not exist or didn't "
    483                                          "post any statuses recently", cmd[1] );
    484469               
    485470                g_free( cmds );
  • root_commands.c

    r508588a r3ad8036  
    12931293{
    12941294        int last = set_getint( &irc->b->set, "last_version" );
    1295         char s[16], *msg;
     1295        GString *msg = g_string_new( "" );
     1296        char s[16];
    12961297       
    12971298        if( last >= BITLBEE_VERSION_CODE )
    12981299                return;
    12991300       
    1300         msg = help_get_whatsnew( &(global.help), last );
    1301        
    1302         if( msg )
     1301        if( last < 0x010206 ) /* 1.2.6 */
     1302        {
     1303                g_string_append( msg,
     1304                        "Twitter support. See \x02help account add twitter\x02.\n" );
     1305        }
     1306        if( last < 0x010300 ) /* 1.3dev */
     1307        {
     1308                g_string_append( msg,
     1309                        "Support for multiple configurable control channels, "
     1310                        "each with a subset of your contact list. See "
     1311                        "\x02help channels\x02 for more information.\n"
     1312                        "File transfer support for some protocols (more if "
     1313                        "you use libpurple). Just /DCC SEND stuff. Incoming "
     1314                        "files also become DCC transfers.\n"
     1315                        "Many more things, briefly described in "
     1316                        "\x02help news1.3\x02.\n" );
     1317        }
     1318       
     1319        if( msg->len > 0 )
    13031320                irc_usermsg( irc, "%s: This seems to be your first time using this "
    13041321                                  "this version of BitlBee. Here's a list of new "
    13051322                                  "features you may like to know about:\n\n%s\n",
    1306                                   irc->user->nick, msg );
    1307        
    1308         g_free( msg );
    1309        
     1323                                  irc->user->nick, msg->str );
     1324       
     1325        g_string_free( msg, TRUE );
    13101326        g_snprintf( s, sizeof( s ), "%d", BITLBEE_VERSION_CODE );
    13111327        set_setstr( &irc->b->set, "last_version", s );
  • sock.h

    r508588a r3ad8036  
    1111#define sock_make_blocking(fd) fcntl(fd, F_SETFL, 0)
    1212#define sockerr_again() (errno == EINPROGRESS || errno == EINTR)
     13#ifndef EVENTS_LIBEVENT
     14#define closesocket(a) close(a)
     15#else
    1316void closesocket( int fd );
     17#endif
    1418#else
    1519# include <winsock2.h>
  • storage_xml.c

    r508588a r3ad8036  
    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                 }
    332322                set_setstr( xd->current_set_head, xd->current_setting, (char*) text );
    333323                g_free( xd->current_setting );
  • unix.c

    r508588a r3ad8036  
    181181                   doesn't make a copy. Odd. */
    182182               
    183                 i = chdir( old_cwd );
     183                chdir( old_cwd );
    184184                close( global.listen_socket );
    185185               
Note: See TracChangeset for help on using the changeset viewer.