Changeset 5ebff60 for protocols/msn


Ignore:
Timestamp:
2015-02-20T22:50:54Z (9 years ago)
Author:
dequis <dx@…>
Branches:
master
Children:
0b9daac, 3d45471, 7733b8c
Parents:
af359b4
git-author:
Indent <please@…> (19-02-15 05:47:20)
git-committer:
dequis <dx@…> (20-02-15 22:50:54)
Message:

Reindent everything to K&R style with tabs

Used uncrustify, with the configuration file in ./doc/uncrustify.cfg

Commit author set to "Indent <please@…>" so that it's easier to
skip while doing git blame.

Location:
protocols/msn
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • protocols/msn/invitation.c

    raf359b4 r5ebff60  
    1313 the Free Software Foundation; either version 2 of the License, or
    1414 (at your option) any later version.
    15  
     15
    1616 This program is distributed in the hope that it will be useful,
    1717 but WITHOUT ANY WARRANTY; without even the implied warranty of
    1818 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1919 GNU General Public License for more details.
    20  
     20
    2121 You should have received a copy of the GNU General Public License with
    2222 the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
     
    3333#undef debug
    3434#endif
    35 #define debug(msg...) log_message( LOGLVL_INFO, msg )
    36 
    37 static void msn_ftp_free( file_transfer_t *file );
    38 static void msn_ftpr_accept( file_transfer_t *file );
    39 static void msn_ftp_finished( file_transfer_t *file );
    40 static void msn_ftp_canceled( file_transfer_t *file, char *reason );
    41 static gboolean msn_ftpr_write_request( file_transfer_t *file );
    42 
    43 static gboolean msn_ftp_connected( gpointer data, gint fd, b_input_condition cond );
    44 static gboolean msn_ftp_read( gpointer data, gint fd, b_input_condition cond );
    45 gboolean msn_ftps_write( file_transfer_t *file, char *buffer, unsigned int len );
     35#define debug(msg ...) log_message(LOGLVL_INFO, msg)
     36
     37static void msn_ftp_free(file_transfer_t *file);
     38static void msn_ftpr_accept(file_transfer_t *file);
     39static void msn_ftp_finished(file_transfer_t *file);
     40static void msn_ftp_canceled(file_transfer_t *file, char *reason);
     41static gboolean msn_ftpr_write_request(file_transfer_t *file);
     42
     43static gboolean msn_ftp_connected(gpointer data, gint fd, b_input_condition cond);
     44static gboolean msn_ftp_read(gpointer data, gint fd, b_input_condition cond);
     45gboolean msn_ftps_write(file_transfer_t *file, char *buffer, unsigned int len);
    4646
    4747/*
    4848 * Vararg wrapper for imcb_file_canceled().
    4949 */
    50 gboolean msn_ftp_abort( file_transfer_t *file, char *format, ... )
    51 {
    52         va_list params;
    53         va_start( params, format );
    54         char error[128];
    55 
    56         if( vsnprintf( error, 128, format, params ) < 0 )
    57                 sprintf( error, "internal error parsing error string (BUG)" );
    58         va_end( params );
    59         imcb_file_canceled( file, error );
     50gboolean msn_ftp_abort(file_transfer_t *file, char *format, ...)
     51{
     52        va_list params;
     53
     54        va_start(params, format);
     55        char error[128];
     56
     57        if (vsnprintf(error, 128, format, params) < 0) {
     58                sprintf(error, "internal error parsing error string (BUG)");
     59        }
     60        va_end(params);
     61        imcb_file_canceled(file, error);
    6062        return FALSE;
    6163}
     
    6365/* very useful */
    6466#define ASSERTSOCKOP(op, msg) \
    65         if( (op) == -1 ) \
    66                 return msn_ftp_abort( file , msg ": %s", strerror( errno ) );
    67 
    68 void msn_ftp_invitation_cmd( struct im_connection *ic, char *who, int cookie, char *icmd,
    69                              char *trailer )
    70 {
    71         struct msn_message *m = g_new0( struct msn_message, 1 );
    72        
    73         m->text = g_strdup_printf( "%s"
    74                     "Invitation-Command: %s\r\n"
    75                     "Invitation-Cookie: %u\r\n"
    76                     "%s",
    77                     MSN_INVITE_HEADERS,
    78                     icmd,
    79                     cookie,
    80                     trailer);
    81        
    82         m->who = g_strdup( who );
    83 
    84         msn_sb_write_msg( ic, m );
    85 }
    86 
    87 void msn_ftp_cancel_invite( struct im_connection *ic, char *who,  int cookie, char *code )
     67        if ((op) == -1) { \
     68                return msn_ftp_abort(file, msg ": %s", strerror(errno)); }
     69
     70void msn_ftp_invitation_cmd(struct im_connection *ic, char *who, int cookie, char *icmd,
     71                            char *trailer)
     72{
     73        struct msn_message *m = g_new0(struct msn_message, 1);
     74
     75        m->text = g_strdup_printf("%s"
     76                                  "Invitation-Command: %s\r\n"
     77                                  "Invitation-Cookie: %u\r\n"
     78                                  "%s",
     79                                  MSN_INVITE_HEADERS,
     80                                  icmd,
     81                                  cookie,
     82                                  trailer);
     83
     84        m->who = g_strdup(who);
     85
     86        msn_sb_write_msg(ic, m);
     87}
     88
     89void msn_ftp_cancel_invite(struct im_connection *ic, char *who,  int cookie, char *code)
    8890{
    8991        char buf[64];
    9092
    91         g_snprintf( buf, sizeof( buf ), "Cancel-Code: %s\r\n", code );
    92         msn_ftp_invitation_cmd( ic, who, cookie, "CANCEL", buf );
    93 }
    94 
    95 void msn_ftp_transfer_request( struct im_connection *ic, file_transfer_t *file, char *who )
    96 {
    97         unsigned int cookie = time( NULL ); /* TODO: randomize */
     93        g_snprintf(buf, sizeof(buf), "Cancel-Code: %s\r\n", code);
     94        msn_ftp_invitation_cmd(ic, who, cookie, "CANCEL", buf);
     95}
     96
     97void msn_ftp_transfer_request(struct im_connection *ic, file_transfer_t *file, char *who)
     98{
     99        unsigned int cookie = time(NULL);  /* TODO: randomize */
    98100        char buf[2048];
    99101
    100         msn_filetransfer_t *msn_file = g_new0( msn_filetransfer_t, 1 );
     102        msn_filetransfer_t *msn_file = g_new0(msn_filetransfer_t, 1);
     103
    101104        file->data = msn_file;
    102105        file->free = msn_ftp_free;
     
    105108        msn_file->md = ic->proto_data;
    106109        msn_file->invite_cookie = cookie;
    107         msn_file->handle = g_strdup( who );
     110        msn_file->handle = g_strdup(who);
    108111        msn_file->dcc = file;
    109         msn_file->md->filetransfers = g_slist_prepend( msn_file->md->filetransfers, msn_file->dcc );
     112        msn_file->md->filetransfers = g_slist_prepend(msn_file->md->filetransfers, msn_file->dcc);
    110113        msn_file->fd = -1;
    111114        msn_file->sbufpos = 3;
    112115
    113         g_snprintf( buf, sizeof( buf ),
    114                 "Application-Name: File Transfer\r\n"
    115                 "Application-GUID: {5D3E02AB-6190-11d3-BBBB-00C04F795683}\r\n"
    116                 "Application-File: %s\r\n"
    117                 "Application-FileSize: %zd\r\n",
    118                 file->file_name,
    119                 file->file_size);
    120 
    121         msn_ftp_invitation_cmd( msn_file->md->ic, msn_file->handle, cookie, "INVITE", buf );
    122 
    123         imcb_file_recv_start( file );
    124 }
    125 
    126 void msn_invitation_invite( struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen )
    127 {
    128         char *itype = msn_findheader( body, "Application-GUID:", blen );
     116        g_snprintf(buf, sizeof(buf),
     117                   "Application-Name: File Transfer\r\n"
     118                   "Application-GUID: {5D3E02AB-6190-11d3-BBBB-00C04F795683}\r\n"
     119                   "Application-File: %s\r\n"
     120                   "Application-FileSize: %zd\r\n",
     121                   file->file_name,
     122                   file->file_size);
     123
     124        msn_ftp_invitation_cmd(msn_file->md->ic, msn_file->handle, cookie, "INVITE", buf);
     125
     126        imcb_file_recv_start(file);
     127}
     128
     129void msn_invitation_invite(struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen)
     130{
     131        char *itype = msn_findheader(body, "Application-GUID:", blen);
    129132        char *name, *size, *invitecookie, *reject = NULL;
    130133        user_t *u;
    131134        size_t isize;
    132135        file_transfer_t *file;
    133        
    134         if( !itype || strcmp( itype, "{5D3E02AB-6190-11d3-BBBB-00C04F795683}" ) != 0 ) {
     136
     137        if (!itype || strcmp(itype, "{5D3E02AB-6190-11d3-BBBB-00C04F795683}") != 0) {
    135138                /* Don't know what that is - don't care */
    136                 char *iname = msn_findheader( body, "Application-Name:", blen );
    137                 imcb_log( sb->ic, "Received unknown MSN invitation %s (%s) from %s",
    138                           itype ? : "with no GUID", iname ? iname : "no application name", handle );
    139                 g_free( iname );
     139                char *iname = msn_findheader(body, "Application-Name:", blen);
     140                imcb_log(sb->ic, "Received unknown MSN invitation %s (%s) from %s",
     141                         itype ? : "with no GUID", iname ? iname : "no application name", handle);
     142                g_free(iname);
    140143                reject = "REJECT_NOT_INSTALLED";
    141         } else if ( 
    142                 !( name = msn_findheader( body, "Application-File:", blen )) ||
    143                 !( size = msn_findheader( body, "Application-FileSize:", blen )) ||
    144                 !( invitecookie = msn_findheader( body, "Invitation-Cookie:", blen)) ||
    145                 !( isize = atoll( size ) ) ) {
    146                 imcb_log( sb->ic, "Received corrupted transfer request from %s"
    147                           "(name=%s, size=%s, invitecookie=%s)",
    148                           handle, name, size, invitecookie );
     144        } else if (
     145                !(name = msn_findheader(body, "Application-File:", blen)) ||
     146                !(size = msn_findheader(body, "Application-FileSize:", blen)) ||
     147                !(invitecookie = msn_findheader(body, "Invitation-Cookie:", blen)) ||
     148                !(isize = atoll(size))) {
     149                imcb_log(sb->ic, "Received corrupted transfer request from %s"
     150                         "(name=%s, size=%s, invitecookie=%s)",
     151                         handle, name, size, invitecookie);
    149152                reject = "REJECT";
    150         } else if ( !( u = user_findhandle( sb->ic, handle ) ) ) {
    151                 imcb_log( sb->ic, "Error in parsing transfer request, User '%s'"
    152                           "is not in contact list", handle );
     153        } else if (!(u = user_findhandle(sb->ic, handle))) {
     154                imcb_log(sb->ic, "Error in parsing transfer request, User '%s'"
     155                         "is not in contact list", handle);
    153156                reject = "REJECT";
    154         } else if ( !( file = imcb_file_send_start( sb->ic, handle, name, isize ) ) ) {
    155                 imcb_log( sb->ic, "Error initiating transfer for request from %s for %s",
    156                           handle, name );
     157        } else if (!(file = imcb_file_send_start(sb->ic, handle, name, isize))) {
     158                imcb_log(sb->ic, "Error initiating transfer for request from %s for %s",
     159                         handle, name);
    157160                reject = "REJECT";
    158161        } else {
    159                 msn_filetransfer_t *msn_file = g_new0( msn_filetransfer_t, 1 );
     162                msn_filetransfer_t *msn_file = g_new0(msn_filetransfer_t, 1);
    160163                file->data = msn_file;
    161164                file->accept = msn_ftpr_accept;
     
    166169                msn_file->md = sb->ic->proto_data;
    167170                msn_file->invite_cookie = cookie;
    168                 msn_file->handle = g_strdup( handle );
     171                msn_file->handle = g_strdup(handle);
    169172                msn_file->dcc = file;
    170                 msn_file->md->filetransfers = g_slist_prepend( msn_file->md->filetransfers, msn_file->dcc );
     173                msn_file->md->filetransfers = g_slist_prepend(msn_file->md->filetransfers, msn_file->dcc);
    171174                msn_file->fd = -1;
    172175        }
    173176
    174         if( reject )
    175                 msn_ftp_cancel_invite( sb->ic, sb->who, cookie, reject );
    176 
    177         g_free( name );
    178         g_free( size );
    179         g_free( invitecookie );
    180         g_free( itype );
    181 }
    182 
    183 msn_filetransfer_t* msn_find_filetransfer( struct msn_data *md, unsigned int cookie, char *handle )
     177        if (reject) {
     178                msn_ftp_cancel_invite(sb->ic, sb->who, cookie, reject);
     179        }
     180
     181        g_free(name);
     182        g_free(size);
     183        g_free(invitecookie);
     184        g_free(itype);
     185}
     186
     187msn_filetransfer_t* msn_find_filetransfer(struct msn_data *md, unsigned int cookie, char *handle)
    184188{
    185189        GSList *l;
    186        
    187         for( l = md->filetransfers; l; l = l->next ) {
    188                 msn_filetransfer_t *file = ( (file_transfer_t*) l->data )->data;
    189                 if( file->invite_cookie == cookie && strcmp( handle, file->handle ) == 0 ) {
     190
     191        for (l = md->filetransfers; l; l = l->next) {
     192                msn_filetransfer_t *file = ((file_transfer_t *) l->data)->data;
     193                if (file->invite_cookie == cookie && strcmp(handle, file->handle) == 0) {
    190194                        return file;
    191195                }
     
    194198}
    195199
    196 gboolean msn_ftps_connected( gpointer data, gint fd, b_input_condition cond )
     200gboolean msn_ftps_connected(gpointer data, gint fd, b_input_condition cond)
    197201{
    198202        file_transfer_t *file = data;
    199203        msn_filetransfer_t *msn_file = file->data;
    200204        struct sockaddr_storage clt_addr;
    201         socklen_t ssize = sizeof( clt_addr );
    202        
    203         debug( "Connected to MSNFTP client" );
    204        
    205         ASSERTSOCKOP( msn_file->fd = accept( fd, (struct sockaddr *) &clt_addr, &ssize ), "Accepting connection" );
    206 
    207         closesocket( fd );
     205        socklen_t ssize = sizeof(clt_addr);
     206
     207        debug("Connected to MSNFTP client");
     208
     209        ASSERTSOCKOP(msn_file->fd = accept(fd, (struct sockaddr *) &clt_addr, &ssize), "Accepting connection");
     210
     211        closesocket(fd);
    208212        fd = msn_file->fd;
    209         sock_make_nonblocking( fd );
    210 
    211         msn_file->r_event_id = b_input_add( fd, B_EV_IO_READ, msn_ftp_read, file );
     213        sock_make_nonblocking(fd);
     214
     215        msn_file->r_event_id = b_input_add(fd, B_EV_IO_READ, msn_ftp_read, file);
    212216
    213217        return FALSE;
    214218}
    215219
    216 void msn_invitations_accept( msn_filetransfer_t *msn_file, struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen )
     220void msn_invitations_accept(msn_filetransfer_t *msn_file, struct msn_switchboard *sb, char *handle, unsigned int cookie,
     221                            char *body, int blen)
    217222{
    218223        file_transfer_t *file = msn_file->dcc;
    219224        char buf[1024];
    220         unsigned int acookie = time ( NULL );
    221         char host[HOST_NAME_MAX+1];
     225        unsigned int acookie = time(NULL);
     226        char host[HOST_NAME_MAX + 1];
    222227        char port[6];
    223228        char *errmsg;
     
    225230        msn_file->auth_cookie = acookie;
    226231
    227         if( ( msn_file->fd = ft_listen( NULL, host, port, FALSE, &errmsg ) ) == -1 ) {
    228                 msn_ftp_abort( file, "Failed to listen locally, check your ft_listen setting in bitlbee.conf: %s", errmsg );
     232        if ((msn_file->fd = ft_listen(NULL, host, port, FALSE, &errmsg)) == -1) {
     233                msn_ftp_abort(file, "Failed to listen locally, check your ft_listen setting in bitlbee.conf: %s",
     234                              errmsg);
    229235                return;
    230236        }
    231237
    232         msn_file->r_event_id = b_input_add( msn_file->fd, B_EV_IO_READ, msn_ftps_connected, file );
    233 
    234         g_snprintf( buf, sizeof( buf ),
    235                     "IP-Address: %s\r\n"
    236                     "Port: %s\r\n"
    237                     "AuthCookie: %d\r\n"
    238                     "Launch-Application: FALSE\r\n"
    239                     "Request-Data: IP-Address:\r\n\r\n",
    240                     host,
    241                     port,
    242                     msn_file->auth_cookie );
    243 
    244         msn_ftp_invitation_cmd( msn_file->md->ic, handle, msn_file->invite_cookie, "ACCEPT", buf );
    245 }
    246 
    247 void msn_invitationr_accept( msn_filetransfer_t *msn_file, struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen ) {
     238        msn_file->r_event_id = b_input_add(msn_file->fd, B_EV_IO_READ, msn_ftps_connected, file);
     239
     240        g_snprintf(buf, sizeof(buf),
     241                   "IP-Address: %s\r\n"
     242                   "Port: %s\r\n"
     243                   "AuthCookie: %d\r\n"
     244                   "Launch-Application: FALSE\r\n"
     245                   "Request-Data: IP-Address:\r\n\r\n",
     246                   host,
     247                   port,
     248                   msn_file->auth_cookie);
     249
     250        msn_ftp_invitation_cmd(msn_file->md->ic, handle, msn_file->invite_cookie, "ACCEPT", buf);
     251}
     252
     253void msn_invitationr_accept(msn_filetransfer_t *msn_file, struct msn_switchboard *sb, char *handle, unsigned int cookie,
     254                            char *body, int blen)
     255{
    248256        file_transfer_t *file = msn_file->dcc;
    249257        char *authcookie, *ip, *port;
    250258
    251         if( !( authcookie = msn_findheader( body, "AuthCookie:", blen ) ) ||
    252             !( ip = msn_findheader( body, "IP-Address:", blen ) ) ||
    253             !( port = msn_findheader( body, "Port:", blen ) ) ) {
    254                 msn_ftp_abort( file, "Received invalid accept reply" );
    255         } else if(
    256                 ( msn_file->fd = proxy_connect( ip, atoi( port ), msn_ftp_connected, file ) )
    257                 < 0 ) {
    258                         msn_ftp_abort( file, "Error connecting to MSN client" );
    259         } else
    260                 msn_file->auth_cookie = strtoul( authcookie, NULL, 10 );
    261 
    262         g_free( authcookie );
    263         g_free( ip );
    264         g_free( port );
    265 }
    266 
    267 void msn_invitation_accept( struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen )
    268 {
    269         msn_filetransfer_t *msn_file = msn_find_filetransfer( sb->ic->proto_data, cookie, handle );
     259        if (!(authcookie = msn_findheader(body, "AuthCookie:", blen)) ||
     260            !(ip = msn_findheader(body, "IP-Address:", blen)) ||
     261            !(port = msn_findheader(body, "Port:", blen))) {
     262                msn_ftp_abort(file, "Received invalid accept reply");
     263        } else if (
     264                (msn_file->fd = proxy_connect(ip, atoi(port), msn_ftp_connected, file))
     265                < 0) {
     266                msn_ftp_abort(file, "Error connecting to MSN client");
     267        } else {
     268                msn_file->auth_cookie = strtoul(authcookie, NULL, 10);
     269        }
     270
     271        g_free(authcookie);
     272        g_free(ip);
     273        g_free(port);
     274}
     275
     276void msn_invitation_accept(struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen)
     277{
     278        msn_filetransfer_t *msn_file = msn_find_filetransfer(sb->ic->proto_data, cookie, handle);
    270279        file_transfer_t *file = msn_file ? msn_file->dcc : NULL;
    271        
    272         if( !msn_file  )
    273                 imcb_log( sb->ic, "Received invitation ACCEPT message for unknown invitation (already aborted?)" );
    274         else if( file->sending )
    275                 msn_invitations_accept( msn_file, sb, handle, cookie, body, blen );
    276         else
    277                 msn_invitationr_accept( msn_file, sb, handle, cookie, body, blen );
    278 }
    279 
    280 void msn_invitation_cancel( struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen )
    281 {
    282         msn_filetransfer_t *msn_file = msn_find_filetransfer( sb->ic->proto_data, cookie, handle );
    283        
    284         if( !msn_file )
    285                 imcb_log( sb->ic, "Received invitation CANCEL message for unknown invitation (already aborted?)" );
    286         else
    287                 msn_ftp_abort( msn_file->dcc, msn_findheader( body, "Cancel-Code:", blen ) );
    288 }
    289 
    290 int msn_ftp_write( file_transfer_t *file, char *format, ... )
     280
     281        if (!msn_file) {
     282                imcb_log(sb->ic, "Received invitation ACCEPT message for unknown invitation (already aborted?)");
     283        } else if (file->sending) {
     284                msn_invitations_accept(msn_file, sb, handle, cookie, body, blen);
     285        } else {
     286                msn_invitationr_accept(msn_file, sb, handle, cookie, body, blen);
     287        }
     288}
     289
     290void msn_invitation_cancel(struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen)
     291{
     292        msn_filetransfer_t *msn_file = msn_find_filetransfer(sb->ic->proto_data, cookie, handle);
     293
     294        if (!msn_file) {
     295                imcb_log(sb->ic, "Received invitation CANCEL message for unknown invitation (already aborted?)");
     296        } else {
     297                msn_ftp_abort(msn_file->dcc, msn_findheader(body, "Cancel-Code:", blen));
     298        }
     299}
     300
     301int msn_ftp_write(file_transfer_t *file, char *format, ...)
    291302{
    292303        msn_filetransfer_t *msn_file = file->data;
     
    294305        int st;
    295306        char *s;
    296        
    297         va_start( params, format );
    298         s = g_strdup_vprintf( format, params );
    299         va_end( params );
    300        
    301         st = write( msn_file->fd, s, strlen( s ) );
    302         if( st != strlen( s ) )
    303                 return msn_ftp_abort( file, "Error sending data over MSNFTP connection: %s",
    304                                 strerror( errno ) );
    305        
    306         g_free( s );
     307
     308        va_start(params, format);
     309        s = g_strdup_vprintf(format, params);
     310        va_end(params);
     311
     312        st = write(msn_file->fd, s, strlen(s));
     313        if (st != strlen(s)) {
     314                return msn_ftp_abort(file, "Error sending data over MSNFTP connection: %s",
     315                                     strerror(errno));
     316        }
     317
     318        g_free(s);
    307319        return 1;
    308320}
    309321
    310 gboolean msn_ftp_connected( gpointer data, gint fd, b_input_condition cond )
     322gboolean msn_ftp_connected(gpointer data, gint fd, b_input_condition cond)
    311323{
    312324        file_transfer_t *file = data;
    313325        msn_filetransfer_t *msn_file = file->data;
    314        
    315         debug( "Connected to MSNFTP server, starting authentication" );
    316         if( !msn_ftp_write( file, "VER MSNFTP\r\n" ) )
     326
     327        debug("Connected to MSNFTP server, starting authentication");
     328        if (!msn_ftp_write(file, "VER MSNFTP\r\n")) {
    317329                return FALSE;
    318        
    319         sock_make_nonblocking( msn_file->fd );
    320         msn_file->r_event_id = b_input_add( msn_file->fd, B_EV_IO_READ, msn_ftp_read, file );
    321        
     330        }
     331
     332        sock_make_nonblocking(msn_file->fd);
     333        msn_file->r_event_id = b_input_add(msn_file->fd, B_EV_IO_READ, msn_ftp_read, file);
     334
    322335        return FALSE;
    323336}
    324337
    325 gboolean msn_ftp_handle_command( file_transfer_t *file, char* line )
    326 {
    327         msn_filetransfer_t *msn_file = file->data;
    328         char **cmd = msn_linesplit( line );
     338gboolean msn_ftp_handle_command(file_transfer_t *file, char* line)
     339{
     340        msn_filetransfer_t *msn_file = file->data;
     341        char **cmd = msn_linesplit(line);
    329342        int count = 0;
    330         if( cmd[0] ) while( cmd[++count] );
    331        
    332         if( count < 1 )
    333                 return msn_ftp_abort( file, "Missing command in MSNFTP communication" );
    334        
    335         if( strcmp( cmd[0], "VER" ) == 0 ) {
    336                 if( strcmp( cmd[1], "MSNFTP" ) != 0 )
    337                         return msn_ftp_abort( file, "Unsupported filetransfer protocol: %s", cmd[1] );
    338                 if( file->sending )
    339                         msn_ftp_write( file, "VER MSNFTP\r\n" );
    340                 else
    341                         msn_ftp_write( file, "USR %s %u\r\n", msn_file->md->ic->acc->user, msn_file->auth_cookie );
    342         } else if( strcmp( cmd[0], "FIL" ) == 0 ) {
    343                 if( strtoul( cmd[1], NULL, 10 ) != file->file_size )
    344                         return msn_ftp_abort( file, "FIL reply contains a different file size than the size in the invitation" );
    345                 msn_ftp_write( file, "TFR\r\n" );
     343
     344        if (cmd[0]) {
     345                while (cmd[++count]) {
     346                        ;
     347                }
     348        }
     349
     350        if (count < 1) {
     351                return msn_ftp_abort(file, "Missing command in MSNFTP communication");
     352        }
     353
     354        if (strcmp(cmd[0], "VER") == 0) {
     355                if (strcmp(cmd[1], "MSNFTP") != 0) {
     356                        return msn_ftp_abort(file, "Unsupported filetransfer protocol: %s", cmd[1]);
     357                }
     358                if (file->sending) {
     359                        msn_ftp_write(file, "VER MSNFTP\r\n");
     360                } else {
     361                        msn_ftp_write(file, "USR %s %u\r\n", msn_file->md->ic->acc->user, msn_file->auth_cookie);
     362                }
     363        } else if (strcmp(cmd[0], "FIL") == 0) {
     364                if (strtoul(cmd[1], NULL, 10) != file->file_size) {
     365                        return msn_ftp_abort(file,
     366                                             "FIL reply contains a different file size than the size in the invitation");
     367                }
     368                msn_ftp_write(file, "TFR\r\n");
    346369                msn_file->status |= MSN_TRANSFER_RECEIVING;
    347         } else if( strcmp( cmd[0], "USR" ) == 0 ) {
    348                 if( ( strcmp( cmd[1], msn_file->handle ) != 0 ) ||
    349                     ( strtoul( cmd[2], NULL, 10 ) != msn_file->auth_cookie ) )
    350                         msn_ftp_abort( file, "Authentication failed. "
    351                                 "Expected handle: %s (got %s), cookie: %u (got %s)",
    352                                 msn_file->handle, cmd[1],
    353                                 msn_file->auth_cookie, cmd[2] );
    354                 msn_ftp_write( file, "FIL %zu\r\n", file->file_size);
    355         } else if( strcmp( cmd[0], "TFR" ) == 0 ) {
    356                 file->write_request( file );
    357         } else if( strcmp( cmd[0], "BYE" ) == 0 ) {
     370        } else if (strcmp(cmd[0], "USR") == 0) {
     371                if ((strcmp(cmd[1], msn_file->handle) != 0) ||
     372                    (strtoul(cmd[2], NULL, 10) != msn_file->auth_cookie)) {
     373                        msn_ftp_abort(file, "Authentication failed. "
     374                                      "Expected handle: %s (got %s), cookie: %u (got %s)",
     375                                      msn_file->handle, cmd[1],
     376                                      msn_file->auth_cookie, cmd[2]);
     377                }
     378                msn_ftp_write(file, "FIL %zu\r\n", file->file_size);
     379        } else if (strcmp(cmd[0], "TFR") == 0) {
     380                file->write_request(file);
     381        } else if (strcmp(cmd[0], "BYE") == 0) {
    358382                unsigned int retcode = count > 1 ? atoi(cmd[1]) : 1;
    359383
    360                 if( ( retcode==16777989 ) || ( retcode==16777987 ) )
    361                         imcb_file_finished( file );
    362                 else if( retcode==2147942405 )
    363                         imcb_file_canceled( file, "Failure: receiver is out of disk space" );
    364                 else if( retcode==2164261682 )
    365                         imcb_file_canceled( file, "Failure: receiver cancelled the transfer" );
    366                 else if( retcode==2164261683 )
    367                         imcb_file_canceled( file, "Failure: sender has cancelled the transfer" );
    368                 else if( retcode==2164261694 )
    369                         imcb_file_canceled( file, "Failure: connection is blocked" );
    370                 else {
     384                if ((retcode == 16777989) || (retcode == 16777987)) {
     385                        imcb_file_finished(file);
     386                } else if (retcode == 2147942405) {
     387                        imcb_file_canceled(file, "Failure: receiver is out of disk space");
     388                } else if (retcode == 2164261682) {
     389                        imcb_file_canceled(file, "Failure: receiver cancelled the transfer");
     390                } else if (retcode == 2164261683) {
     391                        imcb_file_canceled(file, "Failure: sender has cancelled the transfer");
     392                } else if (retcode == 2164261694) {
     393                        imcb_file_canceled(file, "Failure: connection is blocked");
     394                } else {
    371395                        char buf[128];
    372396
    373                         sprintf( buf, "Failure: unknown BYE code: %d", retcode);
    374                         imcb_file_canceled( file, buf );
    375                 }
    376         } else if( strcmp( cmd[0], "CCL" ) == 0 ) {
    377                 imcb_file_canceled( file, "Failure: receiver cancelled the transfer" );
    378         } else {
    379                 msn_ftp_abort( file, "Received invalid command %s from msn client", cmd[0] );
     397                        sprintf(buf, "Failure: unknown BYE code: %d", retcode);
     398                        imcb_file_canceled(file, buf);
     399                }
     400        } else if (strcmp(cmd[0], "CCL") == 0) {
     401                imcb_file_canceled(file, "Failure: receiver cancelled the transfer");
     402        } else {
     403                msn_ftp_abort(file, "Received invalid command %s from msn client", cmd[0]);
    380404        }
    381405        return TRUE;
    382406}
    383407
    384 gboolean msn_ftp_send( gpointer data, gint fd, b_input_condition cond )
     408gboolean msn_ftp_send(gpointer data, gint fd, b_input_condition cond)
    385409{
    386410        file_transfer_t *file = data;
     
    389413        msn_file->w_event_id = 0;
    390414
    391         file->write_request( file );
     415        file->write_request(file);
    392416
    393417        return FALSE;
     
    399423 * This got a bit complicated because (at least) amsn expects packets of size 2045.
    400424 */
    401 gboolean msn_ftps_write( file_transfer_t *file, char *buffer, unsigned int len )
    402 {
    403         msn_filetransfer_t *msn_file = file->data;
    404         int ret, overflow;
     425gboolean msn_ftps_write(file_transfer_t *file, char *buffer, unsigned int len)
     426{
     427        msn_filetransfer_t *msn_file = file->data;
     428        int ret, overflow;
    405429
    406430        /* what we can't send now */
     
    408432
    409433        /* append what we can do the send buffer */
    410         memcpy( msn_file->sbuf + msn_file->sbufpos, buffer, MIN( len, MSNFTP_PSIZE - msn_file->sbufpos ) );
    411         msn_file->sbufpos += MIN( len, MSNFTP_PSIZE - msn_file->sbufpos );
     434        memcpy(msn_file->sbuf + msn_file->sbufpos, buffer, MIN(len, MSNFTP_PSIZE - msn_file->sbufpos));
     435        msn_file->sbufpos += MIN(len, MSNFTP_PSIZE - msn_file->sbufpos);
    412436
    413437        /* if we don't have enough for a full packet and there's more wait for it */
    414         if( ( msn_file->sbufpos < MSNFTP_PSIZE ) &&
    415             ( msn_file->data_sent + msn_file->sbufpos - 3 < file->file_size ) ) {
    416                 if( !msn_file->w_event_id )
    417                         msn_file->w_event_id = b_input_add( msn_file->fd, B_EV_IO_WRITE, msn_ftp_send, file );
     438        if ((msn_file->sbufpos < MSNFTP_PSIZE) &&
     439            (msn_file->data_sent + msn_file->sbufpos - 3 < file->file_size)) {
     440                if (!msn_file->w_event_id) {
     441                        msn_file->w_event_id = b_input_add(msn_file->fd, B_EV_IO_WRITE, msn_ftp_send, file);
     442                }
    418443                return TRUE;
    419444        }
     
    422447
    423448        msn_file->sbuf[0] = 0;
    424         msn_file->sbuf[1] = ( msn_file->sbufpos - 3 ) & 0xff;
    425         msn_file->sbuf[2] = ( ( msn_file->sbufpos - 3 ) >> 8 ) & 0xff;
    426 
    427         ASSERTSOCKOP( ret = send( msn_file->fd, msn_file->sbuf, msn_file->sbufpos, 0 ), "Sending" );
    428 
    429         msn_file->data_sent += ret - 3;
    430 
    431         /* TODO: this should really not be fatal */
    432         if( ret < msn_file->sbufpos )
    433                 return msn_ftp_abort( file, "send() sent %d instead of %d (send buffer full!)", ret, msn_file->sbufpos );
     449        msn_file->sbuf[1] = (msn_file->sbufpos - 3) & 0xff;
     450        msn_file->sbuf[2] = ((msn_file->sbufpos - 3) >> 8) & 0xff;
     451
     452        ASSERTSOCKOP(ret = send(msn_file->fd, msn_file->sbuf, msn_file->sbufpos, 0), "Sending");
     453
     454        msn_file->data_sent += ret - 3;
     455
     456        /* TODO: this should really not be fatal */
     457        if (ret < msn_file->sbufpos) {
     458                return msn_ftp_abort(file, "send() sent %d instead of %d (send buffer full!)", ret, msn_file->sbufpos);
     459        }
    434460
    435461        msn_file->sbufpos = 3;
    436462
    437         if( overflow > 0 ) {
    438                 while( overflow > ( MSNFTP_PSIZE - 3 ) ) {
    439                         if( !msn_ftps_write( file, buffer + len - overflow, MSNFTP_PSIZE - 3 ) )
     463        if (overflow > 0) {
     464                while (overflow > (MSNFTP_PSIZE - 3)) {
     465                        if (!msn_ftps_write(file, buffer + len - overflow, MSNFTP_PSIZE - 3)) {
    440466                                return FALSE;
     467                        }
    441468                        overflow -= MSNFTP_PSIZE - 3;
    442469                }
    443                 return msn_ftps_write( file, buffer + len - overflow, overflow );
    444         }
    445 
    446         if( msn_file->data_sent == file->file_size ) {
    447                 if( msn_file->w_event_id ) {
    448                         b_event_remove( msn_file->w_event_id );
     470                return msn_ftps_write(file, buffer + len - overflow, overflow);
     471        }
     472
     473        if (msn_file->data_sent == file->file_size) {
     474                if (msn_file->w_event_id) {
     475                        b_event_remove(msn_file->w_event_id);
    449476                        msn_file->w_event_id = 0;
    450477                }
    451478        } else {
    452479                /* we might already be listening if this is data from an overflow */
    453                 if( !msn_file->w_event_id )
    454                         msn_file->w_event_id = b_input_add( msn_file->fd, B_EV_IO_WRITE, msn_ftp_send, file );
    455         }
    456 
    457         return TRUE;
     480                if (!msn_file->w_event_id) {
     481                        msn_file->w_event_id = b_input_add(msn_file->fd, B_EV_IO_WRITE, msn_ftp_send, file);
     482                }
     483        }
     484
     485        return TRUE;
    458486}
    459487
    460488/* Binary part of the file transfer protocol */
    461 gboolean msn_ftpr_read( file_transfer_t *file )
     489gboolean msn_ftpr_read(file_transfer_t *file)
    462490{
    463491        msn_filetransfer_t *msn_file = file->data;
     
    465493        unsigned char buf[3];
    466494
    467         if( msn_file->data_remaining ) {
     495        if (msn_file->data_remaining) {
    468496                msn_file->r_event_id = 0;
    469497
    470                 ASSERTSOCKOP( st = read( msn_file->fd, file->buffer, MIN( sizeof( file->buffer ), msn_file->data_remaining ) ), "Receiving" );
    471 
    472                 if( st == 0 )
    473                         return msn_ftp_abort( file, "Remote end closed connection");
     498                ASSERTSOCKOP(st = read(msn_file->fd, file->buffer, MIN(sizeof(file->buffer),
     499                                                                       msn_file->data_remaining)), "Receiving");
     500
     501                if (st == 0) {
     502                        return msn_ftp_abort(file, "Remote end closed connection");
     503                }
    474504
    475505                msn_file->data_sent += st;
     
    477507                msn_file->data_remaining -= st;
    478508
    479                 file->write( file, file->buffer, st );
    480 
    481                 if( msn_file->data_sent >= file->file_size )
    482                         imcb_file_finished( file );
     509                file->write(file, file->buffer, st);
     510
     511                if (msn_file->data_sent >= file->file_size) {
     512                        imcb_file_finished(file);
     513                }
    483514
    484515                return FALSE;
    485516        } else {
    486                 ASSERTSOCKOP( st = read( msn_file->fd, buf, 1 ), "Receiving" );
    487                 if( st == 0 ) {
    488                         return msn_ftp_abort( file, "read returned EOF while reading data header from msn client" );
    489                 } else if( buf[0] == '\r' || buf[0] == '\n' ) {
    490                         debug( "Discarding extraneous newline" );
    491                 } else if( buf[0] != 0 ) {
    492                         msn_ftp_abort( file, "Remote end canceled the transfer");
     517                ASSERTSOCKOP(st = read(msn_file->fd, buf, 1), "Receiving");
     518                if (st == 0) {
     519                        return msn_ftp_abort(file, "read returned EOF while reading data header from msn client");
     520                } else if (buf[0] == '\r' || buf[0] == '\n') {
     521                        debug("Discarding extraneous newline");
     522                } else if (buf[0] != 0) {
     523                        msn_ftp_abort(file, "Remote end canceled the transfer");
    493524                        /* don't really care about these last 2 (should be 0,0) */
    494                         read( msn_file->fd, buf, 2 );
     525                        read(msn_file->fd, buf, 2);
    495526                        return FALSE;
    496527                } else {
    497528                        unsigned int size;
    498                         ASSERTSOCKOP( st = read( msn_file->fd, buf, 2 ), "Receiving" );
    499                         if( st < 2 )
    500                                 return msn_ftp_abort( file, "read returned EOF while reading data header from msn client" );
     529                        ASSERTSOCKOP(st = read(msn_file->fd, buf, 2), "Receiving");
     530                        if (st < 2) {
     531                                return msn_ftp_abort(file,
     532                                                     "read returned EOF while reading data header from msn client");
     533                        }
    501534
    502535                        size = buf[0] + ((unsigned int) buf[1] << 8);
     
    508541
    509542/* Text mode part of the file transfer protocol */
    510 gboolean msn_ftp_txtproto( file_transfer_t *file )
     543gboolean msn_ftp_txtproto(file_transfer_t *file)
    511544{
    512545        msn_filetransfer_t *msn_file = file->data;
     
    514547        char *tbuf = msn_file->tbuf;
    515548
    516         ASSERTSOCKOP( st = read( msn_file->fd,
    517                                  tbuf + msn_file->tbufpos,
    518                                  sizeof( msn_file->tbuf ) - msn_file->tbufpos ),
    519                                  "Receiving" );
    520 
    521         if( st == 0 )
    522                 return msn_ftp_abort( file, "read returned EOF while reading text from msn client" );
     549        ASSERTSOCKOP(st = read(msn_file->fd,
     550                               tbuf + msn_file->tbufpos,
     551                               sizeof(msn_file->tbuf) - msn_file->tbufpos),
     552                     "Receiving");
     553
     554        if (st == 0) {
     555                return msn_ftp_abort(file, "read returned EOF while reading text from msn client");
     556        }
    523557
    524558        msn_file->tbufpos += st;
    525559
    526560        do {
    527                 for( ;i < msn_file->tbufpos; i++ ) {
    528                         if( tbuf[i] == '\n' || tbuf[i] == '\r' ) {
     561                for (; i < msn_file->tbufpos; i++) {
     562                        if (tbuf[i] == '\n' || tbuf[i] == '\r') {
    529563                                tbuf[i] = '\0';
    530                                 if( i > 0 )
    531                                         msn_ftp_handle_command( file, tbuf );
    532                                 else
    533                                         while( tbuf[i] == '\n' || tbuf[i] == '\r' ) i++;
    534                                 memmove( tbuf, tbuf + i + 1, msn_file->tbufpos - i - 1 );
     564                                if (i > 0) {
     565                                        msn_ftp_handle_command(file, tbuf);
     566                                } else {
     567                                        while (tbuf[i] == '\n' || tbuf[i] == '\r') {
     568                                                i++;
     569                                        }
     570                                }
     571                                memmove(tbuf, tbuf + i + 1, msn_file->tbufpos - i - 1);
    535572                                msn_file->tbufpos -= i + 1;
    536573                                i = 0;
     
    538575                        }
    539576                }
    540         } while ( i < msn_file->tbufpos );
    541 
    542         if( msn_file->tbufpos == sizeof( msn_file->tbuf ) )
    543                 return msn_ftp_abort( file,
    544                                       "Line exceeded %d bytes in text protocol",
    545                                       sizeof( msn_file->tbuf ) );
     577        } while (i < msn_file->tbufpos);
     578
     579        if (msn_file->tbufpos == sizeof(msn_file->tbuf)) {
     580                return msn_ftp_abort(file,
     581                                     "Line exceeded %d bytes in text protocol",
     582                                     sizeof(msn_file->tbuf));
     583        }
    546584        return TRUE;
    547585}
    548586
    549 gboolean msn_ftp_read( gpointer data, gint fd, b_input_condition cond )
     587gboolean msn_ftp_read(gpointer data, gint fd, b_input_condition cond)
    550588{
    551589        file_transfer_t *file = data;
    552590        msn_filetransfer_t *msn_file = file->data;
    553        
    554         if( msn_file->status & MSN_TRANSFER_RECEIVING )
    555                 return msn_ftpr_read( file );
    556         else
    557                 return msn_ftp_txtproto( file );
    558 }
    559 
    560 void msn_ftp_free( file_transfer_t *file )
    561 {
    562         msn_filetransfer_t *msn_file = file->data;
    563        
    564         if( msn_file->r_event_id )
    565                 b_event_remove( msn_file->r_event_id );
    566 
    567         if( msn_file->w_event_id )
    568                 b_event_remove( msn_file->w_event_id );
    569 
    570         if( msn_file->fd != -1 )
    571                 closesocket( msn_file->fd );
    572 
    573         msn_file->md->filetransfers = g_slist_remove( msn_file->md->filetransfers, msn_file->dcc );
    574        
    575         g_free( msn_file->handle );
    576        
    577         g_free( msn_file );
    578 }
    579 
    580 void msn_ftpr_accept( file_transfer_t *file )
    581 {
    582         msn_filetransfer_t *msn_file = file->data;
    583 
    584         msn_ftp_invitation_cmd( msn_file->md->ic, msn_file->handle, msn_file->invite_cookie, "ACCEPT",
    585                                 "Launch-Application: FALSE\r\n"
    586                                 "Request-Data: IP-Address:\r\n");
    587 }
    588 
    589 void msn_ftp_finished( file_transfer_t *file )
    590 {
    591         msn_ftp_write( file, "BYE 16777989\r\n" );
    592 }
    593 
    594 void msn_ftp_canceled( file_transfer_t *file, char *reason )
    595 {
    596         msn_filetransfer_t *msn_file = file->data;
    597 
    598         msn_ftp_cancel_invite( msn_file->md->ic, msn_file->handle,
    599                                msn_file->invite_cookie,
    600                                file->status & FT_STATUS_TRANSFERRING ?
    601                                         "FTTIMEOUT" :
    602                                         "FAIL" );
    603 
    604         imcb_log( msn_file->md->ic, "File transfer aborted: %s", reason );
    605 }
    606 
    607 gboolean msn_ftpr_write_request( file_transfer_t *file )
    608 {
    609         msn_filetransfer_t *msn_file = file->data;
    610         if( msn_file->r_event_id != 0 ) {
    611                 msn_ftp_abort( file,
    612                                         "BUG in MSN file transfer:"
    613                                         "write_request called when"
    614                                         "already watching for input" );
     591
     592        if (msn_file->status & MSN_TRANSFER_RECEIVING) {
     593                return msn_ftpr_read(file);
     594        } else {
     595                return msn_ftp_txtproto(file);
     596        }
     597}
     598
     599void msn_ftp_free(file_transfer_t *file)
     600{
     601        msn_filetransfer_t *msn_file = file->data;
     602
     603        if (msn_file->r_event_id) {
     604                b_event_remove(msn_file->r_event_id);
     605        }
     606
     607        if (msn_file->w_event_id) {
     608                b_event_remove(msn_file->w_event_id);
     609        }
     610
     611        if (msn_file->fd != -1) {
     612                closesocket(msn_file->fd);
     613        }
     614
     615        msn_file->md->filetransfers = g_slist_remove(msn_file->md->filetransfers, msn_file->dcc);
     616
     617        g_free(msn_file->handle);
     618
     619        g_free(msn_file);
     620}
     621
     622void msn_ftpr_accept(file_transfer_t *file)
     623{
     624        msn_filetransfer_t *msn_file = file->data;
     625
     626        msn_ftp_invitation_cmd(msn_file->md->ic, msn_file->handle, msn_file->invite_cookie, "ACCEPT",
     627                               "Launch-Application: FALSE\r\n"
     628                               "Request-Data: IP-Address:\r\n");
     629}
     630
     631void msn_ftp_finished(file_transfer_t *file)
     632{
     633        msn_ftp_write(file, "BYE 16777989\r\n");
     634}
     635
     636void msn_ftp_canceled(file_transfer_t *file, char *reason)
     637{
     638        msn_filetransfer_t *msn_file = file->data;
     639
     640        msn_ftp_cancel_invite(msn_file->md->ic, msn_file->handle,
     641                              msn_file->invite_cookie,
     642                              file->status & FT_STATUS_TRANSFERRING ?
     643                              "FTTIMEOUT" :
     644                              "FAIL");
     645
     646        imcb_log(msn_file->md->ic, "File transfer aborted: %s", reason);
     647}
     648
     649gboolean msn_ftpr_write_request(file_transfer_t *file)
     650{
     651        msn_filetransfer_t *msn_file = file->data;
     652
     653        if (msn_file->r_event_id != 0) {
     654                msn_ftp_abort(file,
     655                              "BUG in MSN file transfer:"
     656                              "write_request called when"
     657                              "already watching for input");
    615658                return FALSE;
    616659        }
    617660
    618         msn_file->r_event_id = 
    619                 b_input_add( msn_file->fd, B_EV_IO_READ, msn_ftp_read, file );
     661        msn_file->r_event_id =
     662                b_input_add(msn_file->fd, B_EV_IO_READ, msn_ftp_read, file);
    620663
    621664        return TRUE;
  • protocols/msn/invitation.h

    raf359b4 r5ebff60  
    1212 the Free Software Foundation; either version 2 of the License, or
    1313 (at your option) any later version.
    14  
     14
    1515 This program is distributed in the hope that it will be useful,
    1616 but WITHOUT ANY WARRANTY; without even the implied warranty of
    1717 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1818 GNU General Public License for more details.
    19  
     19
    2020 You should have received a copy of the GNU General Public License with
    2121 the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
     
    2929#include "msn.h"
    3030
    31 #define MSN_INVITE_HEADERS      "MIME-Version: 1.0\r\n" \
    32                                 "Content-Type: text/x-msmsgsinvite; charset=UTF-8\r\n" \
    33                                 "\r\n"
     31#define MSN_INVITE_HEADERS      "MIME-Version: 1.0\r\n" \
     32        "Content-Type: text/x-msmsgsinvite; charset=UTF-8\r\n" \
     33        "\r\n"
    3434
    3535#define MSNFTP_PSIZE 2048
    3636
    3737typedef enum {
    38         MSN_TRANSFER_RECEIVING  = 1,
    39         MSN_TRANSFER_SENDING    = 2
     38        MSN_TRANSFER_RECEIVING  = 1,
     39        MSN_TRANSFER_SENDING    = 2
    4040} msn_filetransfer_status_t;
    4141
    42 typedef struct msn_filetransfer
    43 {
    44 /* Generic invitation data */   
     42typedef struct msn_filetransfer {
     43/* Generic invitation data */
    4544        /* msn_data instance this invitation was received with. */
    4645        struct msn_data *md;
     
    6564        char tbuf[256];
    6665        unsigned int tbufpos;
    67        
     66
    6867        unsigned int data_sent;
    6968
    7069        gint r_event_id;
    7170        gint w_event_id;
    72        
     71
    7372        unsigned char sbuf[2048];
    7473        int sbufpos;
     
    7675} msn_filetransfer_t;
    7776
    78 void msn_invitation_invite( struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen );
    79 void msn_invitation_accept( struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen );
    80 void msn_invitation_cancel( struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen );
     77void msn_invitation_invite(struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen);
     78void msn_invitation_accept(struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen);
     79void msn_invitation_cancel(struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen);
    8180
    8281#endif
  • protocols/msn/msn.c

    raf359b4 r5ebff60  
    1   /********************************************************************\
     1/********************************************************************\
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
     
    3232GSList *msn_switchboards;
    3333
    34 static char *set_eval_display_name( set_t *set, char *value );
    35 
    36 static void msn_init( account_t *acc )
     34static char *set_eval_display_name(set_t *set, char *value);
     35
     36static void msn_init(account_t *acc)
    3737{
    3838        set_t *s;
    39        
    40         s = set_add( &acc->set, "display_name", NULL, set_eval_display_name, acc );
     39
     40        s = set_add(&acc->set, "display_name", NULL, set_eval_display_name, acc);
    4141        s->flags |= SET_NOSAVE | ACC_SET_ONLINE_ONLY;
    42        
    43         s = set_add( &acc->set, "server", MSN_NS_HOST, set_eval_account, acc );
     42
     43        s = set_add(&acc->set, "server", MSN_NS_HOST, set_eval_account, acc);
    4444        s->flags |= SET_NOSAVE | ACC_SET_OFFLINE_ONLY;
    4545
    46         s = set_add( &acc->set, "port", MSN_NS_PORT, set_eval_int, acc );
     46        s = set_add(&acc->set, "port", MSN_NS_PORT, set_eval_int, acc);
    4747        s->flags |= ACC_SET_OFFLINE_ONLY;
    4848
    49         set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc );
    50         set_add( &acc->set, "switchboard_keepalives", "false", set_eval_bool, acc );
    51        
     49        set_add(&acc->set, "mail_notifications", "false", set_eval_bool, acc);
     50        set_add(&acc->set, "switchboard_keepalives", "false", set_eval_bool, acc);
     51
    5252        acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE |
    5353                      ACC_FLAG_HANDLE_DOMAINS;
    5454}
    5555
    56 static void msn_login( account_t *acc )
    57 {
    58         struct im_connection *ic = imcb_new( acc );
    59         struct msn_data *md = g_new0( struct msn_data, 1 );
    60        
     56static void msn_login(account_t *acc)
     57{
     58        struct im_connection *ic = imcb_new(acc);
     59        struct msn_data *md = g_new0(struct msn_data, 1);
     60
    6161        ic->proto_data = md;
    6262        ic->flags |= OPT_PONGS | OPT_PONGED;
    63        
    64         if( strchr( acc->user, '@' ) == NULL )
    65         {
    66                 imcb_error( ic, "Invalid account name" );
    67                 imc_logout( ic, FALSE );
     63
     64        if (strchr(acc->user, '@') == NULL) {
     65                imcb_error(ic, "Invalid account name");
     66                imc_logout(ic, FALSE);
    6867                return;
    6968        }
    70        
     69
    7170        md->ic = ic;
    7271        md->away_state = msn_away_state_list;
    73         md->domaintree = g_tree_new( msn_domaintree_cmp );
     72        md->domaintree = g_tree_new(msn_domaintree_cmp);
    7473        md->ns->fd = -1;
    75        
    76         msn_connections = g_slist_prepend( msn_connections, ic );
    77        
    78         imcb_log( ic, "Connecting" );
    79         msn_ns_connect( ic, md->ns,
    80                         set_getstr( &ic->acc->set, "server" ),
    81                         set_getint( &ic->acc->set, "port" ) );
    82 }
    83 
    84 static void msn_logout( struct im_connection *ic )
     74
     75        msn_connections = g_slist_prepend(msn_connections, ic);
     76
     77        imcb_log(ic, "Connecting");
     78        msn_ns_connect(ic, md->ns,
     79                       set_getstr(&ic->acc->set, "server"),
     80                       set_getint(&ic->acc->set, "port"));
     81}
     82
     83static void msn_logout(struct im_connection *ic)
    8584{
    8685        struct msn_data *md = ic->proto_data;
    8786        GSList *l;
    8887        int i;
    89        
    90         if( md )
    91         {
     88
     89        if (md) {
    9290                /** Disabling MSN ft support for now.
    9391                while( md->filetransfers ) {
    94                         imcb_file_canceled( md->filetransfers->data, "Closing connection" );
     92                        imcb_file_canceled( md->filetransfers->data, "Closing connection" );
    9593                }
    9694                */
    97                
    98                 msn_ns_close( md->ns );
    99                
    100                 while( md->switchboards )
    101                         msn_sb_destroy( md->switchboards->data );
    102                
    103                 msn_msgq_purge( ic, &md->msgq );
    104                 msn_soapq_flush( ic, FALSE );
    105                
    106                 for( i = 0; i < sizeof( md->tokens ) / sizeof( md->tokens[0] ); i ++ )
    107                         g_free( md->tokens[i] );
    108                 g_free( md->lock_key );
    109                 g_free( md->pp_policy );
    110                 g_free( md->uuid );
    111                
    112                 while( md->groups )
    113                 {
     95
     96                msn_ns_close(md->ns);
     97
     98                while (md->switchboards) {
     99                        msn_sb_destroy(md->switchboards->data);
     100                }
     101
     102                msn_msgq_purge(ic, &md->msgq);
     103                msn_soapq_flush(ic, FALSE);
     104
     105                for (i = 0; i < sizeof(md->tokens) / sizeof(md->tokens[0]); i++) {
     106                        g_free(md->tokens[i]);
     107                }
     108                g_free(md->lock_key);
     109                g_free(md->pp_policy);
     110                g_free(md->uuid);
     111
     112                while (md->groups) {
    114113                        struct msn_group *mg = md->groups->data;
    115                         g_free( mg->id );
    116                         g_free( mg->name );
    117                         g_free( mg );
    118                         md->groups = g_slist_remove( md->groups, mg );
    119                 }
    120                
    121                 g_free( md->profile_rid );
    122                
    123                 if( md->domaintree )
    124                         g_tree_destroy( md->domaintree );
     114                        g_free(mg->id);
     115                        g_free(mg->name);
     116                        g_free(mg);
     117                        md->groups = g_slist_remove(md->groups, mg);
     118                }
     119
     120                g_free(md->profile_rid);
     121
     122                if (md->domaintree) {
     123                        g_tree_destroy(md->domaintree);
     124                }
    125125                md->domaintree = NULL;
    126                
    127                 while( md->grpq )
    128                 {
     126
     127                while (md->grpq) {
    129128                        struct msn_groupadd *ga = md->grpq->data;
    130                         g_free( ga->group );
    131                         g_free( ga->who );
    132                         g_free( ga );
    133                         md->grpq = g_slist_remove( md->grpq, ga );
    134                 }
    135                
    136                 g_free( md );
    137         }
    138        
    139         for( l = ic->permit; l; l = l->next )
    140                 g_free( l->data );
    141         g_slist_free( ic->permit );
    142        
    143         for( l = ic->deny; l; l = l->next )
    144                 g_free( l->data );
    145         g_slist_free( ic->deny );
    146        
    147         msn_connections = g_slist_remove( msn_connections, ic );
    148 }
    149 
    150 static int msn_buddy_msg( struct im_connection *ic, char *who, char *message, int away )
    151 {
    152         struct bee_user *bu = bee_user_by_handle( ic->bee, ic, who );
     129                        g_free(ga->group);
     130                        g_free(ga->who);
     131                        g_free(ga);
     132                        md->grpq = g_slist_remove(md->grpq, ga);
     133                }
     134
     135                g_free(md);
     136        }
     137
     138        for (l = ic->permit; l; l = l->next) {
     139                g_free(l->data);
     140        }
     141        g_slist_free(ic->permit);
     142
     143        for (l = ic->deny; l; l = l->next) {
     144                g_free(l->data);
     145        }
     146        g_slist_free(ic->deny);
     147
     148        msn_connections = g_slist_remove(msn_connections, ic);
     149}
     150
     151static int msn_buddy_msg(struct im_connection *ic, char *who, char *message, int away)
     152{
     153        struct bee_user *bu = bee_user_by_handle(ic->bee, ic, who);
    153154        struct msn_buddy_data *bd = bu ? bu->data : NULL;
    154155        struct msn_switchboard *sb;
    155        
     156
    156157#ifdef DEBUG
    157         if( strcmp( who, "raw" ) == 0 )
    158         {
    159                 msn_ns_write( ic, -1, "%s\r\n", message );
    160         }
    161         else
     158        if (strcmp(who, "raw") == 0) {
     159                msn_ns_write(ic, -1, "%s\r\n", message);
     160        } else
    162161#endif
    163         if( bd && bd->flags & MSN_BUDDY_FED )
    164         {
    165                 msn_ns_sendmessage( ic, bu, message );
    166         }
    167         else if( ( sb = msn_sb_by_handle( ic, who ) ) )
    168         {
    169                 return( msn_sb_sendmessage( sb, message ) );
    170         }
    171         else
    172         {
     162        if (bd && bd->flags & MSN_BUDDY_FED) {
     163                msn_ns_sendmessage(ic, bu, message);
     164        } else if ((sb = msn_sb_by_handle(ic, who))) {
     165                return(msn_sb_sendmessage(sb, message));
     166        } else {
    173167                struct msn_message *m;
    174                
     168
    175169                /* Create a message. We have to arrange a usable switchboard, and send the message later. */
    176                 m = g_new0( struct msn_message, 1 );
    177                 m->who = g_strdup( who );
    178                 m->text = g_strdup( message );
    179                
    180                 return msn_sb_write_msg( ic, m );
    181         }
    182        
    183         return( 0 );
    184 }
    185 
    186 static GList *msn_away_states( struct im_connection *ic )
     170                m = g_new0(struct msn_message, 1);
     171                m->who = g_strdup(who);
     172                m->text = g_strdup(message);
     173
     174                return msn_sb_write_msg(ic, m);
     175        }
     176
     177        return(0);
     178}
     179
     180static GList *msn_away_states(struct im_connection *ic)
    187181{
    188182        static GList *l = NULL;
    189183        int i;
    190        
    191         if( l == NULL )
    192                 for( i = 0; *msn_away_state_list[i].code; i ++ )
    193                         if( *msn_away_state_list[i].name )
    194                                 l = g_list_append( l, (void*) msn_away_state_list[i].name );
    195        
     184
     185        if (l == NULL) {
     186                for (i = 0; *msn_away_state_list[i].code; i++) {
     187                        if (*msn_away_state_list[i].name) {
     188                                l = g_list_append(l, (void *) msn_away_state_list[i].name);
     189                        }
     190                }
     191        }
     192
    196193        return l;
    197194}
    198195
    199 static void msn_set_away( struct im_connection *ic, char *state, char *message )
     196static void msn_set_away(struct im_connection *ic, char *state, char *message)
    200197{
    201198        char *uux;
    202199        struct msn_data *md = ic->proto_data;
    203        
    204         if( state == NULL )
     200
     201        if (state == NULL) {
    205202                md->away_state = msn_away_state_list;
    206         else if( ( md->away_state = msn_away_state_by_name( state ) ) == NULL )
     203        } else if ((md->away_state = msn_away_state_by_name(state)) == NULL) {
    207204                md->away_state = msn_away_state_list + 1;
    208        
    209         if( !msn_ns_write( ic, -1, "CHG %d %s %d:%02d\r\n", ++md->trId, md->away_state->code, MSN_CAP1, MSN_CAP2 ) )
     205        }
     206
     207        if (!msn_ns_write(ic, -1, "CHG %d %s %d:%02d\r\n", ++md->trId, md->away_state->code, MSN_CAP1, MSN_CAP2)) {
    210208                return;
    211        
    212         uux = g_markup_printf_escaped( "<EndpointData><Capabilities>%d:%02d"
    213                                        "</Capabilities></EndpointData>",
    214                                        MSN_CAP1, MSN_CAP2 );
    215         msn_ns_write( ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux );
    216         g_free( uux );
    217        
    218         uux = g_markup_printf_escaped( "<PrivateEndpointData><EpName>%s</EpName>"
    219                                        "<Idle>%s</Idle><ClientType>%d</ClientType>"
    220                                        "<State>%s</State></PrivateEndpointData>",
    221                                        md->uuid,
    222                                        strcmp( md->away_state->code, "IDL" ) ? "false" : "true",
    223                                        1, /* ? */
    224                                        md->away_state->code );
    225         msn_ns_write( ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux );
    226         g_free( uux );
    227        
    228         uux = g_markup_printf_escaped( "<Data><DDP></DDP><PSM>%s</PSM>"
    229                                        "<CurrentMedia></CurrentMedia>"
    230                                        "<MachineGuid>%s</MachineGuid></Data>",
    231                                        message ? message : "", md->uuid );
    232         msn_ns_write( ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux );
    233         g_free( uux );
    234 }
    235 
    236 static void msn_get_info(struct im_connection *ic, char *who)
     209        }
     210
     211        uux = g_markup_printf_escaped("<EndpointData><Capabilities>%d:%02d"
     212                                      "</Capabilities></EndpointData>",
     213                                      MSN_CAP1, MSN_CAP2);
     214        msn_ns_write(ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen(uux), uux);
     215        g_free(uux);
     216
     217        uux = g_markup_printf_escaped("<PrivateEndpointData><EpName>%s</EpName>"
     218                                      "<Idle>%s</Idle><ClientType>%d</ClientType>"
     219                                      "<State>%s</State></PrivateEndpointData>",
     220                                      md->uuid,
     221                                      strcmp(md->away_state->code, "IDL") ? "false" : "true",
     222                                      1,  /* ? */
     223                                      md->away_state->code);
     224        msn_ns_write(ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen(uux), uux);
     225        g_free(uux);
     226
     227        uux = g_markup_printf_escaped("<Data><DDP></DDP><PSM>%s</PSM>"
     228                                      "<CurrentMedia></CurrentMedia>"
     229                                      "<MachineGuid>%s</MachineGuid></Data>",
     230                                      message ? message : "", md->uuid);
     231        msn_ns_write(ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen(uux), uux);
     232        g_free(uux);
     233}
     234
     235static void msn_get_info(struct im_connection *ic, char *who)
    237236{
    238237        /* Just make an URL and let the user fetch the info */
    239         imcb_log( ic, "%s\n%s: %s%s", _("User Info"), _("For now, fetch yourself"), PROFILE_URL, who );
    240 }
    241 
    242 static void msn_add_buddy( struct im_connection *ic, char *who, char *group )
    243 {
    244         struct bee_user *bu = bee_user_by_handle( ic->bee, ic, who );
    245        
    246         msn_buddy_list_add( ic, MSN_BUDDY_FL, who, who, group );
    247         if( bu && bu->group )
    248                 msn_buddy_list_remove( ic, MSN_BUDDY_FL, who, bu->group->name );
    249 }
    250 
    251 static void msn_remove_buddy( struct im_connection *ic, char *who, char *group )
    252 {
    253         msn_buddy_list_remove( ic, MSN_BUDDY_FL, who, NULL );
    254 }
    255 
    256 static void msn_chat_msg( struct groupchat *c, char *message, int flags )
    257 {
    258         struct msn_switchboard *sb = msn_sb_by_chat( c );
    259        
    260         if( sb )
    261                 msn_sb_sendmessage( sb, message );
     238        imcb_log(ic, "%s\n%s: %s%s", _("User Info"), _("For now, fetch yourself"), PROFILE_URL, who);
     239}
     240
     241static void msn_add_buddy(struct im_connection *ic, char *who, char *group)
     242{
     243        struct bee_user *bu = bee_user_by_handle(ic->bee, ic, who);
     244
     245        msn_buddy_list_add(ic, MSN_BUDDY_FL, who, who, group);
     246        if (bu && bu->group) {
     247                msn_buddy_list_remove(ic, MSN_BUDDY_FL, who, bu->group->name);
     248        }
     249}
     250
     251static void msn_remove_buddy(struct im_connection *ic, char *who, char *group)
     252{
     253        msn_buddy_list_remove(ic, MSN_BUDDY_FL, who, NULL);
     254}
     255
     256static void msn_chat_msg(struct groupchat *c, char *message, int flags)
     257{
     258        struct msn_switchboard *sb = msn_sb_by_chat(c);
     259
     260        if (sb) {
     261                msn_sb_sendmessage(sb, message);
     262        }
    262263        /* FIXME: Error handling (although this can't happen unless something's
    263264           already severely broken) disappeared here! */
    264265}
    265266
    266 static void msn_chat_invite( struct groupchat *c, char *who, char *message )
    267 {
    268         struct msn_switchboard *sb = msn_sb_by_chat( c );
    269        
    270         if( sb )
    271                 msn_sb_write( sb, "CAL %d %s\r\n", ++sb->trId, who );
    272 }
    273 
    274 static void msn_chat_leave( struct groupchat *c )
    275 {
    276         struct msn_switchboard *sb = msn_sb_by_chat( c );
    277        
    278         if( sb )
    279                 msn_sb_write( sb, "OUT\r\n" );
    280 }
    281 
    282 static struct groupchat *msn_chat_with( struct im_connection *ic, char *who )
     267static void msn_chat_invite(struct groupchat *c, char *who, char *message)
     268{
     269        struct msn_switchboard *sb = msn_sb_by_chat(c);
     270
     271        if (sb) {
     272                msn_sb_write(sb, "CAL %d %s\r\n", ++sb->trId, who);
     273        }
     274}
     275
     276static void msn_chat_leave(struct groupchat *c)
     277{
     278        struct msn_switchboard *sb = msn_sb_by_chat(c);
     279
     280        if (sb) {
     281                msn_sb_write(sb, "OUT\r\n");
     282        }
     283}
     284
     285static struct groupchat *msn_chat_with(struct im_connection *ic, char *who)
    283286{
    284287        struct msn_switchboard *sb;
    285         struct groupchat *c = imcb_chat_new( ic, who );
    286        
    287         if( ( sb = msn_sb_by_handle( ic, who ) ) )
    288         {
    289                 debug( "Converting existing switchboard to %s to a groupchat", who );
    290                 return msn_sb_to_chat( sb );
    291         }
    292         else
    293         {
     288        struct groupchat *c = imcb_chat_new(ic, who);
     289
     290        if ((sb = msn_sb_by_handle(ic, who))) {
     291                debug("Converting existing switchboard to %s to a groupchat", who);
     292                return msn_sb_to_chat(sb);
     293        } else {
    294294                struct msn_message *m;
    295                
     295
    296296                /* Create a magic message. This is quite hackish, but who cares? :-P */
    297                 m = g_new0( struct msn_message, 1 );
    298                 m->who = g_strdup( who );
    299                 m->text = g_strdup( GROUPCHAT_SWITCHBOARD_MESSAGE );
    300                
    301                 msn_sb_write_msg( ic, m );
     297                m = g_new0(struct msn_message, 1);
     298                m->who = g_strdup(who);
     299                m->text = g_strdup(GROUPCHAT_SWITCHBOARD_MESSAGE);
     300
     301                msn_sb_write_msg(ic, m);
    302302
    303303                return c;
     
    305305}
    306306
    307 static void msn_keepalive( struct im_connection *ic )
    308 {
    309         msn_ns_write( ic, -1, "PNG\r\n" );
    310 }
    311 
    312 static void msn_add_permit( struct im_connection *ic, char *who )
    313 {
    314         msn_buddy_list_add( ic, MSN_BUDDY_AL, who, who, NULL );
    315 }
    316 
    317 static void msn_rem_permit( struct im_connection *ic, char *who )
    318 {
    319         msn_buddy_list_remove( ic, MSN_BUDDY_AL, who, NULL );
    320 }
    321 
    322 static void msn_add_deny( struct im_connection *ic, char *who )
     307static void msn_keepalive(struct im_connection *ic)
     308{
     309        msn_ns_write(ic, -1, "PNG\r\n");
     310}
     311
     312static void msn_add_permit(struct im_connection *ic, char *who)
     313{
     314        msn_buddy_list_add(ic, MSN_BUDDY_AL, who, who, NULL);
     315}
     316
     317static void msn_rem_permit(struct im_connection *ic, char *who)
     318{
     319        msn_buddy_list_remove(ic, MSN_BUDDY_AL, who, NULL);
     320}
     321
     322static void msn_add_deny(struct im_connection *ic, char *who)
    323323{
    324324        struct msn_switchboard *sb;
    325        
    326         msn_buddy_list_add( ic, MSN_BUDDY_BL, who, who, NULL );
    327        
     325
     326        msn_buddy_list_add(ic, MSN_BUDDY_BL, who, who, NULL);
     327
    328328        /* If there's still a conversation with this person, close it. */
    329         if( ( sb = msn_sb_by_handle( ic, who ) ) )
    330         {
    331                 msn_sb_destroy( sb );
    332         }
    333 }
    334 
    335 static void msn_rem_deny( struct im_connection *ic, char *who )
    336 {
    337         msn_buddy_list_remove( ic, MSN_BUDDY_BL, who, NULL );
    338 }
    339 
    340 static int msn_send_typing( struct im_connection *ic, char *who, int typing )
    341 {
    342         struct bee_user *bu = bee_user_by_handle( ic->bee, ic, who );
    343        
    344         if( !( bu->flags & BEE_USER_ONLINE ) )
     329        if ((sb = msn_sb_by_handle(ic, who))) {
     330                msn_sb_destroy(sb);
     331        }
     332}
     333
     334static void msn_rem_deny(struct im_connection *ic, char *who)
     335{
     336        msn_buddy_list_remove(ic, MSN_BUDDY_BL, who, NULL);
     337}
     338
     339static int msn_send_typing(struct im_connection *ic, char *who, int typing)
     340{
     341        struct bee_user *bu = bee_user_by_handle(ic->bee, ic, who);
     342
     343        if (!(bu->flags & BEE_USER_ONLINE)) {
    345344                return 0;
    346         else if( typing & OPT_TYPING )
    347                 return( msn_buddy_msg( ic, who, TYPING_NOTIFICATION_MESSAGE, 0 ) );
    348         else
     345        } else if (typing & OPT_TYPING) {
     346                return(msn_buddy_msg(ic, who, TYPING_NOTIFICATION_MESSAGE, 0));
     347        } else {
    349348                return 1;
    350 }
    351 
    352 static char *set_eval_display_name( set_t *set, char *value )
     349        }
     350}
     351
     352static char *set_eval_display_name(set_t *set, char *value)
    353353{
    354354        account_t *acc = set->data;
    355355        struct im_connection *ic = acc->ic;
    356356        struct msn_data *md = ic->proto_data;
    357        
    358         if( md->flags & MSN_EMAIL_UNVERIFIED )
    359                 imcb_log( ic, "Warning: Your e-mail address is unverified. MSN doesn't allow "
    360                               "changing your display name until your e-mail address is verified." );
    361        
    362         if( md->flags & MSN_GOT_PROFILE_DN )
    363                 msn_soap_profile_set_dn( ic, value );
    364         else
    365                 msn_soap_addressbook_set_display_name( ic, value );
    366        
    367         return msn_ns_set_display_name( ic, value ) ? value : NULL;
    368 }
    369 
    370 static void msn_buddy_data_add( bee_user_t *bu )
     357
     358        if (md->flags & MSN_EMAIL_UNVERIFIED) {
     359                imcb_log(ic, "Warning: Your e-mail address is unverified. MSN doesn't allow "
     360                         "changing your display name until your e-mail address is verified.");
     361        }
     362
     363        if (md->flags & MSN_GOT_PROFILE_DN) {
     364                msn_soap_profile_set_dn(ic, value);
     365        } else {
     366                msn_soap_addressbook_set_display_name(ic, value);
     367        }
     368
     369        return msn_ns_set_display_name(ic, value) ? value : NULL;
     370}
     371
     372static void msn_buddy_data_add(bee_user_t *bu)
    371373{
    372374        struct msn_data *md = bu->ic->proto_data;
    373375        struct msn_buddy_data *bd;
    374376        char *handle;
    375        
    376         bd = bu->data = g_new0( struct msn_buddy_data, 1 );
    377         g_tree_insert( md->domaintree, bu->handle, bu );
    378        
    379         for( handle = bu->handle; g_ascii_isdigit( *handle ); handle ++ );
    380         if( *handle == ':' )
    381         {
     377
     378        bd = bu->data = g_new0(struct msn_buddy_data, 1);
     379        g_tree_insert(md->domaintree, bu->handle, bu);
     380
     381        for (handle = bu->handle; g_ascii_isdigit(*handle); handle++) {
     382                ;
     383        }
     384        if (*handle == ':') {
    382385                /* Pass a nick hint so hopefully the stupid numeric prefix
    383386                   won't show up to the user.  */
    384                 char *s = strchr( ++handle, '@' );
    385                 if( s )
    386                 {
    387                         handle = g_strndup( handle, s - handle );
    388                         imcb_buddy_nick_hint( bu->ic, bu->handle, handle );
    389                         g_free( handle );
    390                 }
    391                
     387                char *s = strchr(++handle, '@');
     388                if (s) {
     389                        handle = g_strndup(handle, s - handle);
     390                        imcb_buddy_nick_hint(bu->ic, bu->handle, handle);
     391                        g_free(handle);
     392                }
     393
    392394                bd->flags |= MSN_BUDDY_FED;
    393395        }
    394396}
    395397
    396 static void msn_buddy_data_free( bee_user_t *bu )
     398static void msn_buddy_data_free(bee_user_t *bu)
    397399{
    398400        struct msn_data *md = bu->ic->proto_data;
    399401        struct msn_buddy_data *bd = bu->data;
    400        
    401         g_free( bd->cid );
    402         g_free( bd );
    403        
    404         g_tree_remove( md->domaintree, bu->handle );
    405 }
    406 
    407 GList *msn_buddy_action_list( bee_user_t *bu )
     402
     403        g_free(bd->cid);
     404        g_free(bd);
     405
     406        g_tree_remove(md->domaintree, bu->handle);
     407}
     408
     409GList *msn_buddy_action_list(bee_user_t *bu)
    408410{
    409411        static GList *ret = NULL;
    410        
    411         if( ret == NULL )
    412         {
     412
     413        if (ret == NULL) {
    413414                static const struct buddy_action ba[2] = {
    414415                        { "NUDGE", "Draw attention" },
    415416                };
    416                
    417                 ret = g_list_prepend( ret, (void*) ba + 0 );
    418         }
    419        
     417
     418                ret = g_list_prepend(ret, (void *) ba + 0);
     419        }
     420
    420421        return ret;
    421422}
    422423
    423 void *msn_buddy_action( struct bee_user *bu, const char *action, char * const args[], void *data )
    424 {
    425         if( g_strcasecmp( action, "NUDGE" ) == 0 )
    426                 msn_buddy_msg( bu->ic, bu->handle, NUDGE_MESSAGE, 0 );
    427        
     424void *msn_buddy_action(struct bee_user *bu, const char *action, char * const args[], void *data)
     425{
     426        if (g_strcasecmp(action, "NUDGE") == 0) {
     427                msn_buddy_msg(bu->ic, bu->handle, NUDGE_MESSAGE, 0);
     428        }
     429
    428430        return NULL;
    429431}
     
    432434{
    433435        struct prpl *ret = g_new0(struct prpl, 1);
    434        
     436
    435437        ret->name = "msn";
    436438        ret->mms = 1409;         /* this guess taken from libotr UPGRADING file */
     
    459461        ret->buddy_action_list = msn_buddy_action_list;
    460462        ret->buddy_action = msn_buddy_action;
    461        
     463
    462464        //ret->transfer_request = msn_ftp_transfer_request;
    463465
  • protocols/msn/msn.h

    raf359b4 r5ebff60  
    1   /********************************************************************\
     1/********************************************************************\
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
     
    3535
    3636#ifdef DEBUG_MSN
    37 #define debug( text... ) imcb_log( ic, text );
     37#define debug(text ...) imcb_log(ic, text);
    3838#else
    39 #define debug( text... )
     39#define debug(text ...)
    4040#endif
    4141
     
    6969
    7070#define MSN_MESSAGE_HEADERS "MIME-Version: 1.0\r\n" \
    71                             "Content-Type: text/plain; charset=UTF-8\r\n" \
    72                             "User-Agent: BitlBee " BITLBEE_VERSION "\r\n" \
    73                             "X-MMS-IM-Format: FN=MS%20Shell%20Dlg; EF=; CO=0; CS=0; PF=0\r\n" \
    74                             "\r\n"
     71        "Content-Type: text/plain; charset=UTF-8\r\n" \
     72        "User-Agent: BitlBee " BITLBEE_VERSION "\r\n" \
     73        "X-MMS-IM-Format: FN=MS%20Shell%20Dlg; EF=; CO=0; CS=0; PF=0\r\n" \
     74        "\r\n"
    7575
    7676#define MSN_TYPING_HEADERS "MIME-Version: 1.0\r\n" \
    77                            "Content-Type: text/x-msmsgscontrol\r\n" \
    78                            "TypingUser: %s\r\n" \
    79                            "\r\n\r\n"
     77        "Content-Type: text/x-msmsgscontrol\r\n" \
     78        "TypingUser: %s\r\n" \
     79        "\r\n\r\n"
    8080
    8181#define MSN_NUDGE_HEADERS "MIME-Version: 1.0\r\n" \
    82                           "Content-Type: text/x-msnmsgr-datacast\r\n" \
    83                           "\r\n" \
    84                           "ID: 1\r\n" \
    85                           "\r\n"
     82        "Content-Type: text/x-msnmsgr-datacast\r\n" \
     83        "\r\n" \
     84        "ID: 1\r\n" \
     85        "\r\n"
    8686
    8787#define MSN_SB_KEEPALIVE_HEADERS "MIME-Version: 1.0\r\n" \
    88                                  "Content-Type: text/x-ping\r\n" \
    89                                  "\r\n\r\n"
     88        "Content-Type: text/x-ping\r\n" \
     89        "\r\n\r\n"
    9090
    9191#define PROFILE_URL "http://members.msn.com/"
    9292
    93 typedef enum
    94 {
     93typedef enum {
    9594        MSN_GOT_PROFILE = 1,
    9695        MSN_GOT_PROFILE_DN = 2,
     
    10099} msn_flags_t;
    101100
    102 struct msn_handler_data
    103 {
     101struct msn_handler_data {
    104102        int fd, inpa;
    105103        int rxlen;
    106104        char *rxq;
    107        
     105
    108106        int msglen;
    109107        char *cmd_text;
    110        
     108
    111109        /* Either ic or sb */
    112110        gpointer data;
    113        
    114         int (*exec_command) ( struct msn_handler_data *handler, char **cmd, int count );
    115         int (*exec_message) ( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int count );
    116 };
    117 
    118 struct msn_data
    119 {
     111
     112        int (*exec_command) (struct msn_handler_data *handler, char **cmd, int count);
     113        int (*exec_message) (struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int count);
     114};
     115
     116struct msn_data {
    120117        struct im_connection *ic;
    121        
     118
    122119        struct msn_handler_data ns[1];
    123120        msn_flags_t flags;
    124        
     121
    125122        int trId;
    126123        char *tokens[4];
    127124        char *lock_key, *pp_policy;
    128125        char *uuid;
    129        
     126
    130127        GSList *msgq, *grpq, *soapq;
    131128        GSList *switchboards;
    132129        int sb_failures;
    133130        time_t first_sb_failure;
    134        
     131
    135132        const struct msn_away_state *away_state;
    136133        GSList *groups;
    137134        char *profile_rid;
    138        
     135
    139136        /* Mostly used for sending the ADL command; since MSNP13 the client
    140137           is responsible for downloading the contact list and then sending
     
    144141};
    145142
    146 struct msn_switchboard
    147 {
     143struct msn_switchboard {
    148144        struct im_connection *ic;
    149        
     145
    150146        /* The following two are also in the handler. TODO: Clean up. */
    151147        int fd;
     
    153149        struct msn_handler_data *handler;
    154150        gint keepalive;
    155        
     151
    156152        int trId;
    157153        int ready;
    158        
     154
    159155        int session;
    160156        char *key;
    161        
     157
    162158        GSList *msgq;
    163159        char *who;
     
    165161};
    166162
    167 struct msn_away_state
    168 {
     163struct msn_away_state {
    169164        char code[4];
    170165        char name[16];
    171166};
    172167
    173 struct msn_status_code
    174 {
     168struct msn_status_code {
    175169        int number;
    176170        char *text;
     
    178172};
    179173
    180 struct msn_message
    181 {
     174struct msn_message {
    182175        char *who;
    183176        char *text;
    184177};
    185178
    186 struct msn_groupadd
    187 {
     179struct msn_groupadd {
    188180        char *who;
    189181        char *group;
    190182};
    191183
    192 typedef enum
    193 {
     184typedef enum {
    194185        MSN_BUDDY_FL = 1,   /* Warning: FL,AL,BL *must* be 1,2,4. */
    195186        MSN_BUDDY_AL = 2,
     
    201192} msn_buddy_flags_t;
    202193
    203 struct msn_buddy_data
    204 {
     194struct msn_buddy_data {
    205195        char *cid;
    206196        msn_buddy_flags_t flags;
    207197};
    208198
    209 struct msn_group
    210 {
     199struct msn_group {
    211200        char *name;
    212201        char *id;
     
    216205#define STATUS_FATAL            1
    217206#define STATUS_SB_FATAL         2
    218 #define STATUS_SB_IM_SPARE      4       /* Make one-to-one conversation switchboard available again, invite failed. */
    219 #define STATUS_SB_CHAT_SPARE    8       /* Same, but also for groupchats (not used yet). */
     207#define STATUS_SB_IM_SPARE      4       /* Make one-to-one conversation switchboard available again, invite failed. */
     208#define STATUS_SB_CHAT_SPARE    8       /* Same, but also for groupchats (not used yet). */
    220209
    221210extern int msn_chat_id;
     
    232221
    233222/* ns.c */
    234 int msn_ns_write( struct im_connection *ic, int fd, const char *fmt, ... ) G_GNUC_PRINTF( 3, 4 );
    235 gboolean msn_ns_connect( struct im_connection *ic, struct msn_handler_data *handler, const char *host, int port );
    236 void msn_ns_close( struct msn_handler_data *handler );
    237 void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error );
    238 void msn_auth_got_contact_list( struct im_connection *ic );
    239 int msn_ns_finish_login( struct im_connection *ic );
    240 int msn_ns_sendmessage( struct im_connection *ic, struct bee_user *bu, const char *text );
    241 void msn_ns_oim_send_queue( struct im_connection *ic, GSList **msgq );
     223int msn_ns_write(struct im_connection *ic, int fd, const char *fmt, ...) G_GNUC_PRINTF(3, 4);
     224gboolean msn_ns_connect(struct im_connection *ic, struct msn_handler_data *handler, const char *host, int port);
     225void msn_ns_close(struct msn_handler_data *handler);
     226void msn_auth_got_passport_token(struct im_connection *ic, const char *token, const char *error);
     227void msn_auth_got_contact_list(struct im_connection *ic);
     228int msn_ns_finish_login(struct im_connection *ic);
     229int msn_ns_sendmessage(struct im_connection *ic, struct bee_user *bu, const char *text);
     230void msn_ns_oim_send_queue(struct im_connection *ic, GSList **msgq);
    242231
    243232/* msn_util.c */
    244 int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname_, const char *group );
    245 int msn_buddy_list_remove( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *group );
    246 void msn_buddy_ask( bee_user_t *bu );
    247 char **msn_linesplit( char *line );
    248 int msn_handler( struct msn_handler_data *h );
    249 void msn_msgq_purge( struct im_connection *ic, GSList **list );
    250 char *msn_p11_challenge( char *challenge );
    251 gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ );
    252 struct msn_group *msn_group_by_name( struct im_connection *ic, const char *name );
    253 struct msn_group *msn_group_by_id( struct im_connection *ic, const char *id );
    254 int msn_ns_set_display_name( struct im_connection *ic, const char *value );
    255 const char *msn_normalize_handle( const char *handle );
     233int msn_buddy_list_add(struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname_,
     234                       const char *group);
     235int msn_buddy_list_remove(struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *group);
     236void msn_buddy_ask(bee_user_t *bu);
     237char **msn_linesplit(char *line);
     238int msn_handler(struct msn_handler_data *h);
     239void msn_msgq_purge(struct im_connection *ic, GSList **list);
     240char *msn_p11_challenge(char *challenge);
     241gint msn_domaintree_cmp(gconstpointer a_, gconstpointer b_);
     242struct msn_group *msn_group_by_name(struct im_connection *ic, const char *name);
     243struct msn_group *msn_group_by_id(struct im_connection *ic, const char *id);
     244int msn_ns_set_display_name(struct im_connection *ic, const char *value);
     245const char *msn_normalize_handle(const char *handle);
    256246
    257247/* tables.c */
    258 const struct msn_away_state *msn_away_state_by_number( int number );
    259 const struct msn_away_state *msn_away_state_by_code( char *code );
    260 const struct msn_away_state *msn_away_state_by_name( char *name );
    261 const struct msn_status_code *msn_status_by_number( int number );
     248const struct msn_away_state *msn_away_state_by_number(int number);
     249const struct msn_away_state *msn_away_state_by_code(char *code);
     250const struct msn_away_state *msn_away_state_by_name(char *name);
     251const struct msn_status_code *msn_status_by_number(int number);
    262252
    263253/* sb.c */
    264 int msn_sb_write( struct msn_switchboard *sb, const char *fmt, ... ) G_GNUC_PRINTF( 2, 3 );;
    265 struct msn_switchboard *msn_sb_create( struct im_connection *ic, char *host, int port, char *key, int session );
    266 struct msn_switchboard *msn_sb_by_handle( struct im_connection *ic, const char *handle );
    267 struct msn_switchboard *msn_sb_by_chat( struct groupchat *c );
    268 struct msn_switchboard *msn_sb_spare( struct im_connection *ic );
    269 int msn_sb_sendmessage( struct msn_switchboard *sb, char *text );
    270 struct groupchat *msn_sb_to_chat( struct msn_switchboard *sb );
    271 void msn_sb_destroy( struct msn_switchboard *sb );
    272 gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond );
    273 int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m );
    274 void msn_sb_start_keepalives( struct msn_switchboard *sb, gboolean initial );
    275 void msn_sb_stop_keepalives( struct msn_switchboard *sb );
     254int msn_sb_write(struct msn_switchboard *sb, const char *fmt, ...) G_GNUC_PRINTF(2, 3);;
     255struct msn_switchboard *msn_sb_create(struct im_connection *ic, char *host, int port, char *key, int session);
     256struct msn_switchboard *msn_sb_by_handle(struct im_connection *ic, const char *handle);
     257struct msn_switchboard *msn_sb_by_chat(struct groupchat *c);
     258struct msn_switchboard *msn_sb_spare(struct im_connection *ic);
     259int msn_sb_sendmessage(struct msn_switchboard *sb, char *text);
     260struct groupchat *msn_sb_to_chat(struct msn_switchboard *sb);
     261void msn_sb_destroy(struct msn_switchboard *sb);
     262gboolean msn_sb_connected(gpointer data, gint source, b_input_condition cond);
     263int msn_sb_write_msg(struct im_connection *ic, struct msn_message *m);
     264void msn_sb_start_keepalives(struct msn_switchboard *sb, gboolean initial);
     265void msn_sb_stop_keepalives(struct msn_switchboard *sb);
    276266
    277267#endif //_MSN_H
  • protocols/msn/msn_util.c

    raf359b4 r5ebff60  
    1   /********************************************************************\
     1/********************************************************************\
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
     
    3030#include <ctype.h>
    3131
    32 static char *adlrml_entry( const char *handle_, msn_buddy_flags_t list )
    33 {
    34         char *domain, handle[strlen(handle_)+1];
    35        
    36         strcpy( handle, handle_ );
    37         if( ( domain = strchr( handle, '@' ) ) )
     32static char *adlrml_entry(const char *handle_, msn_buddy_flags_t list)
     33{
     34        char *domain, handle[strlen(handle_) + 1];
     35
     36        strcpy(handle, handle_);
     37        if ((domain = strchr(handle, '@'))) {
    3838                *(domain++) = '\0';
    39         else
     39        } else {
    4040                return NULL;
    41        
    42         return g_markup_printf_escaped( "<ml><d n=\"%s\"><c n=\"%s\" l=\"%d\" t=\"1\"/></d></ml>",
    43                 domain, handle, list );
    44 }
    45 
    46 int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname, const char *group )
     41        }
     42
     43        return g_markup_printf_escaped("<ml><d n=\"%s\"><c n=\"%s\" l=\"%d\" t=\"1\"/></d></ml>",
     44                                       domain, handle, list);
     45}
     46
     47int msn_buddy_list_add(struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname,
     48                       const char *group)
    4749{
    4850        struct msn_data *md = ic->proto_data;
     
    5153        struct msn_buddy_data *bd;
    5254        char *adl;
    53        
     55
    5456        *groupid = '\0';
    5557#if 0
    56         if( group )
    57         {
     58        if (group) {
    5859                int i;
    59                 for( i = 0; i < md->groupcount; i ++ )
    60                         if( g_strcasecmp( md->grouplist[i], group ) == 0 )
    61                         {
    62                                 g_snprintf( groupid, sizeof( groupid ), " %d", i );
     60                for (i = 0; i < md->groupcount; i++) {
     61                        if (g_strcasecmp(md->grouplist[i], group) == 0) {
     62                                g_snprintf(groupid, sizeof(groupid), " %d", i);
    6363                                break;
    6464                        }
    65                
    66                 if( *groupid == '\0' )
    67                 {
     65                }
     66
     67                if (*groupid == '\0') {
    6868                        /* Have to create this group, it doesn't exist yet. */
    6969                        struct msn_groupadd *ga;
    7070                        GSList *l;
    71                        
    72                         for( l = md->grpq; l; l = l->next )
    73                         {
     71
     72                        for (l = md->grpq; l; l = l->next) {
    7473                                ga = l->data;
    75                                 if( g_strcasecmp( ga->group, group ) == 0 )
     74                                if (g_strcasecmp(ga->group, group) == 0) {
    7675                                        break;
    77                         }
    78                        
    79                         ga = g_new0( struct msn_groupadd, 1 );
    80                         ga->who = g_strdup( who );
    81                         ga->group = g_strdup( group );
    82                         md->grpq = g_slist_prepend( md->grpq, ga );
    83                        
    84                         if( l == NULL )
    85                         {
    86                                 char groupname[strlen(group)+1];
    87                                 strcpy( groupname, group );
    88                                 http_encode( groupname );
    89                                 g_snprintf( buf, sizeof( buf ), "ADG %d %s %d\r\n", ++md->trId, groupname, 0 );
    90                                 return msn_write( ic, buf, strlen( buf ) );
    91                         }
    92                         else
    93                         {
     76                                }
     77                        }
     78
     79                        ga = g_new0(struct msn_groupadd, 1);
     80                        ga->who = g_strdup(who);
     81                        ga->group = g_strdup(group);
     82                        md->grpq = g_slist_prepend(md->grpq, ga);
     83
     84                        if (l == NULL) {
     85                                char groupname[strlen(group) + 1];
     86                                strcpy(groupname, group);
     87                                http_encode(groupname);
     88                                g_snprintf(buf, sizeof(buf), "ADG %d %s %d\r\n", ++md->trId, groupname, 0);
     89                                return msn_write(ic, buf, strlen(buf));
     90                        } else {
    9491                                /* This can happen if the user's doing lots of adds to a
    9592                                   new group at once; we're still waiting for the server
     
    10097        }
    10198#endif
    102        
    103         if( !( ( bu = bee_user_by_handle( ic->bee, ic, who ) ) ||
    104                ( bu = bee_user_new( ic->bee, ic, who, 0 ) ) ) ||
    105             !( bd = bu->data ) || bd->flags & list )
     99
     100        if (!((bu = bee_user_by_handle(ic->bee, ic, who)) ||
     101              (bu = bee_user_new(ic->bee, ic, who, 0))) ||
     102            !(bd = bu->data) || bd->flags & list) {
    106103                return 1;
    107        
     104        }
     105
    108106        bd->flags |= list;
    109        
    110         if( list == MSN_BUDDY_FL )
    111                 msn_soap_ab_contact_add( ic, bu );
    112         else
    113                 msn_soap_memlist_edit( ic, who, TRUE, list );
    114        
    115         if( ( adl = adlrml_entry( who, list ) ) )
    116         {
    117                 int st = msn_ns_write( ic, -1, "ADL %d %zd\r\n%s",
    118                                        ++md->trId, strlen( adl ), adl );
    119                 g_free( adl );
    120                
     107
     108        if (list == MSN_BUDDY_FL) {
     109                msn_soap_ab_contact_add(ic, bu);
     110        } else {
     111                msn_soap_memlist_edit(ic, who, TRUE, list);
     112        }
     113
     114        if ((adl = adlrml_entry(who, list))) {
     115                int st = msn_ns_write(ic, -1, "ADL %d %zd\r\n%s",
     116                                      ++md->trId, strlen(adl), adl);
     117                g_free(adl);
     118
    121119                return st;
    122120        }
    123        
     121
    124122        return 1;
    125123}
    126124
    127 int msn_buddy_list_remove( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *group )
     125int msn_buddy_list_remove(struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *group)
    128126{
    129127        struct msn_data *md = ic->proto_data;
     
    132130        struct msn_buddy_data *bd;
    133131        char *adl;
    134        
     132
    135133        *groupid = '\0';
    136134#if 0
    137         if( group )
    138         {
     135        if (group) {
    139136                int i;
    140                 for( i = 0; i < md->groupcount; i ++ )
    141                         if( g_strcasecmp( md->grouplist[i], group ) == 0 )
    142                         {
    143                                 g_snprintf( groupid, sizeof( groupid ), " %d", i );
     137                for (i = 0; i < md->groupcount; i++) {
     138                        if (g_strcasecmp(md->grouplist[i], group) == 0) {
     139                                g_snprintf(groupid, sizeof(groupid), " %d", i);
    144140                                break;
    145141                        }
     142                }
    146143        }
    147144#endif
    148        
    149         if( !( bu = bee_user_by_handle( ic->bee, ic, who ) ) ||
    150             !( bd = bu->data ) || !( bd->flags & list ) )
     145
     146        if (!(bu = bee_user_by_handle(ic->bee, ic, who)) ||
     147            !(bd = bu->data) || !(bd->flags & list)) {
    151148                return 1;
    152        
     149        }
     150
    153151        bd->flags &= ~list;
    154        
    155         if( list == MSN_BUDDY_FL )
    156                 msn_soap_ab_contact_del( ic, bu );
    157         else
    158                 msn_soap_memlist_edit( ic, who, FALSE, list );
    159        
    160         if( ( adl = adlrml_entry( who, list ) ) )
    161         {
    162                 int st = msn_ns_write( ic, -1, "RML %d %zd\r\n%s",
    163                                        ++md->trId, strlen( adl ), adl );
    164                 g_free( adl );
    165                
     152
     153        if (list == MSN_BUDDY_FL) {
     154                msn_soap_ab_contact_del(ic, bu);
     155        } else {
     156                msn_soap_memlist_edit(ic, who, FALSE, list);
     157        }
     158
     159        if ((adl = adlrml_entry(who, list))) {
     160                int st = msn_ns_write(ic, -1, "RML %d %zd\r\n%s",
     161                                      ++md->trId, strlen(adl), adl);
     162                g_free(adl);
     163
    166164                return st;
    167165        }
    168        
     166
    169167        return 1;
    170168}
    171169
    172 struct msn_buddy_ask_data
    173 {
     170struct msn_buddy_ask_data {
    174171        struct im_connection *ic;
    175172        char *handle;
     
    177174};
    178175
    179 static void msn_buddy_ask_yes( void *data )
     176static void msn_buddy_ask_yes(void *data)
    180177{
    181178        struct msn_buddy_ask_data *bla = data;
    182        
    183         msn_buddy_list_add( bla->ic, MSN_BUDDY_AL, bla->handle, bla->realname, NULL );
    184        
    185         imcb_ask_add( bla->ic, bla->handle, NULL );
    186        
    187         g_free( bla->handle );
    188         g_free( bla->realname );
    189         g_free( bla );
    190 }
    191 
    192 static void msn_buddy_ask_no( void *data )
     179
     180        msn_buddy_list_add(bla->ic, MSN_BUDDY_AL, bla->handle, bla->realname, NULL);
     181
     182        imcb_ask_add(bla->ic, bla->handle, NULL);
     183
     184        g_free(bla->handle);
     185        g_free(bla->realname);
     186        g_free(bla);
     187}
     188
     189static void msn_buddy_ask_no(void *data)
    193190{
    194191        struct msn_buddy_ask_data *bla = data;
    195        
    196         msn_buddy_list_add( bla->ic, MSN_BUDDY_BL, bla->handle, bla->realname, NULL );
    197        
    198         g_free( bla->handle );
    199         g_free( bla->realname );
    200         g_free( bla );
    201 }
    202 
    203 void msn_buddy_ask( bee_user_t *bu )
     192
     193        msn_buddy_list_add(bla->ic, MSN_BUDDY_BL, bla->handle, bla->realname, NULL);
     194
     195        g_free(bla->handle);
     196        g_free(bla->realname);
     197        g_free(bla);
     198}
     199
     200void msn_buddy_ask(bee_user_t *bu)
    204201{
    205202        struct msn_buddy_ask_data *bla;
    206203        struct msn_buddy_data *bd = bu->data;
    207204        char buf[1024];
    208        
    209         if( !( bd->flags & MSN_BUDDY_PL ) )
     205
     206        if (!(bd->flags & MSN_BUDDY_PL)) {
    210207                return;
    211        
    212         bla = g_new0( struct msn_buddy_ask_data, 1 );
     208        }
     209
     210        bla = g_new0(struct msn_buddy_ask_data, 1);
    213211        bla->ic = bu->ic;
    214         bla->handle = g_strdup( bu->handle );
    215         bla->realname = g_strdup( bu->fullname );
    216        
    217         g_snprintf( buf, sizeof( buf ),
    218                     "The user %s (%s) wants to add you to his/her buddy list.",
    219                     bu->handle, bu->fullname );
    220         imcb_ask( bu->ic, buf, bla, msn_buddy_ask_yes, msn_buddy_ask_no );
     212        bla->handle = g_strdup(bu->handle);
     213        bla->realname = g_strdup(bu->fullname);
     214
     215        g_snprintf(buf, sizeof(buf),
     216                   "The user %s (%s) wants to add you to his/her buddy list.",
     217                   bu->handle, bu->fullname);
     218        imcb_ask(bu->ic, buf, bla, msn_buddy_ask_yes, msn_buddy_ask_no);
    221219}
    222220
    223221/* *NOT* thread-safe, but that's not a problem for now... */
    224 char **msn_linesplit( char *line )
     222char **msn_linesplit(char *line)
    225223{
    226224        static char **ret = NULL;
    227225        static int size = 3;
    228226        int i, n = 0;
    229        
    230         if( ret == NULL )
    231                 ret = g_new0( char*, size );
    232        
    233         for( i = 0; line[i] && line[i] == ' '; i ++ );
    234         if( line[i] )
    235         {
     227
     228        if (ret == NULL) {
     229                ret = g_new0(char*, size);
     230        }
     231
     232        for (i = 0; line[i] && line[i] == ' '; i++) {
     233                ;
     234        }
     235        if (line[i]) {
    236236                ret[n++] = line + i;
    237                 for( i ++; line[i]; i ++ )
    238                 {
    239                         if( line[i] == ' ' )
     237                for (i++; line[i]; i++) {
     238                        if (line[i] == ' ') {
    240239                                line[i] = 0;
    241                         else if( line[i] != ' ' && !line[i-1] )
     240                        } else if (line[i] != ' ' && !line[i - 1]) {
    242241                                ret[n++] = line + i;
    243                        
    244                         if( n >= size )
    245                                 ret = g_renew( char*, ret, size += 2 );
     242                        }
     243
     244                        if (n >= size) {
     245                                ret = g_renew(char*, ret, size += 2);
     246                        }
    246247                }
    247248        }
    248249        ret[n] = NULL;
    249        
    250         return( ret );
     250
     251        return(ret);
    251252}
    252253
     
    259260                   1: OK */
    260261
    261 int msn_handler( struct msn_handler_data *h )
     262int msn_handler(struct msn_handler_data *h)
    262263{
    263264        int st;
    264        
    265         h->rxq = g_renew( char, h->rxq, h->rxlen + 1024 );
    266         st = read( h->fd, h->rxq + h->rxlen, 1024 );
     265
     266        h->rxq = g_renew(char, h->rxq, h->rxlen + 1024);
     267        st = read(h->fd, h->rxq + h->rxlen, 1024);
    267268        h->rxlen += st;
    268        
    269         if( st <= 0 )
    270                 return( -1 );
    271        
    272         if( getenv( "BITLBEE_DEBUG" ) )
    273         {
    274                 write( 2, "->C:", 4 );
    275                 write( 2, h->rxq + h->rxlen - st, st );
    276         }
    277        
    278         while( st )
    279         {
     269
     270        if (st <= 0) {
     271                return(-1);
     272        }
     273
     274        if (getenv("BITLBEE_DEBUG")) {
     275                write(2, "->C:", 4);
     276                write(2, h->rxq + h->rxlen - st, st);
     277        }
     278
     279        while (st) {
    280280                int i;
    281                
    282                 if( h->msglen == 0 )
    283                 {
    284                         for( i = 0; i < h->rxlen; i ++ )
    285                         {
    286                                 if( h->rxq[i] == '\r' || h->rxq[i] == '\n' )
    287                                 {
     281
     282                if (h->msglen == 0) {
     283                        for (i = 0; i < h->rxlen; i++) {
     284                                if (h->rxq[i] == '\r' || h->rxq[i] == '\n') {
    288285                                        char *cmd_text, **cmd;
    289286                                        int count;
    290                                        
    291                                         cmd_text = g_strndup( h->rxq, i );
    292                                         cmd = msn_linesplit( cmd_text );
    293                                         for( count = 0; cmd[count]; count ++ );
    294                                         st = h->exec_command( h, cmd, count );
    295                                         g_free( cmd_text );
    296                                        
     287
     288                                        cmd_text = g_strndup(h->rxq, i);
     289                                        cmd = msn_linesplit(cmd_text);
     290                                        for (count = 0; cmd[count]; count++) {
     291                                                ;
     292                                        }
     293                                        st = h->exec_command(h, cmd, count);
     294                                        g_free(cmd_text);
     295
    297296                                        /* If the connection broke, don't continue. We don't even exist anymore. */
    298                                         if( !st )
    299                                                 return( 0 );
    300                                        
    301                                         if( h->msglen )
    302                                                 h->cmd_text = g_strndup( h->rxq, i );
    303                                        
     297                                        if (!st) {
     298                                                return(0);
     299                                        }
     300
     301                                        if (h->msglen) {
     302                                                h->cmd_text = g_strndup(h->rxq, i);
     303                                        }
     304
    304305                                        /* Skip to the next non-emptyline */
    305                                         while( i < h->rxlen && ( h->rxq[i] == '\r' || h->rxq[i] == '\n' ) ) i ++;
    306                                        
     306                                        while (i < h->rxlen && (h->rxq[i] == '\r' || h->rxq[i] == '\n')) {
     307                                                i++;
     308                                        }
     309
    307310                                        break;
    308311                                }
    309312                        }
    310                        
     313
    311314                        /* If we reached the end of the buffer, there's still an incomplete command there.
    312315                           Return and wait for more data. */
    313                         if( i == h->rxlen && h->rxq[i-1] != '\r' && h->rxq[i-1] != '\n' )
     316                        if (i == h->rxlen && h->rxq[i - 1] != '\r' && h->rxq[i - 1] != '\n') {
    314317                                break;
    315                 }
    316                 else
    317                 {
     318                        }
     319                } else {
    318320                        char *msg, **cmd;
    319321                        int count;
    320                        
     322
    321323                        /* Do we have the complete message already? */
    322                         if( h->msglen > h->rxlen )
     324                        if (h->msglen > h->rxlen) {
    323325                                break;
    324                        
    325                         msg = g_strndup( h->rxq, h->msglen );
    326                         cmd = msn_linesplit( h->cmd_text );
    327                         for( count = 0; cmd[count]; count ++ );
    328                        
    329                         st = h->exec_message( h, msg, h->msglen, cmd, count );
    330                         g_free( msg );
    331                         g_free( h->cmd_text );
     326                        }
     327
     328                        msg = g_strndup(h->rxq, h->msglen);
     329                        cmd = msn_linesplit(h->cmd_text);
     330                        for (count = 0; cmd[count]; count++) {
     331                                ;
     332                        }
     333
     334                        st = h->exec_message(h, msg, h->msglen, cmd, count);
     335                        g_free(msg);
     336                        g_free(h->cmd_text);
    332337                        h->cmd_text = NULL;
    333                        
    334                         if( !st )
    335                                 return( 0 );
    336                        
     338
     339                        if (!st) {
     340                                return(0);
     341                        }
     342
    337343                        i = h->msglen;
    338344                        h->msglen = 0;
    339345                }
    340                
     346
    341347                /* More data after this block? */
    342                 if( i < h->rxlen )
    343                 {
     348                if (i < h->rxlen) {
    344349                        char *tmp;
    345                        
    346                         tmp = g_memdup( h->rxq + i, h->rxlen - i );
    347                         g_free( h->rxq );
     350
     351                        tmp = g_memdup(h->rxq + i, h->rxlen - i);
     352                        g_free(h->rxq);
    348353                        h->rxq = tmp;
    349354                        h->rxlen -= i;
    350355                        i = 0;
    351                 }
    352                 else
    353                 /* If not, reset the rx queue and get lost. */
    354                 {
    355                         g_free( h->rxq );
    356                         h->rxq = g_new0( char, 1 );
     356                } else {
     357                        /* If not, reset the rx queue and get lost. */
     358                        g_free(h->rxq);
     359                        h->rxq = g_new0(char, 1);
    357360                        h->rxlen = 0;
    358                         return( 1 );
    359                 }
    360         }
    361        
    362         return( 1 );
    363 }
    364 
    365 void msn_msgq_purge( struct im_connection *ic, GSList **list )
     361                        return(1);
     362                }
     363        }
     364
     365        return(1);
     366}
     367
     368void msn_msgq_purge(struct im_connection *ic, GSList **list)
    366369{
    367370        struct msn_message *m;
     
    369372        GSList *l;
    370373        int n = 0;
    371        
     374
    372375        l = *list;
    373         if( l == NULL )
     376        if (l == NULL) {
    374377                return;
    375        
     378        }
     379
    376380        m = l->data;
    377         ret = g_string_sized_new( 1024 );
    378         g_string_printf( ret, "Warning: Cleaning up MSN (switchboard) connection with unsent "
    379                               "messages to %s:", m->who ? m->who : "unknown recipient" );
    380        
    381         while( l )
    382         {
     381        ret = g_string_sized_new(1024);
     382        g_string_printf(ret, "Warning: Cleaning up MSN (switchboard) connection with unsent "
     383                        "messages to %s:", m->who ? m->who : "unknown recipient");
     384
     385        while (l) {
    383386                m = l->data;
    384                
    385                 if( strncmp( m->text, "\r\r\r", 3 ) != 0 )
    386                 {
    387                         g_string_append_printf( ret, "\n%s", m->text );
    388                         n ++;
    389                 }
    390                
    391                 g_free( m->who );
    392                 g_free( m->text );
    393                 g_free( m );
    394                
     387
     388                if (strncmp(m->text, "\r\r\r", 3) != 0) {
     389                        g_string_append_printf(ret, "\n%s", m->text);
     390                        n++;
     391                }
     392
     393                g_free(m->who);
     394                g_free(m->text);
     395                g_free(m);
     396
    395397                l = l->next;
    396398        }
    397         g_slist_free( *list );
     399        g_slist_free(*list);
    398400        *list = NULL;
    399        
    400         if( n > 0 )
    401                 imcb_log( ic, "%s", ret->str );
    402         g_string_free( ret, TRUE );
     401
     402        if (n > 0) {
     403                imcb_log(ic, "%s", ret->str);
     404        }
     405        g_string_free(ret, TRUE);
    403406}
    404407
    405408/* Copied and heavily modified from http://tmsnc.sourceforge.net/chl.c */
    406 char *msn_p11_challenge( char *challenge )
     409char *msn_p11_challenge(char *challenge)
    407410{
    408411        char *output, buf[256];
     
    415418        /* Create the MD5 hash */
    416419        md5_init(&md5c);
    417         md5_append(&md5c, (unsigned char*) challenge, strlen(challenge));
    418         md5_append(&md5c, (unsigned char*) MSNP11_PROD_KEY, strlen(MSNP11_PROD_KEY));
     420        md5_append(&md5c, (unsigned char *) challenge, strlen(challenge));
     421        md5_append(&md5c, (unsigned char *) MSNP11_PROD_KEY, strlen(MSNP11_PROD_KEY));
    419422        md5_finish(&md5c, md5Hash);
    420423
    421424        /* Split it into four integers */
    422         md5Parts = (unsigned int *)md5Hash;
    423         for (i = 0; i < 4; i ++)
    424         { 
     425        md5Parts = (unsigned int *) md5Hash;
     426        for (i = 0; i < 4; i++) {
    425427                md5Parts[i] = GUINT32_TO_LE(md5Parts[i]);
    426                
     428
    427429                /* & each integer with 0x7FFFFFFF */
    428430                /* and save one unmodified array for later */
     
    430432                md5Parts[i] &= 0x7FFFFFFF;
    431433        }
    432        
     434
    433435        /* make a new string and pad with '0' */
    434         n = g_snprintf(buf, sizeof(buf)-5, "%s%s00000000", challenge, MSNP11_PROD_ID);
     436        n = g_snprintf(buf, sizeof(buf) - 5, "%s%s00000000", challenge, MSNP11_PROD_ID);
    435437        /* truncate at an 8-byte boundary */
    436         buf[n&=~7] = '\0';
    437        
     438        buf[n &= ~7] = '\0';
     439
    438440        /* split into integers */
    439         chlStringParts = (unsigned int *)buf;
    440        
     441        chlStringParts = (unsigned int *) buf;
     442
    441443        /* this is magic */
    442         for (i = 0; i < (n / 4) - 1; i += 2)
    443         {
     444        for (i = 0; i < (n / 4) - 1; i += 2) {
    444445                long long temp;
    445446
    446447                chlStringParts[i]   = GUINT32_TO_LE(chlStringParts[i]);
    447                 chlStringParts[i+1] = GUINT32_TO_LE(chlStringParts[i+1]);
    448 
    449                 temp  = (md5Parts[0] * (((0x0E79A9C1 * (long long)chlStringParts[i]) % 0x7FFFFFFF)+nHigh) + md5Parts[1])%0x7FFFFFFF;
    450                 nHigh = (md5Parts[2] * (((long long)chlStringParts[i+1]+temp) % 0x7FFFFFFF) + md5Parts[3]) % 0x7FFFFFFF;
     448                chlStringParts[i + 1] = GUINT32_TO_LE(chlStringParts[i + 1]);
     449
     450                temp  =
     451                        (md5Parts[0] *
     452                         (((0x0E79A9C1 *
     453                            (long long) chlStringParts[i]) % 0x7FFFFFFF) + nHigh) + md5Parts[1]) % 0x7FFFFFFF;
     454                nHigh =
     455                        (md5Parts[2] *
     456                         (((long long) chlStringParts[i + 1] + temp) % 0x7FFFFFFF) + md5Parts[3]) % 0x7FFFFFFF;
    451457                nLow  = nLow + nHigh + temp;
    452458        }
    453         nHigh = (nHigh+md5Parts[1]) % 0x7FFFFFFF;
    454         nLow = (nLow+md5Parts[3]) % 0x7FFFFFFF;
    455        
     459        nHigh = (nHigh + md5Parts[1]) % 0x7FFFFFFF;
     460        nLow = (nLow + md5Parts[3]) % 0x7FFFFFFF;
     461
    456462        newHashParts[0] ^= nHigh;
    457463        newHashParts[1] ^= nLow;
    458464        newHashParts[2] ^= nHigh;
    459465        newHashParts[3] ^= nLow;
    460        
     466
    461467        /* swap more bytes if big endian */
    462         for (i = 0; i < 4; i ++)
    463                 newHashParts[i] = GUINT32_TO_LE(newHashParts[i]);
    464        
     468        for (i = 0; i < 4; i++) {
     469                newHashParts[i] = GUINT32_TO_LE(newHashParts[i]);
     470        }
     471
    465472        /* make a string of the parts */
    466         newHash = (unsigned char *)newHashParts;
    467        
     473        newHash = (unsigned char *) newHashParts;
     474
    468475        /* convert to hexadecimal */
    469476        output = g_new(char, 33);
    470         for (i = 0; i < 16; i ++)
     477        for (i = 0; i < 16; i++) {
    471478                sprintf(output + i * 2, "%02x", newHash[i]);
    472        
     479        }
     480
    473481        return output;
    474482}
    475483
    476 gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ )
     484gint msn_domaintree_cmp(gconstpointer a_, gconstpointer b_)
    477485{
    478486        const char *a = a_, *b = b_;
    479487        gint ret;
    480        
    481         if( !( a = strchr( a, '@' ) ) || !( b = strchr( b, '@' ) ) ||
    482             ( ret = strcmp( a, b ) ) == 0 )
    483                 ret = strcmp( a_, b_ );
    484        
     488
     489        if (!(a = strchr(a, '@')) || !(b = strchr(b, '@')) ||
     490            (ret = strcmp(a, b)) == 0) {
     491                ret = strcmp(a_, b_);
     492        }
     493
    485494        return ret;
    486495}
    487496
    488 struct msn_group *msn_group_by_name( struct im_connection *ic, const char *name )
     497struct msn_group *msn_group_by_name(struct im_connection *ic, const char *name)
    489498{
    490499        struct msn_data *md = ic->proto_data;
    491500        GSList *l;
    492        
    493         for( l = md->groups; l; l = l->next )
    494         {
     501
     502        for (l = md->groups; l; l = l->next) {
    495503                struct msn_group *mg = l->data;
    496                
    497                 if( g_strcasecmp( mg->name, name ) == 0 )
     504
     505                if (g_strcasecmp(mg->name, name) == 0) {
    498506                        return mg;
    499         }
    500        
     507                }
     508        }
     509
    501510        return NULL;
    502511}
    503512
    504 struct msn_group *msn_group_by_id( struct im_connection *ic, const char *id )
     513struct msn_group *msn_group_by_id(struct im_connection *ic, const char *id)
    505514{
    506515        struct msn_data *md = ic->proto_data;
    507516        GSList *l;
    508        
    509         for( l = md->groups; l; l = l->next )
    510         {
     517
     518        for (l = md->groups; l; l = l->next) {
    511519                struct msn_group *mg = l->data;
    512                
    513                 if( g_strcasecmp( mg->id, id ) == 0 )
     520
     521                if (g_strcasecmp(mg->id, id) == 0) {
    514522                        return mg;
    515         }
    516        
     523                }
     524        }
     525
    517526        return NULL;
    518527}
    519528
    520 int msn_ns_set_display_name( struct im_connection *ic, const char *value )
     529int msn_ns_set_display_name(struct im_connection *ic, const char *value)
    521530{
    522531        struct msn_data *md = ic->proto_data;
    523         char fn[strlen(value)*3+1];
    524        
    525         strcpy( fn, value );
    526         http_encode( fn );
    527        
     532        char fn[strlen(value) * 3 + 1];
     533
     534        strcpy(fn, value);
     535        http_encode(fn);
     536
    528537        /* Note: We don't actually know if the server accepted the new name,
    529538           and won't give proper feedback yet if it doesn't. */
    530         return msn_ns_write( ic, -1, "PRP %d MFN %s\r\n", ++md->trId, fn );
    531 }
    532 
    533 const char *msn_normalize_handle( const char *handle )
    534 {
    535         if( strncmp( handle, "1:", 2 ) == 0 )
     539        return msn_ns_write(ic, -1, "PRP %d MFN %s\r\n", ++md->trId, fn);
     540}
     541
     542const char *msn_normalize_handle(const char *handle)
     543{
     544        if (strncmp(handle, "1:", 2) == 0) {
    536545                return handle + 2;
    537         else
     546        } else {
    538547                return handle;
    539 }
     548        }
     549}
  • protocols/msn/ns.c

    raf359b4 r5ebff60  
    1   /********************************************************************\
     1/********************************************************************\
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
     
    3333#include "xmltree.h"
    3434
    35 static gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond );
    36 static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond );
    37 static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num_parts );
    38 static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts );
    39 
    40 static void msn_ns_send_adl_start( struct im_connection *ic );
    41 static void msn_ns_send_adl( struct im_connection *ic );
    42 
    43 int msn_ns_write( struct im_connection *ic, int fd, const char *fmt, ... )
     35static gboolean msn_ns_connected(gpointer data, gint source, b_input_condition cond);
     36static gboolean msn_ns_callback(gpointer data, gint source, b_input_condition cond);
     37static int msn_ns_command(struct msn_handler_data *handler, char **cmd, int num_parts);
     38static int msn_ns_message(struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts);
     39
     40static void msn_ns_send_adl_start(struct im_connection *ic);
     41static void msn_ns_send_adl(struct im_connection *ic);
     42
     43int msn_ns_write(struct im_connection *ic, int fd, const char *fmt, ...)
    4444{
    4545        struct msn_data *md = ic->proto_data;
     
    4848        size_t len;
    4949        int st;
    50        
    51         va_start( params, fmt );
    52         out = g_strdup_vprintf( fmt, params );
    53         va_end( params );
    54        
    55         if( fd < 0 )
     50
     51        va_start(params, fmt);
     52        out = g_strdup_vprintf(fmt, params);
     53        va_end(params);
     54
     55        if (fd < 0) {
    5656                fd = md->ns->fd;
    57        
    58         if( getenv( "BITLBEE_DEBUG" ) )
    59                 fprintf( stderr, "->NS%d:%s\n", fd, out );
    60        
    61         len = strlen( out );
    62         st = write( fd, out, len );
    63         g_free( out );
    64         if( st != len )
    65         {
    66                 imcb_error( ic, "Short write() to main server" );
    67                 imc_logout( ic, TRUE );
     57        }
     58
     59        if (getenv("BITLBEE_DEBUG")) {
     60                fprintf(stderr, "->NS%d:%s\n", fd, out);
     61        }
     62
     63        len = strlen(out);
     64        st = write(fd, out, len);
     65        g_free(out);
     66        if (st != len) {
     67                imcb_error(ic, "Short write() to main server");
     68                imc_logout(ic, TRUE);
    6869                return 0;
    6970        }
    70        
     71
    7172        return 1;
    7273}
    7374
    74 gboolean msn_ns_connect( struct im_connection *ic, struct msn_handler_data *handler, const char *host, int port )
    75 {
    76         if( handler->fd >= 0 )
    77                 closesocket( handler->fd );
    78        
     75gboolean msn_ns_connect(struct im_connection *ic, struct msn_handler_data *handler, const char *host, int port)
     76{
     77        if (handler->fd >= 0) {
     78                closesocket(handler->fd);
     79        }
     80
    7981        handler->exec_command = msn_ns_command;
    8082        handler->exec_message = msn_ns_message;
    8183        handler->data = ic;
    82         handler->fd = proxy_connect( host, port, msn_ns_connected, handler );
    83         if( handler->fd < 0 )
    84         {
    85                 imcb_error( ic, "Could not connect to server" );
    86                 imc_logout( ic, TRUE );
     84        handler->fd = proxy_connect(host, port, msn_ns_connected, handler);
     85        if (handler->fd < 0) {
     86                imcb_error(ic, "Could not connect to server");
     87                imc_logout(ic, TRUE);
    8788                return FALSE;
    8889        }
    89        
     90
    9091        return TRUE;
    9192}
    9293
    93 static gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond )
     94static gboolean msn_ns_connected(gpointer data, gint source, b_input_condition cond)
    9495{
    9596        struct msn_handler_data *handler = data;
    9697        struct im_connection *ic = handler->data;
    9798        struct msn_data *md;
    98        
    99         if( !g_slist_find( msn_connections, ic ) )
     99
     100        if (!g_slist_find(msn_connections, ic)) {
    100101                return FALSE;
    101        
     102        }
     103
    102104        md = ic->proto_data;
    103        
    104         if( source == -1 )
    105         {
    106                 imcb_error( ic, "Could not connect to server" );
    107                 imc_logout( ic, TRUE );
     105
     106        if (source == -1) {
     107                imcb_error(ic, "Could not connect to server");
     108                imc_logout(ic, TRUE);
    108109                return FALSE;
    109110        }
    110        
    111         g_free( handler->rxq );
     111
     112        g_free(handler->rxq);
    112113        handler->rxlen = 0;
    113         handler->rxq = g_new0( char, 1 );
    114        
    115         if( md->uuid == NULL )
    116         {
     114        handler->rxq = g_new0(char, 1);
     115
     116        if (md->uuid == NULL) {
    117117                struct utsname name;
    118118                sha1_state_t sha[1];
    119                
     119
    120120                /* UUID == SHA1("BitlBee" + my hostname + MSN username) */
    121                 sha1_init( sha );
    122                 sha1_append( sha, (void*) "BitlBee", 7 );
    123                 if( uname( &name ) == 0 )
    124                 {
    125                         sha1_append( sha, (void*) name.nodename, strlen( name.nodename ) );
    126                 }
    127                 sha1_append( sha, (void*) ic->acc->user, strlen( ic->acc->user ) );
    128                 md->uuid = sha1_random_uuid( sha );
    129                 memcpy( md->uuid, "b171be3e", 8 ); /* :-P */
    130         }
    131        
    132         if( msn_ns_write( ic, source, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER ) )
    133         {
    134                 handler->inpa = b_input_add( handler->fd, B_EV_IO_READ, msn_ns_callback, handler );
    135                 imcb_log( ic, "Connected to server, waiting for reply" );
    136         }
    137        
     121                sha1_init(sha);
     122                sha1_append(sha, (void *) "BitlBee", 7);
     123                if (uname(&name) == 0) {
     124                        sha1_append(sha, (void *) name.nodename, strlen(name.nodename));
     125                }
     126                sha1_append(sha, (void *) ic->acc->user, strlen(ic->acc->user));
     127                md->uuid = sha1_random_uuid(sha);
     128                memcpy(md->uuid, "b171be3e", 8);   /* :-P */
     129        }
     130
     131        if (msn_ns_write(ic, source, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER)) {
     132                handler->inpa = b_input_add(handler->fd, B_EV_IO_READ, msn_ns_callback, handler);
     133                imcb_log(ic, "Connected to server, waiting for reply");
     134        }
     135
    138136        return FALSE;
    139137}
    140138
    141 void msn_ns_close( struct msn_handler_data *handler )
    142 {
    143         if( handler->fd >= 0 )
    144         {
    145                 closesocket( handler->fd );
    146                 b_event_remove( handler->inpa );
    147         }
    148        
     139void msn_ns_close(struct msn_handler_data *handler)
     140{
     141        if (handler->fd >= 0) {
     142                closesocket(handler->fd);
     143                b_event_remove(handler->inpa);
     144        }
     145
    149146        handler->fd = handler->inpa = -1;
    150         g_free( handler->rxq );
    151         g_free( handler->cmd_text );
    152        
     147        g_free(handler->rxq);
     148        g_free(handler->cmd_text);
     149
    153150        handler->rxlen = 0;
    154151        handler->rxq = NULL;
     
    156153}
    157154
    158 static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond )
     155static gboolean msn_ns_callback(gpointer data, gint source, b_input_condition cond)
    159156{
    160157        struct msn_handler_data *handler = data;
    161158        struct im_connection *ic = handler->data;
    162        
    163         if( msn_handler( handler ) == -1 ) /* Don't do this on ret == 0, it's already done then. */
    164         {
    165                 imcb_error( ic, "Error while reading from server" );
    166                 imc_logout( ic, TRUE );
    167                
     159
     160        if (msn_handler(handler) == -1) {  /* Don't do this on ret == 0, it's already done then. */
     161                imcb_error(ic, "Error while reading from server");
     162                imc_logout(ic, TRUE);
     163
    168164                return FALSE;
    169         }
    170         else
     165        } else {
    171166                return TRUE;
    172 }
    173 
    174 static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num_parts )
     167        }
     168}
     169
     170static int msn_ns_command(struct msn_handler_data *handler, char **cmd, int num_parts)
    175171{
    176172        struct im_connection *ic = handler->data;
    177173        struct msn_data *md = ic->proto_data;
    178        
    179         if( num_parts == 0 )
    180         {
     174
     175        if (num_parts == 0) {
    181176                /* Hrrm... Empty command...? Ignore? */
    182                 return( 1 );
    183         }
    184        
    185         if( strcmp( cmd[0], "VER" ) == 0 )
    186         {
    187                 if( cmd[2] && strncmp( cmd[2], MSNP_VER, 5 ) != 0 )
    188                 {
    189                         imcb_error( ic, "Unsupported protocol" );
    190                         imc_logout( ic, FALSE );
    191                         return( 0 );
    192                 }
    193                
    194                 return( msn_ns_write( ic, handler->fd, "CVR %d 0x0409 mac 10.2.0 ppc macmsgs 3.5.1 macmsgs %s\r\n",
    195                                       ++md->trId, ic->acc->user ) );
    196         }
    197         else if( strcmp( cmd[0], "CVR" ) == 0 )
    198         {
     177                return(1);
     178        }
     179
     180        if (strcmp(cmd[0], "VER") == 0) {
     181                if (cmd[2] && strncmp(cmd[2], MSNP_VER, 5) != 0) {
     182                        imcb_error(ic, "Unsupported protocol");
     183                        imc_logout(ic, FALSE);
     184                        return(0);
     185                }
     186
     187                return(msn_ns_write(ic, handler->fd, "CVR %d 0x0409 mac 10.2.0 ppc macmsgs 3.5.1 macmsgs %s\r\n",
     188                                    ++md->trId, ic->acc->user));
     189        } else if (strcmp(cmd[0], "CVR") == 0) {
    199190                /* We don't give a damn about the information we just received */
    200                 return msn_ns_write( ic, handler->fd, "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user );
    201         }
    202         else if( strcmp( cmd[0], "XFR" ) == 0 )
    203         {
     191                return msn_ns_write(ic, handler->fd, "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user);
     192        } else if (strcmp(cmd[0], "XFR") == 0) {
    204193                char *server;
    205194                int port;
    206                
    207                 if( num_parts >= 6 && strcmp( cmd[2], "NS" ) == 0 )
    208                 {
    209                         b_event_remove( handler->inpa );
     195
     196                if (num_parts >= 6 && strcmp(cmd[2], "NS") == 0) {
     197                        b_event_remove(handler->inpa);
    210198                        handler->inpa = -1;
    211                        
    212                         server = strchr( cmd[3], ':' );
    213                         if( !server )
    214                         {
    215                                 imcb_error( ic, "Syntax error" );
    216                                 imc_logout( ic, TRUE );
    217                                 return( 0 );
     199
     200                        server = strchr(cmd[3], ':');
     201                        if (!server) {
     202                                imcb_error(ic, "Syntax error");
     203                                imc_logout(ic, TRUE);
     204                                return(0);
    218205                        }
    219206                        *server = 0;
    220                         port = atoi( server + 1 );
     207                        port = atoi(server + 1);
    221208                        server = cmd[3];
    222                        
    223                         imcb_log( ic, "Transferring to other server" );
    224                         return msn_ns_connect( ic, handler, server, port );
    225                 }
    226                 else if( num_parts >= 6 && strcmp( cmd[2], "SB" ) == 0 )
    227                 {
     209
     210                        imcb_log(ic, "Transferring to other server");
     211                        return msn_ns_connect(ic, handler, server, port);
     212                } else if (num_parts >= 6 && strcmp(cmd[2], "SB") == 0) {
    228213                        struct msn_switchboard *sb;
    229                        
    230                         server = strchr( cmd[3], ':' );
    231                         if( !server )
    232                         {
    233                                 imcb_error( ic, "Syntax error" );
    234                                 imc_logout( ic, TRUE );
    235                                 return( 0 );
     214
     215                        server = strchr(cmd[3], ':');
     216                        if (!server) {
     217                                imcb_error(ic, "Syntax error");
     218                                imc_logout(ic, TRUE);
     219                                return(0);
    236220                        }
    237221                        *server = 0;
    238                         port = atoi( server + 1 );
     222                        port = atoi(server + 1);
    239223                        server = cmd[3];
    240                        
    241                         if( strcmp( cmd[4], "CKI" ) != 0 )
    242                         {
    243                                 imcb_error( ic, "Unknown authentication method for switchboard" );
    244                                 imc_logout( ic, TRUE );
    245                                 return( 0 );
    246                         }
    247                        
    248                         debug( "Connecting to a new switchboard with key %s", cmd[5] );
    249 
    250                         if( ( sb = msn_sb_create( ic, server, port, cmd[5], MSN_SB_NEW ) ) == NULL )
    251                         {
     224
     225                        if (strcmp(cmd[4], "CKI") != 0) {
     226                                imcb_error(ic, "Unknown authentication method for switchboard");
     227                                imc_logout(ic, TRUE);
     228                                return(0);
     229                        }
     230
     231                        debug("Connecting to a new switchboard with key %s", cmd[5]);
     232
     233                        if ((sb = msn_sb_create(ic, server, port, cmd[5], MSN_SB_NEW)) == NULL) {
    252234                                /* Although this isn't strictly fatal for the NS connection, it's
    253235                                   definitely something serious (we ran out of file descriptors?). */
    254                                 imcb_error( ic, "Could not create new switchboard" );
    255                                 imc_logout( ic, TRUE );
    256                                 return( 0 );
    257                         }
    258                        
    259                         if( md->msgq )
    260                         {
     236                                imcb_error(ic, "Could not create new switchboard");
     237                                imc_logout(ic, TRUE);
     238                                return(0);
     239                        }
     240
     241                        if (md->msgq) {
    261242                                struct msn_message *m = md->msgq->data;
    262243                                GSList *l;
    263                                
    264                                 sb->who = g_strdup( m->who );
    265                                
     244
     245                                sb->who = g_strdup(m->who);
     246
    266247                                /* Move all the messages to the first user in the message
    267248                                   queue to the switchboard message queue. */
    268249                                l = md->msgq;
    269                                 while( l )
    270                                 {
     250                                while (l) {
    271251                                        m = l->data;
    272252                                        l = l->next;
    273                                         if( strcmp( m->who, sb->who ) == 0 )
    274                                         {
    275                                                 sb->msgq = g_slist_append( sb->msgq, m );
    276                                                 md->msgq = g_slist_remove( md->msgq, m );
     253                                        if (strcmp(m->who, sb->who) == 0) {
     254                                                sb->msgq = g_slist_append(sb->msgq, m);
     255                                                md->msgq = g_slist_remove(md->msgq, m);
    277256                                        }
    278257                                }
    279258                        }
    280                 }
    281                 else
    282                 {
    283                         imcb_error( ic, "Syntax error" );
    284                         imc_logout( ic, TRUE );
    285                         return( 0 );
    286                 }
    287         }
    288         else if( strcmp( cmd[0], "USR" ) == 0 )
    289         {
    290                 if( num_parts >= 6 && strcmp( cmd[2], "SSO" ) == 0 &&
    291                     strcmp( cmd[3], "S" ) == 0 )
    292                 {
    293                         g_free( md->pp_policy );
    294                         md->pp_policy = g_strdup( cmd[4] );
    295                         msn_soap_passport_sso_request( ic, cmd[5] );
    296                 }
    297                 else if( strcmp( cmd[2], "OK" ) == 0 )
    298                 {
     259                } else {
     260                        imcb_error(ic, "Syntax error");
     261                        imc_logout(ic, TRUE);
     262                        return(0);
     263                }
     264        } else if (strcmp(cmd[0], "USR") == 0) {
     265                if (num_parts >= 6 && strcmp(cmd[2], "SSO") == 0 &&
     266                    strcmp(cmd[3], "S") == 0) {
     267                        g_free(md->pp_policy);
     268                        md->pp_policy = g_strdup(cmd[4]);
     269                        msn_soap_passport_sso_request(ic, cmd[5]);
     270                } else if (strcmp(cmd[2], "OK") == 0) {
    299271                        /* If the number after the handle is 0, the e-mail
    300272                           address is unverified, which means we can't change
    301273                           the display name. */
    302                         if( cmd[4][0] == '0' )
     274                        if (cmd[4][0] == '0') {
    303275                                md->flags |= MSN_EMAIL_UNVERIFIED;
    304                        
    305                         imcb_log( ic, "Authenticated, getting buddy list" );
    306                         msn_soap_memlist_request( ic );
    307                 }
    308                 else
    309                 {
    310                         imcb_error( ic, "Unknown authentication type" );
    311                         imc_logout( ic, FALSE );
    312                         return( 0 );
    313                 }
    314         }
    315         else if( strcmp( cmd[0], "MSG" ) == 0 )
    316         {
    317                 if( num_parts < 4 )
    318                 {
    319                         imcb_error( ic, "Syntax error" );
    320                         imc_logout( ic, TRUE );
    321                         return( 0 );
    322                 }
    323                
    324                 handler->msglen = atoi( cmd[3] );
    325                
    326                 if( handler->msglen <= 0 )
    327                 {
    328                         imcb_error( ic, "Syntax error" );
    329                         imc_logout( ic, TRUE );
    330                         return( 0 );
    331                 }
    332         }
    333         else if( strcmp( cmd[0], "BLP" ) == 0 )
    334         {
    335                 msn_ns_send_adl_start( ic );
    336                 return msn_ns_finish_login( ic );
    337         }
    338         else if( strcmp( cmd[0], "ADL" ) == 0 )
    339         {
    340                 if( num_parts >= 3 && strcmp( cmd[2], "OK" ) == 0 )
    341                 {
    342                         msn_ns_send_adl( ic );
    343                         return msn_ns_finish_login( ic );
    344                 }
    345                 else if( num_parts >= 3 )
    346                 {
    347                         handler->msglen = atoi( cmd[2] );
    348                 }
    349         }
    350         else if( strcmp( cmd[0], "PRP" ) == 0 )
    351         {
    352                 imcb_connected( ic );
    353         }
    354         else if( strcmp( cmd[0], "CHL" ) == 0 )
    355         {
     276                        }
     277
     278                        imcb_log(ic, "Authenticated, getting buddy list");
     279                        msn_soap_memlist_request(ic);
     280                } else {
     281                        imcb_error(ic, "Unknown authentication type");
     282                        imc_logout(ic, FALSE);
     283                        return(0);
     284                }
     285        } else if (strcmp(cmd[0], "MSG") == 0) {
     286                if (num_parts < 4) {
     287                        imcb_error(ic, "Syntax error");
     288                        imc_logout(ic, TRUE);
     289                        return(0);
     290                }
     291
     292                handler->msglen = atoi(cmd[3]);
     293
     294                if (handler->msglen <= 0) {
     295                        imcb_error(ic, "Syntax error");
     296                        imc_logout(ic, TRUE);
     297                        return(0);
     298                }
     299        } else if (strcmp(cmd[0], "BLP") == 0) {
     300                msn_ns_send_adl_start(ic);
     301                return msn_ns_finish_login(ic);
     302        } else if (strcmp(cmd[0], "ADL") == 0) {
     303                if (num_parts >= 3 && strcmp(cmd[2], "OK") == 0) {
     304                        msn_ns_send_adl(ic);
     305                        return msn_ns_finish_login(ic);
     306                } else if (num_parts >= 3) {
     307                        handler->msglen = atoi(cmd[2]);
     308                }
     309        } else if (strcmp(cmd[0], "PRP") == 0) {
     310                imcb_connected(ic);
     311        } else if (strcmp(cmd[0], "CHL") == 0) {
    356312                char *resp;
    357313                int st;
    358                
    359                 if( num_parts < 3 )
    360                 {
    361                         imcb_error( ic, "Syntax error" );
    362                         imc_logout( ic, TRUE );
    363                         return( 0 );
    364                 }
    365                
    366                 resp = msn_p11_challenge( cmd[2] );
    367                
    368                 st =  msn_ns_write( ic, -1, "QRY %d %s %zd\r\n%s",
    369                                     ++md->trId, MSNP11_PROD_ID,
    370                                     strlen( resp ), resp );
    371                 g_free( resp );
     314
     315                if (num_parts < 3) {
     316                        imcb_error(ic, "Syntax error");
     317                        imc_logout(ic, TRUE);
     318                        return(0);
     319                }
     320
     321                resp = msn_p11_challenge(cmd[2]);
     322
     323                st =  msn_ns_write(ic, -1, "QRY %d %s %zd\r\n%s",
     324                                   ++md->trId, MSNP11_PROD_ID,
     325                                   strlen(resp), resp);
     326                g_free(resp);
    372327                return st;
    373         }
    374         else if( strcmp( cmd[0], "ILN" ) == 0 || strcmp( cmd[0], "NLN" ) == 0 )
    375         {
     328        } else if (strcmp(cmd[0], "ILN") == 0 || strcmp(cmd[0], "NLN") == 0) {
    376329                const struct msn_away_state *st;
    377330                const char *handle;
    378331                int cap = 0;
    379                
    380                 if( num_parts < 6 )
    381                 {
    382                         imcb_error( ic, "Syntax error" );
    383                         imc_logout( ic, TRUE );
    384                         return( 0 );
     332
     333                if (num_parts < 6) {
     334                        imcb_error(ic, "Syntax error");
     335                        imc_logout(ic, TRUE);
     336                        return(0);
    385337                }
    386338                /* ILN and NLN are more or less the same, except ILN has a trId
    387                    at the start, and NLN has a capability field at the end. 
     339                   at the start, and NLN has a capability field at the end.
    388340                   Does ILN still exist BTW? */
    389                 if( cmd[0][1] == 'I' )
    390                         cmd ++;
    391                 else
    392                         cap = atoi( cmd[4] );
    393 
    394                 handle = msn_normalize_handle( cmd[2] );
    395                 if( strcmp( handle, ic->acc->user ) == 0 )
     341                if (cmd[0][1] == 'I') {
     342                        cmd++;
     343                } else {
     344                        cap = atoi(cmd[4]);
     345                }
     346
     347                handle = msn_normalize_handle(cmd[2]);
     348                if (strcmp(handle, ic->acc->user) == 0) {
    396349                        return 1; /* That's me! */
    397                
    398                 http_decode( cmd[3] );
    399                 imcb_rename_buddy( ic, handle, cmd[3] );
    400                
    401                 st = msn_away_state_by_code( cmd[1] );
    402                 if( !st )
    403                 {
     350
     351                }
     352                http_decode(cmd[3]);
     353                imcb_rename_buddy(ic, handle, cmd[3]);
     354
     355                st = msn_away_state_by_code(cmd[1]);
     356                if (!st) {
    404357                        /* FIXME: Warn/Bomb about unknown away state? */
    405358                        st = msn_away_state_list + 1;
    406359                }
    407                
    408                 imcb_buddy_status( ic, handle, OPT_LOGGED_IN |
    409                                    ( st != msn_away_state_list ? OPT_AWAY : 0 ) |
    410                                    ( cap & 1 ? OPT_MOBILE : 0 ),
    411                                    st->name, NULL );
    412                
    413                 msn_sb_stop_keepalives( msn_sb_by_handle( ic, handle ) );
    414         }
    415         else if( strcmp( cmd[0], "FLN" ) == 0 )
    416         {
     360
     361                imcb_buddy_status(ic, handle, OPT_LOGGED_IN |
     362                                  (st != msn_away_state_list ? OPT_AWAY : 0) |
     363                                  (cap & 1 ? OPT_MOBILE : 0),
     364                                  st->name, NULL);
     365
     366                msn_sb_stop_keepalives(msn_sb_by_handle(ic, handle));
     367        } else if (strcmp(cmd[0], "FLN") == 0) {
    417368                const char *handle;
    418                
    419                 if( cmd[1] == NULL )
     369
     370                if (cmd[1] == NULL) {
    420371                        return 1;
    421                
    422                 handle = msn_normalize_handle( cmd[1] );
    423                 imcb_buddy_status( ic, handle, 0, NULL, NULL );
    424                 msn_sb_start_keepalives( msn_sb_by_handle( ic, handle ), TRUE );
    425         }
    426         else if( strcmp( cmd[0], "RNG" ) == 0 )
    427         {
     372                }
     373
     374                handle = msn_normalize_handle(cmd[1]);
     375                imcb_buddy_status(ic, handle, 0, NULL, NULL);
     376                msn_sb_start_keepalives(msn_sb_by_handle(ic, handle), TRUE);
     377        } else if (strcmp(cmd[0], "RNG") == 0) {
    428378                struct msn_switchboard *sb;
    429379                char *server;
    430380                int session, port;
    431                
    432                 if( num_parts < 7 )
    433                 {
    434                         imcb_error( ic, "Syntax error" );
    435                         imc_logout( ic, TRUE );
    436                         return( 0 );
    437                 }
    438                
    439                 session = atoi( cmd[1] );
    440                
    441                 server = strchr( cmd[2], ':' );
    442                 if( !server )
    443                 {
    444                         imcb_error( ic, "Syntax error" );
    445                         imc_logout( ic, TRUE );
    446                         return( 0 );
     381
     382                if (num_parts < 7) {
     383                        imcb_error(ic, "Syntax error");
     384                        imc_logout(ic, TRUE);
     385                        return(0);
     386                }
     387
     388                session = atoi(cmd[1]);
     389
     390                server = strchr(cmd[2], ':');
     391                if (!server) {
     392                        imcb_error(ic, "Syntax error");
     393                        imc_logout(ic, TRUE);
     394                        return(0);
    447395                }
    448396                *server = 0;
    449                 port = atoi( server + 1 );
     397                port = atoi(server + 1);
    450398                server = cmd[2];
    451                
    452                 if( strcmp( cmd[3], "CKI" ) != 0 )
    453                 {
    454                         imcb_error( ic, "Unknown authentication method for switchboard" );
    455                         imc_logout( ic, TRUE );
    456                         return( 0 );
    457                 }
    458                
    459                 debug( "Got a call from %s (session %d). Key = %s", cmd[5], session, cmd[4] );
    460                
    461                 if( ( sb = msn_sb_create( ic, server, port, cmd[4], session ) ) == NULL )
    462                 {
     399
     400                if (strcmp(cmd[3], "CKI") != 0) {
     401                        imcb_error(ic, "Unknown authentication method for switchboard");
     402                        imc_logout(ic, TRUE);
     403                        return(0);
     404                }
     405
     406                debug("Got a call from %s (session %d). Key = %s", cmd[5], session, cmd[4]);
     407
     408                if ((sb = msn_sb_create(ic, server, port, cmd[4], session)) == NULL) {
    463409                        /* Although this isn't strictly fatal for the NS connection, it's
    464410                           definitely something serious (we ran out of file descriptors?). */
    465                         imcb_error( ic, "Could not create new switchboard" );
    466                         imc_logout( ic, TRUE );
    467                         return( 0 );
    468                 }
    469                 else
    470                 {
    471                         sb->who = g_strdup( msn_normalize_handle( cmd[5] ) );
    472                 }
    473         }
    474         else if( strcmp( cmd[0], "OUT" ) == 0 )
    475         {
     411                        imcb_error(ic, "Could not create new switchboard");
     412                        imc_logout(ic, TRUE);
     413                        return(0);
     414                } else {
     415                        sb->who = g_strdup(msn_normalize_handle(cmd[5]));
     416                }
     417        } else if (strcmp(cmd[0], "OUT") == 0) {
    476418                int allow_reconnect = TRUE;
    477                
    478                 if( cmd[1] && strcmp( cmd[1], "OTH" ) == 0 )
    479                 {
    480                         imcb_error( ic, "Someone else logged in with your account" );
     419
     420                if (cmd[1] && strcmp(cmd[1], "OTH") == 0) {
     421                        imcb_error(ic, "Someone else logged in with your account");
    481422                        allow_reconnect = FALSE;
    482                 }
    483                 else if( cmd[1] && strcmp( cmd[1], "SSD" ) == 0 )
    484                 {
    485                         imcb_error( ic, "Terminating session because of server shutdown" );
    486                 }
    487                 else
    488                 {
    489                         imcb_error( ic, "Session terminated by remote server (%s)",
    490                                     cmd[1] ? cmd[1] : "reason unknown)" );
    491                 }
    492                
    493                 imc_logout( ic, allow_reconnect );
    494                 return( 0 );
    495         }
    496         else if( strcmp( cmd[0], "IPG" ) == 0 )
    497         {
    498                 imcb_error( ic, "Received IPG command, we don't handle them yet." );
    499                
    500                 handler->msglen = atoi( cmd[1] );
    501                
    502                 if( handler->msglen <= 0 )
    503                 {
    504                         imcb_error( ic, "Syntax error" );
    505                         imc_logout( ic, TRUE );
    506                         return( 0 );
     423                } else if (cmd[1] && strcmp(cmd[1], "SSD") == 0) {
     424                        imcb_error(ic, "Terminating session because of server shutdown");
     425                } else {
     426                        imcb_error(ic, "Session terminated by remote server (%s)",
     427                                   cmd[1] ? cmd[1] : "reason unknown)");
     428                }
     429
     430                imc_logout(ic, allow_reconnect);
     431                return(0);
     432        } else if (strcmp(cmd[0], "IPG") == 0) {
     433                imcb_error(ic, "Received IPG command, we don't handle them yet.");
     434
     435                handler->msglen = atoi(cmd[1]);
     436
     437                if (handler->msglen <= 0) {
     438                        imcb_error(ic, "Syntax error");
     439                        imc_logout(ic, TRUE);
     440                        return(0);
    507441                }
    508442        }
    509443#if 0
    510         else if( strcmp( cmd[0], "ADG" ) == 0 )
    511         {
    512                 char *group = g_strdup( cmd[3] );
     444        else if (strcmp(cmd[0], "ADG") == 0) {
     445                char *group = g_strdup(cmd[3]);
    513446                int groupnum, i;
    514447                GSList *l, *next;
    515                
    516                 http_decode( group );
    517                 if( sscanf( cmd[4], "%d", &groupnum ) == 1 )
    518                 {
    519                         if( groupnum >= md->groupcount )
    520                         {
    521                                 md->grouplist = g_renew( char *, md->grouplist, groupnum + 1 );
    522                                 for( i = md->groupcount; i <= groupnum; i ++ )
     448
     449                http_decode(group);
     450                if (sscanf(cmd[4], "%d", &groupnum) == 1) {
     451                        if (groupnum >= md->groupcount) {
     452                                md->grouplist = g_renew(char *, md->grouplist, groupnum + 1);
     453                                for (i = md->groupcount; i <= groupnum; i++) {
    523454                                        md->grouplist[i] = NULL;
     455                                }
    524456                                md->groupcount = groupnum + 1;
    525457                        }
    526                         g_free( md->grouplist[groupnum] );
     458                        g_free(md->grouplist[groupnum]);
    527459                        md->grouplist[groupnum] = group;
    528                 }
    529                 else
    530                 {
     460                } else {
    531461                        /* Shouldn't happen, but if it does, give up on the group. */
    532                         g_free( group );
    533                         imcb_error( ic, "Syntax error" );
    534                         imc_logout( ic, TRUE );
     462                        g_free(group);
     463                        imcb_error(ic, "Syntax error");
     464                        imc_logout(ic, TRUE);
    535465                        return 0;
    536466                }
    537                
    538                 for( l = md->grpq; l; l = next )
    539                 {
     467
     468                for (l = md->grpq; l; l = next) {
    540469                        struct msn_groupadd *ga = l->data;
    541470                        next = l->next;
    542                         if( g_strcasecmp( ga->group, group ) == 0 )
    543                         {
    544                                 if( !msn_buddy_list_add( ic, "FL", ga->who, ga->who, group ) )
     471                        if (g_strcasecmp(ga->group, group) == 0) {
     472                                if (!msn_buddy_list_add(ic, "FL", ga->who, ga->who, group)) {
    545473                                        return 0;
    546                                
    547                                 g_free( ga->group );
    548                                 g_free( ga->who );
    549                                 g_free( ga );
    550                                 md->grpq = g_slist_remove( md->grpq, ga );
     474                                }
     475
     476                                g_free(ga->group);
     477                                g_free(ga->who);
     478                                g_free(ga);
     479                                md->grpq = g_slist_remove(md->grpq, ga);
    551480                        }
    552481                }
    553482        }
    554483#endif
    555         else if( strcmp( cmd[0], "GCF" ) == 0 )
    556         {
     484        else if (strcmp(cmd[0], "GCF") == 0) {
    557485                /* Coming up is cmd[2] bytes of stuff we're supposed to
    558486                   censore. Meh. */
    559                 handler->msglen = atoi( cmd[2] );
    560         }
    561         else if( strcmp( cmd[0], "UBX" ) == 0 )
    562         {
     487                handler->msglen = atoi(cmd[2]);
     488        } else if (strcmp(cmd[0], "UBX") == 0) {
    563489                /* Status message. */
    564                 if( num_parts >= 3 )
    565                         handler->msglen = atoi( cmd[2] );
    566         }
    567         else if( strcmp( cmd[0], "NOT" ) == 0 )
    568         {
     490                if (num_parts >= 3) {
     491                        handler->msglen = atoi(cmd[2]);
     492                }
     493        } else if (strcmp(cmd[0], "NOT") == 0) {
    569494                /* Some kind of notification, poorly documented but
    570495                   apparently used to announce address book changes. */
    571                 if( num_parts >= 2 )
    572                         handler->msglen = atoi( cmd[1] );
    573         }
    574         else if( strcmp( cmd[0], "UBM" ) == 0 )
    575         {
    576                 if( num_parts >= 7 )
    577                         handler->msglen = atoi( cmd[6] );
    578         }
    579         else if( strcmp( cmd[0], "QNG" ) == 0 )
    580         {
     496                if (num_parts >= 2) {
     497                        handler->msglen = atoi(cmd[1]);
     498                }
     499        } else if (strcmp(cmd[0], "UBM") == 0) {
     500                if (num_parts >= 7) {
     501                        handler->msglen = atoi(cmd[6]);
     502                }
     503        } else if (strcmp(cmd[0], "QNG") == 0) {
    581504                ic->flags |= OPT_PONGED;
    582         }
    583         else if( g_ascii_isdigit( cmd[0][0] ) )
    584         {
    585                 int num = atoi( cmd[0] );
    586                 const struct msn_status_code *err = msn_status_by_number( num );
    587                
    588                 imcb_error( ic, "Error reported by MSN server: %s", err->text );
    589                
    590                 if( err->flags & STATUS_FATAL )
    591                 {
    592                         imc_logout( ic, TRUE );
    593                         return( 0 );
    594                 }
    595                
     505        } else if (g_ascii_isdigit(cmd[0][0])) {
     506                int num = atoi(cmd[0]);
     507                const struct msn_status_code *err = msn_status_by_number(num);
     508
     509                imcb_error(ic, "Error reported by MSN server: %s", err->text);
     510
     511                if (err->flags & STATUS_FATAL) {
     512                        imc_logout(ic, TRUE);
     513                        return(0);
     514                }
     515
    596516                /* Oh yes, errors can have payloads too now. Discard them for now. */
    597                 if( num_parts >= 3 )
    598                         handler->msglen = atoi( cmd[2] );
    599         }
    600         else
    601         {
     517                if (num_parts >= 3) {
     518                        handler->msglen = atoi(cmd[2]);
     519                }
     520        } else {
    602521                /* debug( "Received unknown command from main server: %s", cmd[0] ); */
    603522        }
    604        
    605         return( 1 );
    606 }
    607 
    608 static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts )
     523
     524        return(1);
     525}
     526
     527static int msn_ns_message(struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts)
    609528{
    610529        struct im_connection *ic = handler->data;
    611530        char *body;
    612531        int blen = 0;
    613        
    614         if( !num_parts )
    615                 return( 1 );
    616        
    617         if( ( body = strstr( msg, "\r\n\r\n" ) ) )
    618         {
     532
     533        if (!num_parts) {
     534                return(1);
     535        }
     536
     537        if ((body = strstr(msg, "\r\n\r\n"))) {
    619538                body += 4;
    620                 blen = msglen - ( body - msg );
    621         }
    622        
    623         if( strcmp( cmd[0], "MSG" ) == 0 )
    624         {
    625                 if( g_strcasecmp( cmd[1], "Hotmail" ) == 0 )
    626                 {
    627                         char *ct = get_rfc822_header( msg, "Content-Type:", msglen );
    628                        
    629                         if( !ct )
    630                                 return( 1 );
    631                        
    632                         if( g_strncasecmp( ct, "application/x-msmsgssystemmessage", 33 ) == 0 )
    633                         {
     539                blen = msglen - (body - msg);
     540        }
     541
     542        if (strcmp(cmd[0], "MSG") == 0) {
     543                if (g_strcasecmp(cmd[1], "Hotmail") == 0) {
     544                        char *ct = get_rfc822_header(msg, "Content-Type:", msglen);
     545
     546                        if (!ct) {
     547                                return(1);
     548                        }
     549
     550                        if (g_strncasecmp(ct, "application/x-msmsgssystemmessage", 33) == 0) {
    634551                                char *mtype;
    635552                                char *arg1;
    636                                
    637                                 if( !body )
    638                                         return( 1 );
    639                                
    640                                 mtype = get_rfc822_header( body, "Type:", blen );
    641                                 arg1 = get_rfc822_header( body, "Arg1:", blen );
    642                                
    643                                 if( mtype && strcmp( mtype, "1" ) == 0 )
    644                                 {
    645                                         if( arg1 )
    646                                                 imcb_log( ic, "The server is going down for maintenance in %s minutes.", arg1 );
    647                                 }
    648                                
    649                                 g_free( arg1 );
    650                                 g_free( mtype );
    651                         }
    652                         else if( g_strncasecmp( ct, "text/x-msmsgsprofile", 20 ) == 0 )
    653                         {
     553
     554                                if (!body) {
     555                                        return(1);
     556                                }
     557
     558                                mtype = get_rfc822_header(body, "Type:", blen);
     559                                arg1 = get_rfc822_header(body, "Arg1:", blen);
     560
     561                                if (mtype && strcmp(mtype, "1") == 0) {
     562                                        if (arg1) {
     563                                                imcb_log(ic, "The server is going down for maintenance in %s minutes.",
     564                                                         arg1);
     565                                        }
     566                                }
     567
     568                                g_free(arg1);
     569                                g_free(mtype);
     570                        } else if (g_strncasecmp(ct, "text/x-msmsgsprofile", 20) == 0) {
    654571                                /* We don't care about this profile for now... */
    655                         }
    656                         else if( g_strncasecmp( ct, "text/x-msmsgsinitialemailnotification", 37 ) == 0 )
    657                         {
    658                                 if( set_getbool( &ic->acc->set, "mail_notifications" ) )
    659                                 {
    660                                         char *inbox = get_rfc822_header( body, "Inbox-Unread:", blen );
    661                                         char *folders = get_rfc822_header( body, "Folders-Unread:", blen );
    662 
    663                                         if( inbox && folders )
    664                                                 imcb_log( ic, "INBOX contains %s new messages, plus %s messages in other folders.", inbox, folders );
    665                                        
    666                                         g_free( inbox );
    667                                         g_free( folders );
    668                                 }
    669                         }
    670                         else if( g_strncasecmp( ct, "text/x-msmsgsemailnotification", 30 ) == 0 )
    671                         {
    672                                 if( set_getbool( &ic->acc->set, "mail_notifications" ) )
    673                                 {
    674                                         char *from = get_rfc822_header( body, "From-Addr:", blen );
    675                                         char *fromname = get_rfc822_header( body, "From:", blen );
    676                                        
    677                                         if( from && fromname )
    678                                                 imcb_log( ic, "Received an e-mail message from %s <%s>.", fromname, from );
    679 
    680                                         g_free( from );
    681                                         g_free( fromname );
    682                                 }
    683                         }
    684                         else if( g_strncasecmp( ct, "text/x-msmsgsactivemailnotification", 35 ) == 0 )
    685                         {
    686                         }
    687                         else if( g_strncasecmp( ct, "text/x-msmsgsinitialmdatanotification", 37 ) == 0 ||
    688                                  g_strncasecmp( ct, "text/x-msmsgsoimnotification", 28 ) == 0 )
    689                         {
     572                        } else if (g_strncasecmp(ct, "text/x-msmsgsinitialemailnotification", 37) == 0) {
     573                                if (set_getbool(&ic->acc->set, "mail_notifications")) {
     574                                        char *inbox = get_rfc822_header(body, "Inbox-Unread:", blen);
     575                                        char *folders = get_rfc822_header(body, "Folders-Unread:", blen);
     576
     577                                        if (inbox && folders) {
     578                                                imcb_log(ic,
     579                                                         "INBOX contains %s new messages, plus %s messages in other folders.", inbox,
     580                                                         folders);
     581                                        }
     582
     583                                        g_free(inbox);
     584                                        g_free(folders);
     585                                }
     586                        } else if (g_strncasecmp(ct, "text/x-msmsgsemailnotification", 30) == 0) {
     587                                if (set_getbool(&ic->acc->set, "mail_notifications")) {
     588                                        char *from = get_rfc822_header(body, "From-Addr:", blen);
     589                                        char *fromname = get_rfc822_header(body, "From:", blen);
     590
     591                                        if (from && fromname) {
     592                                                imcb_log(ic, "Received an e-mail message from %s <%s>.", fromname,
     593                                                         from);
     594                                        }
     595
     596                                        g_free(from);
     597                                        g_free(fromname);
     598                                }
     599                        } else if (g_strncasecmp(ct, "text/x-msmsgsactivemailnotification", 35) == 0) {
     600                        } else if (g_strncasecmp(ct, "text/x-msmsgsinitialmdatanotification", 37) == 0 ||
     601                                   g_strncasecmp(ct, "text/x-msmsgsoimnotification", 28) == 0) {
    690602                                /* We received an offline message. Or at least notification
    691603                                   that there is one waiting for us. Fetching the message(s)
     
    694606                                   have the notification server send them directly, I was
    695607                                   pretty sure I saw Pidgin do it..
    696                                    
     608
    697609                                   At least give a notification for now, seems like a
    698610                                   reasonable thing to do. Only problem is, they'll keep
    699611                                   coming back at login time until you read them using a
    700612                                   different client. :-( */
    701                                
    702                                 char *xml = get_rfc822_header( body, "Mail-Data:", blen );
     613
     614                                char *xml = get_rfc822_header(body, "Mail-Data:", blen);
    703615                                struct xt_node *md, *m;
    704                                
    705                                 if( !xml )
     616
     617                                if (!xml) {
    706618                                        return 1;
    707                                 md = xt_from_string( xml, 0 );
    708                                 if( !md )
     619                                }
     620                                md = xt_from_string(xml, 0);
     621                                if (!md) {
    709622                                        return 1;
    710                                
    711                                 for( m = md->children; ( m = xt_find_node( m, "M" ) ); m = m->next )
    712                                 {
    713                                         struct xt_node *e = xt_find_node( m->children, "E" );
    714                                         struct xt_node *rt = xt_find_node( m->children, "RT" );
     623                                }
     624
     625                                for (m = md->children; (m = xt_find_node(m, "M")); m = m->next) {
     626                                        struct xt_node *e = xt_find_node(m->children, "E");
     627                                        struct xt_node *rt = xt_find_node(m->children, "RT");
    715628                                        struct tm tp;
    716629                                        time_t msgtime = 0;
    717                                        
    718                                         if( !e || !e->text )
     630
     631                                        if (!e || !e->text) {
    719632                                                continue;
    720                                        
    721                                         memset( &tp, 0, sizeof( tp ) );
    722                                         if( rt && rt->text &&
    723                                             sscanf( rt->text, "%4d-%2d-%2dT%2d:%2d:%2d.",
    724                                                     &tp.tm_year, &tp.tm_mon, &tp.tm_mday,
    725                                                     &tp.tm_hour, &tp.tm_min, &tp.tm_sec ) == 6 )
    726                                         {
     633                                        }
     634
     635                                        memset(&tp, 0, sizeof(tp));
     636                                        if (rt && rt->text &&
     637                                            sscanf(rt->text, "%4d-%2d-%2dT%2d:%2d:%2d.",
     638                                                   &tp.tm_year, &tp.tm_mon, &tp.tm_mday,
     639                                                   &tp.tm_hour, &tp.tm_min, &tp.tm_sec) == 6) {
    727640                                                tp.tm_year -= 1900;
    728                                                 tp.tm_mon --;
    729                                                 msgtime = mktime_utc( &tp );
    730                                                
     641                                                tp.tm_mon--;
     642                                                msgtime = mktime_utc(&tp);
     643
    731644                                        }
    732                                         imcb_buddy_msg( ic, e->text, "<< \002BitlBee\002 - Received offline message. BitlBee can't show these. >>", 0, msgtime );
    733                                 }
    734                                
    735                                 g_free( xml );
    736                                 xt_free_node( md );
    737                         }
    738                         else
    739                         {
    740                                 debug( "Can't handle %s packet from notification server", ct );
    741                         }
    742                        
    743                         g_free( ct );
    744                 }
    745         }
    746         else if( strcmp( cmd[0], "UBX" ) == 0 )
    747         {
     645                                        imcb_buddy_msg(ic, e->text,
     646                                                       "<< \002BitlBee\002 - Received offline message. BitlBee can't show these. >>", 0,
     647                                                       msgtime);
     648                                }
     649
     650                                g_free(xml);
     651                                xt_free_node(md);
     652                        } else {
     653                                debug("Can't handle %s packet from notification server", ct);
     654                        }
     655
     656                        g_free(ct);
     657                }
     658        } else if (strcmp(cmd[0], "UBX") == 0) {
    748659                struct xt_node *ubx, *psm;
    749660                char *psm_text = NULL;
    750                
    751                 ubx = xt_from_string( msg, msglen );
    752                 if( ubx && strcmp( ubx->name, "Data" ) == 0 &&
    753                     ( psm = xt_find_node( ubx->children, "PSM" ) ) )
     661
     662                ubx = xt_from_string(msg, msglen);
     663                if (ubx && strcmp(ubx->name, "Data") == 0 &&
     664                    (psm = xt_find_node(ubx->children, "PSM"))) {
    754665                        psm_text = psm->text;
    755                
    756                 imcb_buddy_status_msg( ic, msn_normalize_handle( cmd[1] ), psm_text );
    757                 xt_free_node( ubx );
    758         }
    759         else if( strcmp( cmd[0], "ADL" ) == 0 )
    760         {
     666                }
     667
     668                imcb_buddy_status_msg(ic, msn_normalize_handle(cmd[1]), psm_text);
     669                xt_free_node(ubx);
     670        } else if (strcmp(cmd[0], "ADL") == 0) {
    761671                struct xt_node *adl, *d, *c;
    762                
    763                 if( !( adl = xt_from_string( msg, msglen ) ) )
     672
     673                if (!(adl = xt_from_string(msg, msglen))) {
    764674                        return 1;
    765                
    766                 for( d = adl->children; d; d = d->next )
    767                 {
     675                }
     676
     677                for (d = adl->children; d; d = d->next) {
    768678                        char *dn;
    769                         if( strcmp( d->name, "d" ) != 0 ||
    770                             ( dn = xt_find_attr( d, "n" ) ) == NULL )
     679                        if (strcmp(d->name, "d") != 0 ||
     680                            (dn = xt_find_attr(d, "n")) == NULL) {
    771681                                continue;
    772                         for( c = d->children; c; c = c->next )
    773                         {
     682                        }
     683                        for (c = d->children; c; c = c->next) {
    774684                                bee_user_t *bu;
    775685                                struct msn_buddy_data *bd;
    776686                                char *cn, *handle, *f, *l;
    777687                                int flags;
    778                                
    779                                 if( strcmp( c->name, "c" ) != 0 ||
    780                                     ( l = xt_find_attr( c, "l" ) ) == NULL ||
    781                                     ( cn = xt_find_attr( c, "n" ) ) == NULL )
     688
     689                                if (strcmp(c->name, "c") != 0 ||
     690                                    (l = xt_find_attr(c, "l")) == NULL ||
     691                                    (cn = xt_find_attr(c, "n")) == NULL) {
    782692                                        continue;
    783                                
     693                                }
     694
    784695                                /* FIXME: Use "t" here, guess I should just add it
    785696                                   as a prefix like elsewhere in the protocol. */
    786                                 handle = g_strdup_printf( "%s@%s", cn, dn );
    787                                 if( !( ( bu = bee_user_by_handle( ic->bee, ic, handle ) ) ||
    788                                        ( bu = bee_user_new( ic->bee, ic, handle, 0 ) ) ) )
    789                                 {
    790                                         g_free( handle );
     697                                handle = g_strdup_printf("%s@%s", cn, dn);
     698                                if (!((bu = bee_user_by_handle(ic->bee, ic, handle)) ||
     699                                      (bu = bee_user_new(ic->bee, ic, handle, 0)))) {
     700                                        g_free(handle);
    791701                                        continue;
    792702                                }
    793                                 g_free( handle );
     703                                g_free(handle);
    794704                                bd = bu->data;
    795                                
    796                                 if( ( f = xt_find_attr( c, "f" ) ) )
    797                                 {
    798                                         http_decode( f );
    799                                         imcb_rename_buddy( ic, bu->handle, f );
    800                                 }
    801                                
    802                                 flags = atoi( l ) & 15;
    803                                 if( bd->flags != flags )
    804                                 {
     705
     706                                if ((f = xt_find_attr(c, "f"))) {
     707                                        http_decode(f);
     708                                        imcb_rename_buddy(ic, bu->handle, f);
     709                                }
     710
     711                                flags = atoi(l) & 15;
     712                                if (bd->flags != flags) {
    805713                                        bd->flags = flags;
    806                                         msn_buddy_ask( bu );
    807                                 }
    808                         }
    809                 }
    810         }
    811         else if( strcmp( cmd[0], "UBM" ) == 0 )
    812         {
     714                                        msn_buddy_ask(bu);
     715                                }
     716                        }
     717                }
     718        } else if (strcmp(cmd[0], "UBM") == 0) {
    813719                /* This one will give us msgs from federated networks. Technically
    814720                   it should also get us offline messages, but I don't know how
    815721                   I can signal MSN servers to use it. */
    816722                char *ct, *handle;
    817                
    818                 if( strcmp( cmd[1], ic->acc->user ) == 0 )
    819                 {
     723
     724                if (strcmp(cmd[1], ic->acc->user) == 0) {
    820725                        /* With MPOP, you'll get copies of your own msgs from other
    821726                           sessions. Discard those at least for now. */
    822727                        return 1;
    823728                }
    824                
    825                 ct = get_rfc822_header( msg, "Content-Type", msglen );
    826                 if( strncmp( ct, "text/plain", 10 ) != 0 )
    827                 {
     729
     730                ct = get_rfc822_header(msg, "Content-Type", msglen);
     731                if (strncmp(ct, "text/plain", 10) != 0) {
    828732                        /* Typing notification or something? */
    829                         g_free( ct );
     733                        g_free(ct);
    830734                        return 1;
    831735                }
    832                 if( strcmp( cmd[2], "1" ) != 0 )
    833                         handle = g_strdup_printf( "%s:%s", cmd[2], cmd[1] );
    834                 else
    835                         handle = g_strdup( cmd[1] );
    836                
    837                 imcb_buddy_msg( ic, handle, body, 0, 0 );
    838                 g_free( handle );
    839         }
    840        
     736                if (strcmp(cmd[2], "1") != 0) {
     737                        handle = g_strdup_printf("%s:%s", cmd[2], cmd[1]);
     738                } else {
     739                        handle = g_strdup(cmd[1]);
     740                }
     741
     742                imcb_buddy_msg(ic, handle, body, 0, 0);
     743                g_free(handle);
     744        }
     745
    841746        return 1;
    842747}
    843748
    844 void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error )
     749void msn_auth_got_passport_token(struct im_connection *ic, const char *token, const char *error)
    845750{
    846751        struct msn_data *md;
    847        
     752
    848753        /* Dead connection? */
    849         if( g_slist_find( msn_connections, ic ) == NULL )
     754        if (g_slist_find(msn_connections, ic) == NULL) {
    850755                return;
    851        
     756        }
     757
    852758        md = ic->proto_data;
    853        
    854         if( token )
    855         {
    856                 msn_ns_write( ic, -1, "USR %d SSO S %s %s {%s}\r\n", ++md->trId, md->tokens[0], token, md->uuid );
    857         }
    858         else
    859         {
    860                 imcb_error( ic, "Error during Passport authentication: %s", error );
    861                 imc_logout( ic, TRUE );
    862         }
    863 }
    864 
    865 void msn_auth_got_contact_list( struct im_connection *ic )
     759
     760        if (token) {
     761                msn_ns_write(ic, -1, "USR %d SSO S %s %s {%s}\r\n", ++md->trId, md->tokens[0], token, md->uuid);
     762        } else {
     763                imcb_error(ic, "Error during Passport authentication: %s", error);
     764                imc_logout(ic, TRUE);
     765        }
     766}
     767
     768void msn_auth_got_contact_list(struct im_connection *ic)
    866769{
    867770        struct msn_data *md;
    868        
     771
    869772        /* Dead connection? */
    870         if( g_slist_find( msn_connections, ic ) == NULL )
     773        if (g_slist_find(msn_connections, ic) == NULL) {
    871774                return;
    872        
     775        }
     776
    873777        md = ic->proto_data;
    874         msn_ns_write( ic, -1, "BLP %d %s\r\n", ++md->trId, "BL" );
    875 }
    876 
    877 static gboolean msn_ns_send_adl_1( gpointer key, gpointer value, gpointer data )
     778        msn_ns_write(ic, -1, "BLP %d %s\r\n", ++md->trId, "BL");
     779}
     780
     781static gboolean msn_ns_send_adl_1(gpointer key, gpointer value, gpointer data)
    878782{
    879783        struct xt_node *adl = data, *d, *c;
     
    884788        char *domain;
    885789        char l[4];
    886        
    887         if( ( bd->flags & 7 ) == 0 || ( bd->flags & MSN_BUDDY_ADL_SYNCED ) )
     790
     791        if ((bd->flags & 7) == 0 || (bd->flags & MSN_BUDDY_ADL_SYNCED)) {
    888792                return FALSE;
    889        
    890         strcpy( handle, bu->handle );
    891         if( ( domain = strchr( handle, '@' ) ) == NULL ) /* WTF */
    892                 return FALSE;
     793        }
     794
     795        strcpy(handle, bu->handle);
     796        if ((domain = strchr(handle, '@')) == NULL) {    /* WTF */
     797                return FALSE;
     798        }
    893799        *domain = '\0';
    894         domain ++;
    895        
    896         if( ( d = adl->children ) == NULL ||
    897             g_strcasecmp( xt_find_attr( d, "n" ), domain ) != 0 )
    898         {
    899                 d = xt_new_node( "d", NULL, NULL );
    900                 xt_add_attr( d, "n", domain );
    901                 xt_insert_child( adl, d );
    902         }
    903        
    904         g_snprintf( l, sizeof( l ), "%d", bd->flags & 7 );
    905         c = xt_new_node( "c", NULL, NULL );
    906         xt_add_attr( c, "n", handle );
    907         xt_add_attr( c, "l", l );
    908         xt_add_attr( c, "t", "1" ); /* FIXME: Network type, i.e. 32 for Y!MSG */
    909         xt_insert_child( d, c );
    910        
     800        domain++;
     801
     802        if ((d = adl->children) == NULL ||
     803            g_strcasecmp(xt_find_attr(d, "n"), domain) != 0) {
     804                d = xt_new_node("d", NULL, NULL);
     805                xt_add_attr(d, "n", domain);
     806                xt_insert_child(adl, d);
     807        }
     808
     809        g_snprintf(l, sizeof(l), "%d", bd->flags & 7);
     810        c = xt_new_node("c", NULL, NULL);
     811        xt_add_attr(c, "n", handle);
     812        xt_add_attr(c, "l", l);
     813        xt_add_attr(c, "t", "1");   /* FIXME: Network type, i.e. 32 for Y!MSG */
     814        xt_insert_child(d, c);
     815
    911816        /* Do this in batches of 100. */
    912817        bd->flags |= MSN_BUDDY_ADL_SYNCED;
     
    914819}
    915820
    916 static void msn_ns_send_adl( struct im_connection *ic )
     821static void msn_ns_send_adl(struct im_connection *ic)
    917822{
    918823        struct xt_node *adl;
    919824        struct msn_data *md = ic->proto_data;
    920825        char *adls;
    921        
    922         adl = xt_new_node( "ml", NULL, NULL );
    923         xt_add_attr( adl, "l", "1" );
    924         g_tree_foreach( md->domaintree, msn_ns_send_adl_1, adl );
    925         if( adl->children == NULL )
    926         {
     826
     827        adl = xt_new_node("ml", NULL, NULL);
     828        xt_add_attr(adl, "l", "1");
     829        g_tree_foreach(md->domaintree, msn_ns_send_adl_1, adl);
     830        if (adl->children == NULL) {
    927831                /* This tells the caller that we're done now. */
    928832                md->adl_todo = -1;
    929                 xt_free_node( adl );
     833                xt_free_node(adl);
    930834                return;
    931835        }
    932        
    933         adls = xt_to_string( adl );
    934         xt_free_node( adl );
    935         msn_ns_write( ic, -1, "ADL %d %zd\r\n%s", ++md->trId, strlen( adls ), adls );
    936         g_free( adls );
    937 }
    938 
    939 static void msn_ns_send_adl_start( struct im_connection *ic )
     836
     837        adls = xt_to_string(adl);
     838        xt_free_node(adl);
     839        msn_ns_write(ic, -1, "ADL %d %zd\r\n%s", ++md->trId, strlen(adls), adls);
     840        g_free(adls);
     841}
     842
     843static void msn_ns_send_adl_start(struct im_connection *ic)
    940844{
    941845        struct msn_data *md;
    942846        GSList *l;
    943        
     847
    944848        /* Dead connection? */
    945         if( g_slist_find( msn_connections, ic ) == NULL )
     849        if (g_slist_find(msn_connections, ic) == NULL) {
    946850                return;
    947        
     851        }
     852
    948853        md = ic->proto_data;
    949854        md->adl_todo = 0;
    950         for( l = ic->bee->users; l; l = l->next )
    951         {
     855        for (l = ic->bee->users; l; l = l->next) {
    952856                bee_user_t *bu = l->data;
    953857                struct msn_buddy_data *bd = bu->data;
    954                
    955                 if( bu->ic != ic || ( bd->flags & 7 ) == 0 )
     858
     859                if (bu->ic != ic || (bd->flags & 7) == 0) {
    956860                        continue;
    957                
     861                }
     862
    958863                bd->flags &= ~MSN_BUDDY_ADL_SYNCED;
    959864                md->adl_todo++;
    960865        }
    961        
    962         msn_ns_send_adl( ic );
    963 }
    964 
    965 int msn_ns_finish_login( struct im_connection *ic )
     866
     867        msn_ns_send_adl(ic);
     868}
     869
     870int msn_ns_finish_login(struct im_connection *ic)
    966871{
    967872        struct msn_data *md = ic->proto_data;
    968        
    969         if( ic->flags & OPT_LOGGED_IN )
     873
     874        if (ic->flags & OPT_LOGGED_IN) {
    970875                return 1;
    971        
    972         if( md->adl_todo < 0 )
     876        }
     877
     878        if (md->adl_todo < 0) {
    973879                md->flags |= MSN_DONE_ADL;
    974        
    975         if( ( md->flags & MSN_DONE_ADL ) && ( md->flags & MSN_GOT_PROFILE ) )
    976         {
    977                 if( md->flags & MSN_EMAIL_UNVERIFIED )
    978                         imcb_connected( ic );
    979                 else
    980                         return msn_ns_set_display_name( ic, set_getstr( &ic->acc->set, "display_name" ) );
    981         }
    982        
     880        }
     881
     882        if ((md->flags & MSN_DONE_ADL) && (md->flags & MSN_GOT_PROFILE)) {
     883                if (md->flags & MSN_EMAIL_UNVERIFIED) {
     884                        imcb_connected(ic);
     885                } else {
     886                        return msn_ns_set_display_name(ic, set_getstr(&ic->acc->set, "display_name"));
     887                }
     888        }
     889
    983890        return 1;
    984891}
    985892
    986 int msn_ns_sendmessage( struct im_connection *ic, bee_user_t *bu, const char *text )
     893int msn_ns_sendmessage(struct im_connection *ic, bee_user_t *bu, const char *text)
    987894{
    988895        struct msn_data *md = ic->proto_data;
    989896        int type = 0;
    990897        char *buf, *handle;
    991        
    992         if( strncmp( text, "\r\r\r", 3 ) == 0 )
     898
     899        if (strncmp(text, "\r\r\r", 3) == 0) {
    993900                /* Err. Shouldn't happen but I guess it can. Don't send others
    994901                   any of the "SHAKE THAT THING" messages. :-D */
    995902                return 1;
    996        
     903        }
     904
    997905        /* This might be a federated contact. Get its network number,
    998906           prefixed to bu->handle with a colon. Default is 1. */
    999         for( handle = bu->handle; g_ascii_isdigit( *handle ); handle ++ )
     907        for (handle = bu->handle; g_ascii_isdigit(*handle); handle++) {
    1000908                type = type * 10 + *handle - '0';
    1001         if( *handle == ':' )
    1002                 handle ++;
    1003         else
     909        }
     910        if (*handle == ':') {
     911                handle++;
     912        } else {
    1004913                type = 1;
    1005        
    1006         buf = g_strdup_printf( "%s%s", MSN_MESSAGE_HEADERS, text );
    1007        
    1008         if( msn_ns_write( ic, -1, "UUM %d %s %d %d %zd\r\n%s",
    1009                                   ++md->trId, handle, type,
    1010                                   1, /* type == IM (not nudge/typing) */
    1011                                   strlen( buf ), buf ) )
     914        }
     915
     916        buf = g_strdup_printf("%s%s", MSN_MESSAGE_HEADERS, text);
     917
     918        if (msn_ns_write(ic, -1, "UUM %d %s %d %d %zd\r\n%s",
     919                         ++md->trId, handle, type,
     920                         1,          /* type == IM (not nudge/typing) */
     921                         strlen(buf), buf)) {
    1012922                return 1;
    1013         else
     923        } else {
    1014924                return 0;
    1015 }
    1016 
    1017 void msn_ns_oim_send_queue( struct im_connection *ic, GSList **msgq )
     925        }
     926}
     927
     928void msn_ns_oim_send_queue(struct im_connection *ic, GSList **msgq)
    1018929{
    1019930        GSList *l;
    1020        
    1021         for( l = *msgq; l; l = l->next )
    1022         {
     931
     932        for (l = *msgq; l; l = l->next) {
    1023933                struct msn_message *m = l->data;
    1024                 bee_user_t *bu = bee_user_by_handle( ic->bee, ic, m->who );
    1025                
    1026                 if( bu )
    1027                         if( !msn_ns_sendmessage( ic, bu, m->text ) )
     934                bee_user_t *bu = bee_user_by_handle(ic->bee, ic, m->who);
     935
     936                if (bu) {
     937                        if (!msn_ns_sendmessage(ic, bu, m->text)) {
    1028938                                return;
    1029         }
    1030        
    1031         while( *msgq != NULL )
    1032         {
     939                        }
     940                }
     941        }
     942
     943        while (*msgq != NULL) {
    1033944                struct msn_message *m = (*msgq)->data;
    1034                
    1035                 g_free( m->who );
    1036                 g_free( m->text );
    1037                 g_free( m );
    1038                
    1039                 *msgq = g_slist_remove( *msgq, m );
    1040         }
    1041 }
     945
     946                g_free(m->who);
     947                g_free(m->text);
     948                g_free(m);
     949
     950                *msgq = g_slist_remove(*msgq, m);
     951        }
     952}
  • protocols/msn/sb.c

    raf359b4 r5ebff60  
    1   /********************************************************************\
     1/********************************************************************\
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
     
    3131#include "invitation.h"
    3232
    33 static 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, ... )
     33static gboolean msn_sb_callback(gpointer data, gint source, b_input_condition cond);
     34static int msn_sb_command(struct msn_handler_data *handler, char **cmd, int num_parts);
     35static int msn_sb_message(struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts);
     36
     37int msn_sb_write(struct msn_switchboard *sb, const char *fmt, ...)
    3838{
    3939        va_list params;
     
    4141        size_t len;
    4242        int st;
    43        
    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\n", sb->fd, out );
    50        
    51         len = strlen( out );
    52         st = write( sb->fd, out, len );
    53         g_free( out );
    54         if( st != len )
    55         {
    56                 msn_sb_destroy( sb );
     43
     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\n", sb->fd, out);
     50        }
     51
     52        len = strlen(out);
     53        st = write(sb->fd, out, len);
     54        g_free(out);
     55        if (st != len) {
     56                msn_sb_destroy(sb);
    5757                return 0;
    5858        }
    59        
     59
    6060        return 1;
    6161}
    6262
    63 int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m )
     63int msn_sb_write_msg(struct im_connection *ic, struct msn_message *m)
    6464{
    6565        struct msn_data *md = ic->proto_data;
     
    6767
    6868        /* FIXME: *CHECK* the reliability of using spare sb's! */
    69         if( ( sb = msn_sb_spare( ic ) ) )
    70         {
    71                 debug( "Trying to use a spare switchboard to message %s", m->who );
    72                
    73                 sb->who = g_strdup( m->who );
    74                 if( msn_sb_write( sb, "CAL %d %s\r\n", ++sb->trId, m->who ) )
    75                 {
     69        if ((sb = msn_sb_spare(ic))) {
     70                debug("Trying to use a spare switchboard to message %s", m->who);
     71
     72                sb->who = g_strdup(m->who);
     73                if (msn_sb_write(sb, "CAL %d %s\r\n", ++sb->trId, m->who)) {
    7674                        /* He/She should join the switchboard soon, let's queue the message. */
    77                         sb->msgq = g_slist_append( sb->msgq, m );
    78                         return( 1 );
    79                 }
    80         }
    81        
    82         debug( "Creating a new switchboard to message %s", m->who );
    83        
     75                        sb->msgq = g_slist_append(sb->msgq, m);
     76                        return(1);
     77                }
     78        }
     79
     80        debug("Creating a new switchboard to message %s", m->who);
     81
    8482        /* 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 ) )
    86         {
    87                 g_free( m->who );
    88                 g_free( m->text );
    89                 g_free( m );
    90                
    91                 return( 0 );
    92         }
    93        
     83        if (!msn_ns_write(ic, -1, "XFR %d SB\r\n", ++md->trId)) {
     84                g_free(m->who);
     85                g_free(m->text);
     86                g_free(m);
     87
     88                return(0);
     89        }
     90
    9491        /* And queue the message to md. We'll pick it up when the switchboard comes up. */
    95         md->msgq = g_slist_append( md->msgq, m );
    96        
     92        md->msgq = g_slist_append(md->msgq, m);
     93
    9794        /* FIXME: If the switchboard creation fails, the message will not be sent. */
    98        
    99         return( 1 );
    100 }
    101 
    102 struct msn_switchboard *msn_sb_create( struct im_connection *ic, char *host, int port, char *key, int session )
     95
     96        return(1);
     97}
     98
     99struct msn_switchboard *msn_sb_create(struct im_connection *ic, char *host, int port, char *key, int session)
    103100{
    104101        struct msn_data *md = ic->proto_data;
    105         struct msn_switchboard *sb = g_new0( struct msn_switchboard, 1 );
    106        
    107         sb->fd = proxy_connect( host, port, msn_sb_connected, sb );
    108         if( sb->fd < 0 )
    109         {
    110                 g_free( sb );
    111                 return( NULL );
    112         }
    113        
     102        struct msn_switchboard *sb = g_new0(struct msn_switchboard, 1);
     103
     104        sb->fd = proxy_connect(host, port, msn_sb_connected, sb);
     105        if (sb->fd < 0) {
     106                g_free(sb);
     107                return(NULL);
     108        }
     109
    114110        sb->ic = ic;
    115         sb->key = g_strdup( key );
     111        sb->key = g_strdup(key);
    116112        sb->session = session;
    117        
    118         msn_switchboards = g_slist_append( msn_switchboards, sb );
    119         md->switchboards = g_slist_append( md->switchboards, sb );
    120        
    121         return( sb );
    122 }
    123 
    124 struct msn_switchboard *msn_sb_by_handle( struct im_connection *ic, const char *handle )
     113
     114        msn_switchboards = g_slist_append(msn_switchboards, sb);
     115        md->switchboards = g_slist_append(md->switchboards, sb);
     116
     117        return(sb);
     118}
     119
     120struct msn_switchboard *msn_sb_by_handle(struct im_connection *ic, const char *handle)
    125121{
    126122        struct msn_data *md = ic->proto_data;
    127123        struct msn_switchboard *sb;
    128124        GSList *l;
    129        
    130         for( l = md->switchboards; l; l = l->next )
    131         {
     125
     126        for (l = md->switchboards; l; l = l->next) {
    132127                sb = l->data;
    133                 if( sb->who && strcmp( sb->who, handle ) == 0 )
    134                         return( sb );
    135         }
    136        
    137         return( NULL );
    138 }
    139 
    140 struct msn_switchboard *msn_sb_by_chat( struct groupchat *c )
     128                if (sb->who && strcmp(sb->who, handle) == 0) {
     129                        return(sb);
     130                }
     131        }
     132
     133        return(NULL);
     134}
     135
     136struct msn_switchboard *msn_sb_by_chat(struct groupchat *c)
    141137{
    142138        struct msn_data *md = c->ic->proto_data;
    143139        struct msn_switchboard *sb;
    144140        GSList *l;
    145        
    146         for( l = md->switchboards; l; l = l->next )
    147         {
     141
     142        for (l = md->switchboards; l; l = l->next) {
    148143                sb = l->data;
    149                 if( sb->chat == c )
    150                         return( sb );
    151         }
    152        
    153         return( NULL );
    154 }
    155 
    156 struct msn_switchboard *msn_sb_spare( struct im_connection *ic )
     144                if (sb->chat == c) {
     145                        return(sb);
     146                }
     147        }
     148
     149        return(NULL);
     150}
     151
     152struct msn_switchboard *msn_sb_spare(struct im_connection *ic)
    157153{
    158154        struct msn_data *md = ic->proto_data;
    159155        struct msn_switchboard *sb;
    160156        GSList *l;
    161        
    162         for( l = md->switchboards; l; l = l->next )
    163         {
     157
     158        for (l = md->switchboards; l; l = l->next) {
    164159                sb = l->data;
    165                 if( !sb->who && !sb->chat )
    166                         return( sb );
    167         }
    168        
    169         return( NULL );
    170 }
    171 
    172 int msn_sb_sendmessage( struct msn_switchboard *sb, char *text )
    173 {
    174         if( sb->ready )
    175         {
     160                if (!sb->who && !sb->chat) {
     161                        return(sb);
     162                }
     163        }
     164
     165        return(NULL);
     166}
     167
     168int msn_sb_sendmessage(struct msn_switchboard *sb, char *text)
     169{
     170        if (sb->ready) {
    176171                char *buf;
    177172                int i, j;
    178                
     173
    179174                /* Build the message. Convert LF to CR-LF for normal messages. */
    180                 if( strcmp( text, TYPING_NOTIFICATION_MESSAGE ) == 0 )
    181                 {
    182                         i = strlen( MSN_TYPING_HEADERS ) + strlen( sb->ic->acc->user );
    183                         buf = g_new0( char, i );
    184                         i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->ic->acc->user );
    185                 }
    186                 else if( strcmp( text, NUDGE_MESSAGE ) == 0 )
    187                 {
    188                         buf = g_strdup( MSN_NUDGE_HEADERS );
    189                         i = strlen( buf );
    190                 }
    191                 else if( strcmp( text, SB_KEEPALIVE_MESSAGE ) == 0 )
    192                 {
    193                         buf = g_strdup( MSN_SB_KEEPALIVE_HEADERS );
    194                         i = strlen( buf );
    195                 }
    196                 else if( strncmp( text, MSN_INVITE_HEADERS, sizeof( MSN_INVITE_HEADERS ) - 1 ) == 0 )
    197                 {
    198                         buf = g_strdup( text );
    199                         i = strlen( buf );
    200                 }
    201                 else
    202                 {
    203                         buf = g_new0( char, sizeof( MSN_MESSAGE_HEADERS ) + strlen( text ) * 2 + 1 );
    204                         i = strlen( MSN_MESSAGE_HEADERS );
    205                        
    206                         strcpy( buf, MSN_MESSAGE_HEADERS );
    207                         for( j = 0; text[j]; j ++ )
    208                         {
    209                                 if( text[j] == '\n' )
     175                if (strcmp(text, TYPING_NOTIFICATION_MESSAGE) == 0) {
     176                        i = strlen(MSN_TYPING_HEADERS) + strlen(sb->ic->acc->user);
     177                        buf = g_new0(char, i);
     178                        i = g_snprintf(buf, i, MSN_TYPING_HEADERS, sb->ic->acc->user);
     179                } else if (strcmp(text, NUDGE_MESSAGE) == 0) {
     180                        buf = g_strdup(MSN_NUDGE_HEADERS);
     181                        i = strlen(buf);
     182                } else if (strcmp(text, SB_KEEPALIVE_MESSAGE) == 0) {
     183                        buf = g_strdup(MSN_SB_KEEPALIVE_HEADERS);
     184                        i = strlen(buf);
     185                } else if (strncmp(text, MSN_INVITE_HEADERS, sizeof(MSN_INVITE_HEADERS) - 1) == 0) {
     186                        buf = g_strdup(text);
     187                        i = strlen(buf);
     188                } else {
     189                        buf = g_new0(char, sizeof(MSN_MESSAGE_HEADERS) + strlen(text) * 2 + 1);
     190                        i = strlen(MSN_MESSAGE_HEADERS);
     191
     192                        strcpy(buf, MSN_MESSAGE_HEADERS);
     193                        for (j = 0; text[j]; j++) {
     194                                if (text[j] == '\n') {
    210195                                        buf[i++] = '\r';
    211                                
     196                                }
     197
    212198                                buf[i++] = text[j];
    213199                        }
    214200                }
    215                
     201
    216202                /* Build the final packet (MSG command + the message). */
    217                 if( msn_sb_write( sb, "MSG %d N %d\r\n%s", ++sb->trId, i, buf ) )
    218                 {
    219                         g_free( buf );
     203                if (msn_sb_write(sb, "MSG %d N %d\r\n%s", ++sb->trId, i, buf)) {
     204                        g_free(buf);
    220205                        return 1;
    221                 }
    222                 else
    223                 {
    224                         g_free( buf );
     206                } else {
     207                        g_free(buf);
    225208                        return 0;
    226209                }
    227         }
    228         else if( sb->who )
    229         {
    230                 struct msn_message *m = g_new0( struct msn_message, 1 );
    231                
    232                 m->who = g_strdup( "" );
    233                 m->text = g_strdup( text );
    234                 sb->msgq = g_slist_append( sb->msgq, m );
    235                
    236                 return( 1 );
    237         }
    238         else
    239         {
    240                 return( 0 );
    241         }
    242 }
    243 
    244 struct groupchat *msn_sb_to_chat( struct msn_switchboard *sb )
     210        } else if (sb->who) {
     211                struct msn_message *m = g_new0(struct msn_message, 1);
     212
     213                m->who = g_strdup("");
     214                m->text = g_strdup(text);
     215                sb->msgq = g_slist_append(sb->msgq, m);
     216
     217                return(1);
     218        } else {
     219                return(0);
     220        }
     221}
     222
     223struct groupchat *msn_sb_to_chat(struct msn_switchboard *sb)
    245224{
    246225        struct im_connection *ic = sb->ic;
    247226        struct groupchat *c = NULL;
    248227        char buf[1024];
    249        
     228
    250229        /* Create the groupchat structure. */
    251         g_snprintf( buf, sizeof( buf ), "MSN groupchat session %d", sb->session );
    252         if( sb->who )
    253                 c = bee_chat_by_title( ic->bee, ic, sb->who );
    254         if( c && !msn_sb_by_chat( c ) )
     230        g_snprintf(buf, sizeof(buf), "MSN groupchat session %d", sb->session);
     231        if (sb->who) {
     232                c = bee_chat_by_title(ic->bee, ic, sb->who);
     233        }
     234        if (c && !msn_sb_by_chat(c)) {
    255235                sb->chat = c;
    256         else
    257                 sb->chat = imcb_chat_new( ic, buf );
    258        
     236        } else {
     237                sb->chat = imcb_chat_new(ic, buf);
     238        }
     239
    259240        /* Populate the channel. */
    260         if( sb->who ) imcb_chat_add_buddy( sb->chat, sb->who );
    261         imcb_chat_add_buddy( sb->chat, ic->acc->user );
    262        
     241        if (sb->who) {
     242                imcb_chat_add_buddy(sb->chat, sb->who);
     243        }
     244        imcb_chat_add_buddy(sb->chat, ic->acc->user);
     245
    263246        /* And make sure the switchboard doesn't look like a regular chat anymore. */
    264         if( sb->who )
    265         {
    266                 g_free( sb->who );
     247        if (sb->who) {
     248                g_free(sb->who);
    267249                sb->who = NULL;
    268250        }
    269        
     251
    270252        return sb->chat;
    271253}
    272254
    273 void msn_sb_destroy( struct msn_switchboard *sb )
     255void msn_sb_destroy(struct msn_switchboard *sb)
    274256{
    275257        struct im_connection *ic = sb->ic;
    276258        struct msn_data *md = ic->proto_data;
    277        
    278         debug( "Destroying switchboard: %s", sb->who ? sb->who : sb->key ? sb->key : "" );
    279        
    280         msn_msgq_purge( ic, &sb->msgq );
    281         msn_sb_stop_keepalives( sb );
    282        
    283         if( sb->key ) g_free( sb->key );
    284         if( sb->who ) g_free( sb->who );
    285        
    286         if( sb->chat )
    287         {
    288                 imcb_chat_free( sb->chat );
    289         }
    290        
    291         if( sb->handler )
    292         {
    293                 if( sb->handler->rxq ) g_free( sb->handler->rxq );
    294                 if( sb->handler->cmd_text ) g_free( sb->handler->cmd_text );
    295                 g_free( sb->handler );
    296         }
    297        
    298         if( sb->inp ) b_event_remove( sb->inp );
    299         closesocket( sb->fd );
    300        
    301         msn_switchboards = g_slist_remove( msn_switchboards, sb );
    302         md->switchboards = g_slist_remove( md->switchboards, sb );
    303         g_free( sb );
    304 }
    305 
    306 gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond )
     259
     260        debug("Destroying switchboard: %s", sb->who ? sb->who : sb->key ? sb->key : "");
     261
     262        msn_msgq_purge(ic, &sb->msgq);
     263        msn_sb_stop_keepalives(sb);
     264
     265        if (sb->key) {
     266                g_free(sb->key);
     267        }
     268        if (sb->who) {
     269                g_free(sb->who);
     270        }
     271
     272        if (sb->chat) {
     273                imcb_chat_free(sb->chat);
     274        }
     275
     276        if (sb->handler) {
     277                if (sb->handler->rxq) {
     278                        g_free(sb->handler->rxq);
     279                }
     280                if (sb->handler->cmd_text) {
     281                        g_free(sb->handler->cmd_text);
     282                }
     283                g_free(sb->handler);
     284        }
     285
     286        if (sb->inp) {
     287                b_event_remove(sb->inp);
     288        }
     289        closesocket(sb->fd);
     290
     291        msn_switchboards = g_slist_remove(msn_switchboards, sb);
     292        md->switchboards = g_slist_remove(md->switchboards, sb);
     293        g_free(sb);
     294}
     295
     296gboolean msn_sb_connected(gpointer data, gint source, b_input_condition cond)
    307297{
    308298        struct msn_switchboard *sb = data;
     
    310300        struct msn_data *md;
    311301        char buf[1024];
    312        
     302
    313303        /* Are we still alive? */
    314         if( !g_slist_find( msn_switchboards, sb ) )
     304        if (!g_slist_find(msn_switchboards, sb)) {
    315305                return FALSE;
    316        
     306        }
     307
    317308        ic = sb->ic;
    318309        md = ic->proto_data;
    319        
    320         if( source != sb->fd )
    321         {
    322                 debug( "Error %d while connecting to switchboard server", 1 );
    323                 msn_sb_destroy( sb );
     310
     311        if (source != sb->fd) {
     312                debug("Error %d while connecting to switchboard server", 1);
     313                msn_sb_destroy(sb);
    324314                return FALSE;
    325315        }
    326        
     316
    327317        /* Prepare the callback */
    328         sb->handler = g_new0( struct msn_handler_data, 1 );
     318        sb->handler = g_new0(struct msn_handler_data, 1);
    329319        sb->handler->fd = sb->fd;
    330         sb->handler->rxq = g_new0( char, 1 );
     320        sb->handler->rxq = g_new0(char, 1);
    331321        sb->handler->data = sb;
    332322        sb->handler->exec_command = msn_sb_command;
    333323        sb->handler->exec_message = msn_sb_message;
    334        
    335         if( sb->session == MSN_SB_NEW )
    336                 g_snprintf( buf, sizeof( buf ), "USR %d %s;{%s} %s\r\n", ++sb->trId, ic->acc->user, md->uuid, sb->key );
    337         else
    338                 g_snprintf( buf, sizeof( buf ), "ANS %d %s;{%s} %s %d\r\n", ++sb->trId, ic->acc->user, md->uuid, sb->key, sb->session );
    339        
    340         if( msn_sb_write( sb, "%s", buf ) )
    341                 sb->inp = b_input_add( sb->fd, B_EV_IO_READ, msn_sb_callback, sb );
    342         else
    343                 debug( "Error %d while connecting to switchboard server", 2 );
    344        
     324
     325        if (sb->session == MSN_SB_NEW) {
     326                g_snprintf(buf, sizeof(buf), "USR %d %s;{%s} %s\r\n", ++sb->trId, ic->acc->user, md->uuid, sb->key);
     327        } else {
     328                g_snprintf(buf, sizeof(buf), "ANS %d %s;{%s} %s %d\r\n", ++sb->trId, ic->acc->user, md->uuid, sb->key,
     329                           sb->session);
     330        }
     331
     332        if (msn_sb_write(sb, "%s", buf)) {
     333                sb->inp = b_input_add(sb->fd, B_EV_IO_READ, msn_sb_callback, sb);
     334        } else {
     335                debug("Error %d while connecting to switchboard server", 2);
     336        }
     337
    345338        return FALSE;
    346339}
    347340
    348 static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond )
     341static gboolean msn_sb_callback(gpointer data, gint source, b_input_condition cond)
    349342{
    350343        struct msn_switchboard *sb = data;
    351344        struct im_connection *ic = sb->ic;
    352345        struct msn_data *md = ic->proto_data;
    353        
    354         if( msn_handler( sb->handler ) != -1 )
     346
     347        if (msn_handler(sb->handler) != -1) {
    355348                return TRUE;
    356        
    357         if( sb->msgq != NULL )
    358         {
    359                 time_t now = time( NULL );
    360                
    361                 if( now - md->first_sb_failure > 600 )
    362                 {
     349        }
     350
     351        if (sb->msgq != NULL) {
     352                time_t now = time(NULL);
     353
     354                if (now - md->first_sb_failure > 600) {
    363355                        /* It's not really the first one, but the start of this "series".
    364356                           With this, the warning below will be shown only if this happens
     
    368360                        md->sb_failures = 0;
    369361