source: protocols/msn/sb.c @ 9bf2481

Last change on this file since 9bf2481 was 9bf2481, checked in by Wilmer van der Gaast <wilmer@…>, at 2010-04-09T23:16:38Z

First stab at MSN keepalives.

Only kicks in if the user goes offline during a conversation.

  • Property mode set to 100644
File size: 17.7 KB
RevLine 
[b7d3cc34]1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
[c92e6801]4  * Copyright 2002-2005 Wilmer van der Gaast and others                *
[b7d3cc34]5  \********************************************************************/
6
7/* MSN module - Switchboard server callbacks and utilities              */
8
9/*
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License with
21  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
22  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
23  Suite 330, Boston, MA  02111-1307  USA
24*/
25
26#include <ctype.h>
27#include "nogaim.h"
28#include "msn.h"
29#include "passport.h"
30#include "md5.h"
31
[ba9edaa]32static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond );
[b7d3cc34]33static int msn_sb_command( gpointer data, char **cmd, int num_parts );
34static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts );
35
36int msn_sb_write( struct msn_switchboard *sb, char *s, int len )
37{
38        int st;
39       
40        st = write( sb->fd, s, len );
41        if( st != len )
42        {
43                msn_sb_destroy( sb );
44                return( 0 );
45        }
46       
47        return( 1 );
48}
49
[a830512]50int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m )
51{
52        struct msn_data *md = ic->proto_data;
53        struct msn_switchboard *sb;
54        char buf[1024];
55
56        /* FIXME: *CHECK* the reliability of using spare sb's! */
57        if( ( sb = msn_sb_spare( ic ) ) )
58        {
59                debug( "Trying to use a spare switchboard to message %s", m->who );
60               
61                sb->who = g_strdup( m->who );
62                g_snprintf( buf, sizeof( buf ), "CAL %d %s\r\n", ++sb->trId, m->who );
63                if( msn_sb_write( sb, buf, strlen( buf ) ) )
64                {
65                        /* He/She should join the switchboard soon, let's queue the message. */
66                        sb->msgq = g_slist_append( sb->msgq, m );
67                        return( 1 );
68                }
69        }
70       
71        debug( "Creating a new switchboard to message %s", m->who );
72       
73        /* If we reach this line, there was no spare switchboard, so let's make one. */
74        g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId );
75        if( !msn_write( ic, buf, strlen( buf ) ) )
76        {
77                g_free( m->who );
78                g_free( m->text );
79                g_free( m );
80               
81                return( 0 );
82        }
83       
84        /* And queue the message to md. We'll pick it up when the switchboard comes up. */
85        md->msgq = g_slist_append( md->msgq, m );
86       
87        /* FIXME: If the switchboard creation fails, the message will not be sent. */
88       
89        return( 1 );
90}
91
[0da65d5]92struct msn_switchboard *msn_sb_create( struct im_connection *ic, char *host, int port, char *key, int session )
[b7d3cc34]93{
[0da65d5]94        struct msn_data *md = ic->proto_data;
[b7d3cc34]95        struct msn_switchboard *sb = g_new0( struct msn_switchboard, 1 );
96       
97        sb->fd = proxy_connect( host, port, msn_sb_connected, sb );
98        if( sb->fd < 0 )
99        {
100                g_free( sb );
101                return( NULL );
102        }
103       
[0da65d5]104        sb->ic = ic;
[b7d3cc34]105        sb->key = g_strdup( key );
106        sb->session = session;
107       
108        msn_switchboards = g_slist_append( msn_switchboards, sb );
109        md->switchboards = g_slist_append( md->switchboards, sb );
110       
111        return( sb );
112}
113
[0da65d5]114struct msn_switchboard *msn_sb_by_handle( struct im_connection *ic, char *handle )
[b7d3cc34]115{
[0da65d5]116        struct msn_data *md = ic->proto_data;
[b7d3cc34]117        struct msn_switchboard *sb;
118        GSList *l;
119       
120        for( l = md->switchboards; l; l = l->next )
121        {
122                sb = l->data;
123                if( sb->who && strcmp( sb->who, handle ) == 0 )
124                        return( sb );
125        }
126       
127        return( NULL );
128}
129
[0da65d5]130struct msn_switchboard *msn_sb_by_chat( struct groupchat *c )
[b7d3cc34]131{
[0da65d5]132        struct msn_data *md = c->ic->proto_data;
[b7d3cc34]133        struct msn_switchboard *sb;
134        GSList *l;
135       
136        for( l = md->switchboards; l; l = l->next )
137        {
138                sb = l->data;
[fa29d093]139                if( sb->chat == c )
[b7d3cc34]140                        return( sb );
141        }
142       
143        return( NULL );
144}
145
[0da65d5]146struct msn_switchboard *msn_sb_spare( struct im_connection *ic )
[b7d3cc34]147{
[0da65d5]148        struct msn_data *md = ic->proto_data;
[b7d3cc34]149        struct msn_switchboard *sb;
150        GSList *l;
151       
152        for( l = md->switchboards; l; l = l->next )
153        {
154                sb = l->data;
155                if( !sb->who && !sb->chat )
156                        return( sb );
157        }
158       
159        return( NULL );
160}
161
162int msn_sb_sendmessage( struct msn_switchboard *sb, char *text )
163{
164        if( sb->ready )
165        {
[bd28e6a]166                char *packet, *buf;
[b7d3cc34]167                int i, j;
168               
[bd28e6a]169                /* Build the message. Convert LF to CR-LF for normal messages. */
[9bf2481]170                if( strcmp( text, TYPING_NOTIFICATION_MESSAGE ) == 0 )
171                {
172                        i = strlen( MSN_TYPING_HEADERS ) + strlen( sb->ic->acc->user );
173                        buf = g_new0( char, i );
174                        i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->ic->acc->user );
175                }
176                else if( strcmp( text, SB_KEEPALIVE_MESSAGE ) == 0 )
177                {
178                        buf = g_strdup( SB_KEEPALIVE_HEADERS );
179                        i = strlen( buf );
180                }
181                else
[b7d3cc34]182                {
[46dca11]183                        buf = g_new0( char, sizeof( MSN_MESSAGE_HEADERS ) + strlen( text ) * 2 + 1 );
[b7d3cc34]184                        i = strlen( MSN_MESSAGE_HEADERS );
185                       
186                        strcpy( buf, MSN_MESSAGE_HEADERS );
187                        for( j = 0; text[j]; j ++ )
188                        {
189                                if( text[j] == '\n' )
190                                        buf[i++] = '\r';
191                               
192                                buf[i++] = text[j];
193                        }
194                }
195               
[bd28e6a]196                /* Build the final packet (MSG command + the message). */
197                packet = g_strdup_printf( "MSG %d N %d\r\n%s", ++sb->trId, i, buf );
198                g_free( buf );
199                if( msn_sb_write( sb, packet, strlen( packet ) ) )
[b7d3cc34]200                {
[bd28e6a]201                        g_free( packet );
[b7d3cc34]202                        return( 1 );
203                }
204                else
205                {
[bd28e6a]206                        g_free( packet );
[b7d3cc34]207                        return( 0 );
208                }
209        }
210        else if( sb->who )
211        {
212                struct msn_message *m = g_new0( struct msn_message, 1 );
213               
214                m->who = g_strdup( "" );
215                m->text = g_strdup( text );
216                sb->msgq = g_slist_append( sb->msgq, m );
217               
218                return( 1 );
219        }
220        else
221        {
222                return( 0 );
223        }
224}
225
[0da65d5]226struct groupchat *msn_sb_to_chat( struct msn_switchboard *sb )
[b7d3cc34]227{
[0da65d5]228        struct im_connection *ic = sb->ic;
[b7d3cc34]229        char buf[1024];
230       
231        /* Create the groupchat structure. */
232        g_snprintf( buf, sizeof( buf ), "MSN groupchat session %d", sb->session );
[61ae52c]233        sb->chat = imcb_chat_new( ic, buf );
[b7d3cc34]234       
235        /* Populate the channel. */
[61ae52c]236        if( sb->who ) imcb_chat_add_buddy( sb->chat, sb->who );
237        imcb_chat_add_buddy( sb->chat, ic->acc->user );
[b7d3cc34]238       
239        /* And make sure the switchboard doesn't look like a regular chat anymore. */
240        if( sb->who )
241        {
242                g_free( sb->who );
243                sb->who = NULL;
244        }
[fa29d093]245       
246        return sb->chat;
[b7d3cc34]247}
248
249void msn_sb_destroy( struct msn_switchboard *sb )
250{
[0da65d5]251        struct im_connection *ic = sb->ic;
252        struct msn_data *md = ic->proto_data;
[b7d3cc34]253       
254        debug( "Destroying switchboard: %s", sb->who ? sb->who : sb->key ? sb->key : "" );
255       
[46dca11]256        msn_msgq_purge( ic, &sb->msgq );
[b7d3cc34]257       
[8ba511d]258        if( sb->key ) g_free( sb->key );
259        if( sb->who ) g_free( sb->who );
260       
[b7d3cc34]261        if( sb->chat )
262        {
[e35d1a1]263                imcb_chat_free( sb->chat );
[b7d3cc34]264        }
265       
266        if( sb->handler )
267        {
268                if( sb->handler->rxq ) g_free( sb->handler->rxq );
269                if( sb->handler->cmd_text ) g_free( sb->handler->cmd_text );
270                g_free( sb->handler );
271        }
272       
[ba9edaa]273        if( sb->inp ) b_event_remove( sb->inp );
[b7d3cc34]274        closesocket( sb->fd );
275       
276        msn_switchboards = g_slist_remove( msn_switchboards, sb );
277        md->switchboards = g_slist_remove( md->switchboards, sb );
278        g_free( sb );
279}
280
[ba9edaa]281gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond )
[b7d3cc34]282{
283        struct msn_switchboard *sb = data;
[0da65d5]284        struct im_connection *ic;
[b7d3cc34]285        struct msn_data *md;
286        char buf[1024];
287       
288        /* Are we still alive? */
289        if( !g_slist_find( msn_switchboards, sb ) )
[ba9edaa]290                return FALSE;
[b7d3cc34]291       
[0da65d5]292        ic = sb->ic;
293        md = ic->proto_data;
[b7d3cc34]294       
295        if( source != sb->fd )
296        {
[46dca11]297                debug( "Error %d while connecting to switchboard server", 1 );
[b7d3cc34]298                msn_sb_destroy( sb );
[ba9edaa]299                return FALSE;
[b7d3cc34]300        }
301       
302        /* Prepare the callback */
303        sb->handler = g_new0( struct msn_handler_data, 1 );
304        sb->handler->fd = sb->fd;
305        sb->handler->rxq = g_new0( char, 1 );
306        sb->handler->data = sb;
307        sb->handler->exec_command = msn_sb_command;
308        sb->handler->exec_message = msn_sb_message;
309       
310        if( sb->session == MSN_SB_NEW )
[c2fb3809]311                g_snprintf( buf, sizeof( buf ), "USR %d %s %s\r\n", ++sb->trId, ic->acc->user, sb->key );
[b7d3cc34]312        else
[c2fb3809]313                g_snprintf( buf, sizeof( buf ), "ANS %d %s %s %d\r\n", ++sb->trId, ic->acc->user, sb->key, sb->session );
[b7d3cc34]314       
315        if( msn_sb_write( sb, buf, strlen( buf ) ) )
[ba9edaa]316                sb->inp = b_input_add( sb->fd, GAIM_INPUT_READ, msn_sb_callback, sb );
[b7d3cc34]317        else
[46dca11]318                debug( "Error %d while connecting to switchboard server", 2 );
[ba9edaa]319       
320        return FALSE;
[b7d3cc34]321}
322
[ba9edaa]323static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond )
[b7d3cc34]324{
325        struct msn_switchboard *sb = data;
[59f527b6]326        struct im_connection *ic = sb->ic;
327        struct msn_data *md = ic->proto_data;
[b7d3cc34]328       
329        if( msn_handler( sb->handler ) == -1 )
330        {
[59f527b6]331                time_t now = time( NULL );
332               
333                if( now - md->first_sb_failure > 600 )
334                {
335                        /* It's not really the first one, but the start of this "series".
336                           With this, the warning below will be shown only if this happens
337                           at least three times in ten minutes. This algorithm isn't
338                           perfect, but for this purpose it will do. */
339                        md->first_sb_failure = now;
340                        md->sb_failures = 0;
341                }
342               
[46dca11]343                debug( "Error: Switchboard died" );
[59f527b6]344                if( ++ md->sb_failures >= 3 )
345                        imcb_log( ic, "Warning: Many switchboard failures on MSN connection. "
346                                      "There might be problems delivering your messages." );
347               
348                if( sb->msgq != NULL )
349                {
350                        char buf[1024];
351                       
352                        if( md->msgq == NULL )
353                        {
354                                md->msgq = sb->msgq;
355                        }
356                        else
357                        {
358                                GSList *l;
359                               
360                                for( l = md->msgq; l->next; l = l->next );
361                                l->next = sb->msgq;
362                        }
363                        sb->msgq = NULL;
364                       
365                        debug( "Moved queued messages back to the main queue, creating a new switchboard to retry." );
366                        g_snprintf( buf, sizeof( buf ), "XFR %d SB\r\n", ++md->trId );
367                        if( !msn_write( ic, buf, strlen( buf ) ) )
368                                return FALSE;
369                }
370               
[b7d3cc34]371                msn_sb_destroy( sb );
[ba9edaa]372               
373                return FALSE;
[b7d3cc34]374        }
[ba9edaa]375        else
[59f527b6]376        {
[ba9edaa]377                return TRUE;
[59f527b6]378        }
[b7d3cc34]379}
380
381static int msn_sb_command( gpointer data, char **cmd, int num_parts )
382{
383        struct msn_switchboard *sb = data;
[0da65d5]384        struct im_connection *ic = sb->ic;
[b7d3cc34]385        char buf[1024];
386       
387        if( !num_parts )
388        {
389                /* Hrrm... Empty command...? Ignore? */
390                return( 1 );
391        }
392       
393        if( strcmp( cmd[0], "XFR" ) == 0 )
394        {
[84b045d]395                imcb_error( ic, "Received an XFR from a switchboard server, unable to comply! This is likely to be a bug, please report it!" );
[c2fb3809]396                imc_logout( ic, TRUE );
[b7d3cc34]397                return( 0 );
398        }
399        else if( strcmp( cmd[0], "USR" ) == 0 )
400        {
401                if( num_parts != 5 )
402                {
403                        msn_sb_destroy( sb );
404                        return( 0 );
405                }
406               
407                if( strcmp( cmd[2], "OK" ) != 0 )
408                {
409                        msn_sb_destroy( sb );
410                        return( 0 );
411                }
412               
413                if( sb->who )
414                {
415                        g_snprintf( buf, sizeof( buf ), "CAL %d %s\r\n", ++sb->trId, sb->who );
416                        return( msn_sb_write( sb, buf, strlen( buf ) ) );
417                }
418                else
419                {
420                        debug( "Just created a switchboard, but I don't know what to do with it." );
421                }
422        }
423        else if( strcmp( cmd[0], "IRO" ) == 0 )
424        {
425                int num, tot;
426               
427                if( num_parts != 6 )
428                {
429                        msn_sb_destroy( sb );
430                        return( 0 );
431                }
432               
433                num = atoi( cmd[2] );
434                tot = atoi( cmd[3] );
435               
436                if( tot <= 0 )
437                {
438                        msn_sb_destroy( sb );
439                        return( 0 );
440                }
441                else if( tot > 1 )
442                {
443                        char buf[1024];
444                       
445                        if( num == 1 )
446                        {
447                                g_snprintf( buf, sizeof( buf ), "MSN groupchat session %d", sb->session );
[61ae52c]448                                sb->chat = imcb_chat_new( ic, buf );
[b7d3cc34]449                               
450                                g_free( sb->who );
451                                sb->who = NULL;
452                        }
453                       
[61ae52c]454                        imcb_chat_add_buddy( sb->chat, cmd[4] );
[b7d3cc34]455                       
456                        if( num == tot )
457                        {
[61ae52c]458                                imcb_chat_add_buddy( sb->chat, ic->acc->user );
[b7d3cc34]459                        }
460                }
461        }
462        else if( strcmp( cmd[0], "ANS" ) == 0 )
463        {
464                if( num_parts != 3 )
465                {
466                        msn_sb_destroy( sb );
467                        return( 0 );
468                }
469               
470                if( strcmp( cmd[2], "OK" ) != 0 )
471                {
472                        debug( "Switchboard server sent a negative ANS reply" );
473                        msn_sb_destroy( sb );
474                        return( 0 );
475                }
476               
477                sb->ready = 1;
478        }
479        else if( strcmp( cmd[0], "CAL" ) == 0 )
480        {
481                if( num_parts != 4 || !isdigit( cmd[3][0] ) )
482                {
483                        msn_sb_destroy( sb );
484                        return( 0 );
485                }
486               
487                sb->session = atoi( cmd[3] );
488        }
489        else if( strcmp( cmd[0], "JOI" ) == 0 )
490        {
491                if( num_parts != 3 )
492                {
493                        msn_sb_destroy( sb );
494                        return( 0 );
495                }
496               
497                if( sb->who && g_strcasecmp( cmd[1], sb->who ) == 0 )
498                {
499                        /* The user we wanted to talk to is finally there, let's send the queued messages then. */
500                        struct msn_message *m;
501                        GSList *l;
502                        int st = 1;
503                       
504                        debug( "%s arrived in the switchboard session, now sending queued message(s)", cmd[1] );
505                       
506                        /* Without this, sendmessage() will put everything back on the queue... */
507                        sb->ready = 1;
508                       
509                        while( ( l = sb->msgq ) )
510                        {
511                                m = l->data;
512                                if( st )
513                                {
514                                        /* This hack is meant to convert a regular new chat into a groupchat */
515                                        if( strcmp( m->text, GROUPCHAT_SWITCHBOARD_MESSAGE ) == 0 )
516                                                msn_sb_to_chat( sb );
517                                        else
518                                                st = msn_sb_sendmessage( sb, m->text );
519                                }
520                                g_free( m->text );
521                                g_free( m->who );
522                                g_free( m );
523                               
524                                sb->msgq = g_slist_remove( sb->msgq, m );
525                        }
526                       
527                        return( st );
528                }
529                else if( sb->who )
530                {
531                        debug( "Converting chat with %s to a groupchat because %s joined the session.", sb->who, cmd[1] );
532                       
533                        /* This SB is a one-to-one chat right now, but someone else is joining. */
534                        msn_sb_to_chat( sb );
535                       
[61ae52c]536                        imcb_chat_add_buddy( sb->chat, cmd[1] );
[b7d3cc34]537                }
538                else if( sb->chat )
539                {
[61ae52c]540                        imcb_chat_add_buddy( sb->chat, cmd[1] );
[b7d3cc34]541                        sb->ready = 1;
542                }
543                else
544                {
545                        /* PANIC! */
546                }
547        }
548        else if( strcmp( cmd[0], "MSG" ) == 0 )
549        {
550                if( num_parts != 4 )
551                {
552                        msn_sb_destroy( sb );
553                        return( 0 );
554                }
555               
556                sb->handler->msglen = atoi( cmd[3] );
557               
558                if( sb->handler->msglen <= 0 )
559                {
560                        debug( "Received a corrupted message on the switchboard, the switchboard will be closed" );
561                        msn_sb_destroy( sb );
562                        return( 0 );
563                }
564        }
[3585c5a]565        else if( strcmp( cmd[0], "NAK" ) == 0 )
566        {
567                if( sb->who )
568                {
569                        imcb_log( ic, "The MSN servers could not deliver one of your messages to %s.", sb->who );
570                }
571                else
572                {
573                        imcb_log( ic, "The MSN servers could not deliver one of your groupchat messages to all participants." );
574                }
575        }
[b7d3cc34]576        else if( strcmp( cmd[0], "BYE" ) == 0 )
577        {
578                if( num_parts < 2 )
579                {
580                        msn_sb_destroy( sb );
581                        return( 0 );
582                }
583               
584                /* if( cmd[2] && *cmd[2] == '1' ) -=> Chat is being cleaned up because of idleness */
585               
586                if( sb->who )
587                {
588                        /* This is a single-person chat, and the other person is leaving. */
589                        g_free( sb->who );
590                        sb->who = NULL;
591                        sb->ready = 0;
592                       
593                        debug( "Person %s left the one-to-one switchboard connection. Keeping it around as a spare...", cmd[1] );
594                       
595                        /* We could clean up the switchboard now, but keeping it around
596                           as a spare for a next conversation sounds more sane to me.
597                           The server will clean it up when it's idle for too long. */
598                }
599                else if( sb->chat )
600                {
[61ae52c]601                        imcb_chat_remove_buddy( sb->chat, cmd[1], "" );
[b7d3cc34]602                }
603                else
604                {
605                        /* PANIC! */
606                }
607        }
608        else if( isdigit( cmd[0][0] ) )
609        {
610                int num = atoi( cmd[0] );
[08995b0]611                const struct msn_status_code *err = msn_status_by_number( num );
[b7d3cc34]612               
[84b045d]613                imcb_error( ic, "Error reported by switchboard server: %s", err->text );
[b7d3cc34]614               
615                if( err->flags & STATUS_SB_FATAL )
616                {
617                        msn_sb_destroy( sb );
[6048744]618                        return 0;
[b7d3cc34]619                }
[6048744]620                else if( err->flags & STATUS_FATAL )
[b7d3cc34]621                {
[c2fb3809]622                        imc_logout( ic, TRUE );
[6048744]623                        return 0;
[b7d3cc34]624                }
[6048744]625                else if( err->flags & STATUS_SB_IM_SPARE )
[3b9390b]626                {
627                        if( sb->who )
628                        {
629                                /* Apparently some invitation failed. We might want to use this
630                                   board later, so keep it as a spare. */
631                                g_free( sb->who );
632                                sb->who = NULL;
633                               
634                                /* Also clear the msgq, otherwise someone else might get them. */
[46dca11]635                                msn_msgq_purge( ic, &sb->msgq );
[3b9390b]636                        }
[6048744]637                       
638                        /* Do NOT return 0 here, we want to keep this sb. */
[3b9390b]639                }
[b7d3cc34]640        }
641        else
642        {
[8ff0a61]643                /* debug( "Received unknown command from switchboard server: %s", cmd[0] ); */
[b7d3cc34]644        }
645       
646        return( 1 );
647}
648
649static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts )
650{
651        struct msn_switchboard *sb = data;
[0da65d5]652        struct im_connection *ic = sb->ic;
[b7d3cc34]653        char *body;
654        int blen = 0;
655       
656        if( !num_parts )
657                return( 1 );
658       
659        if( ( body = strstr( msg, "\r\n\r\n" ) ) )
660        {
661                body += 4;
662                blen = msglen - ( body - msg );
663        }
664       
665        if( strcmp( cmd[0], "MSG" ) == 0 )
666        {
667                char *ct = msn_findheader( msg, "Content-Type:", msglen );
668               
669                if( !ct )
670                        return( 1 );
671               
672                if( g_strncasecmp( ct, "text/plain", 10 ) == 0 )
673                {
674                        g_free( ct );
675                       
676                        if( !body )
677                                return( 1 );
678                       
679                        if( sb->who )
680                        {
[9624fdf]681                                imcb_buddy_msg( ic, cmd[1], body, 0, 0 );
[b7d3cc34]682                        }
683                        else if( sb->chat )
684                        {
[61ae52c]685                                imcb_chat_msg( sb->chat, cmd[1], body, 0, 0 );
[b7d3cc34]686                        }
687                        else
688                        {
689                                /* PANIC! */
690                        }
691                }
692                else if( g_strncasecmp( ct, "text/x-msmsgsinvite", 19 ) == 0 )
693                {
694                        char *itype = msn_findheader( body, "Application-GUID:", blen );
695                        char buf[1024];
696                       
697                        g_free( ct );
698                       
699                        *buf = 0;
700                       
701                        if( !itype )
702                                return( 1 );
703                       
704                        /* File transfer. */
705                        if( strcmp( itype, "{5D3E02AB-6190-11d3-BBBB-00C04F795683}" ) == 0 )
706                        {
707                                char *name = msn_findheader( body, "Application-File:", blen );
708                                char *size = msn_findheader( body, "Application-FileSize:", blen );
709                               
710                                if( name && size )
711                                {
712                                        g_snprintf( buf, sizeof( buf ), "<< \x02""BitlBee\x02"" - Filetransfer: `%s', %s bytes >>\n"
713                                                    "Filetransfers are not supported by BitlBee for now...", name, size );
714                                }
715                                else
716                                {
717                                        strcpy( buf, "<< \x02""BitlBee\x02"" - Corrupted MSN filetransfer invitation message >>" );
718                                }
719                               
720                                if( name ) g_free( name );
721                                if( size ) g_free( size );
722                        }
723                        else
724                        {
725                                char *iname = msn_findheader( body, "Application-Name:", blen );
726                               
727                                g_snprintf( buf, sizeof( buf ), "<< \x02""BitlBee\x02"" - Unknown MSN invitation - %s (%s) >>",
728                                                                itype, iname ? iname : "no name" );
729                               
730                                if( iname ) g_free( iname );
731                        }
732                       
733                        g_free( itype );
734                       
735                        if( !*buf )
736                                return( 1 );
737                       
738                        if( sb->who )
739                        {
[9624fdf]740                                imcb_buddy_msg( ic, cmd[1], buf, 0, 0 );
[b7d3cc34]741                        }
742                        else if( sb->chat )
743                        {
[61ae52c]744                                imcb_chat_msg( sb->chat, cmd[1], buf, 0, 0 );
[b7d3cc34]745                        }
746                        else
747                        {
748                                /* PANIC! */
749                        }
750                }
751                else if( g_strncasecmp( ct, "text/x-msmsgscontrol", 20 ) == 0 )
752                {
753                        char *who = msn_findheader( msg, "TypingUser:", msglen );
754                       
755                        if( who )
756                        {
[9624fdf]757                                imcb_buddy_typing( ic, who, OPT_TYPING );
[b7d3cc34]758                                g_free( who );
759                        }
760                       
761                        g_free( ct );
762                }
763                else
764                {
765                        g_free( ct );
766                }
767        }
768       
769        return( 1 );
770}
[9bf2481]771
772gboolean msn_sb_keepalive( gpointer data, gint source, b_input_condition cond )
773{
774        struct msn_switchboard *sb = data;
775        return sb->ready && msn_sb_sendmessage( sb, SB_KEEPALIVE_MESSAGE );
776}
Note: See TracBrowser for help on using the repository browser.