source: protocols/msn/msn_util.c @ 2811940

Last change on this file since 2811940 was 2811940, checked in by Wilmer van der Gaast <wilmer@…>, at 2006-07-27T14:55:53Z

Copy-paste considered harmful + Fixed double handling of gc->permit/deny
which actually broke the block/allow commands.

  • Property mode set to 100644
File size: 7.7 KB
RevLine 
[b7d3cc34]1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2004 Wilmer van der Gaast and others                *
5  \********************************************************************/
6
7/* MSN module - Miscellaneous 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 "nogaim.h"
27#include "msn.h"
28#include <ctype.h>
29
30int msn_write( struct gaim_connection *gc, char *s, int len )
31{
32        struct msn_data *md = gc->proto_data;
33        int st;
34       
35        st = write( md->fd, s, len );
36        if( st != len )
37        {
38                hide_login_progress_error( gc, "Short write() to main server" );
39                signoff( gc );
40                return( 0 );
41        }
42       
43        return( 1 );
44}
45
46int msn_logged_in( struct gaim_connection *gc )
47{
48        account_online( gc );
49       
50        return( 0 );
51}
52
53int msn_buddy_list_add( struct gaim_connection *gc, char *list, char *who, char *realname_ )
54{
55        struct msn_data *md = gc->proto_data;
56        char buf[1024], *realname;
57       
58        realname = g_new0( char, strlen( realname_ ) * 3 + 1 );
59        strcpy( realname, realname_ );
60        http_encode( realname );
61       
62        g_snprintf( buf, sizeof( buf ), "ADD %d %s %s %s\r\n", ++md->trId, list, who, realname );
63        if( msn_write( gc, buf, strlen( buf ) ) )
64        {
65                g_free( realname );
66               
67                return( 1 );
68        }
69       
70        g_free( realname );
71       
72        return( 0 );
73}
74
75int msn_buddy_list_remove( struct gaim_connection *gc, char *list, char *who )
76{
77        struct msn_data *md = gc->proto_data;
78        char buf[1024];
79       
80        g_snprintf( buf, sizeof( buf ), "REM %d %s %s\r\n", ++md->trId, list, who );
81        if( msn_write( gc, buf, strlen( buf ) ) )
82                return( 1 );
83       
84        return( 0 );
85}
86
87struct msn_buddy_ask_data
88{
89        struct gaim_connection *gc;
90        char *handle;
91        char *realname;
92};
93
94static void msn_buddy_ask_yes( gpointer w, struct msn_buddy_ask_data *bla )
95{
96        msn_buddy_list_add( bla->gc, "AL", bla->handle, bla->realname );
97       
[e6d6047]98        if( find_buddy( bla->gc, bla->handle ) == NULL )
99                show_got_added( bla->gc, bla->handle, NULL );
100       
[b7d3cc34]101        g_free( bla->handle );
102        g_free( bla->realname );
103        g_free( bla );
104}
105
106static void msn_buddy_ask_no( gpointer w, struct msn_buddy_ask_data *bla )
107{
108        msn_buddy_list_add( bla->gc, "BL", bla->handle, bla->realname );
109       
110        g_free( bla->handle );
111        g_free( bla->realname );
112        g_free( bla );
113}
114
115void msn_buddy_ask( struct gaim_connection *gc, char *handle, char *realname )
116{
117        struct msn_buddy_ask_data *bla = g_new0( struct msn_buddy_ask_data, 1 );
118        char buf[1024];
119       
120        bla->gc = gc;
121        bla->handle = g_strdup( handle );
122        bla->realname = g_strdup( realname );
123       
124        g_snprintf( buf, sizeof( buf ),
[5c09a59]125                    "The user %s (%s) wants to add you to his/her buddy list.",
[b7d3cc34]126                    handle, realname );
127        do_ask_dialog( gc, buf, bla, msn_buddy_ask_yes, msn_buddy_ask_no );
128}
129
130char *msn_findheader( char *text, char *header, int len )
131{
132        int hlen = strlen( header ), i;
133        char *ret;
134       
135        if( len == 0 )
136                len = strlen( text );
137       
138        i = 0;
139        while( ( i + hlen ) < len )
140        {
141                /* Maybe this is a bit over-commented, but I just hate this part... */
142                if( g_strncasecmp( text + i, header, hlen ) == 0 )
143                {
144                        /* Skip to the (probable) end of the header */
145                        i += hlen;
146                       
147                        /* Find the first non-[: \t] character */
148                        while( i < len && ( text[i] == ':' || text[i] == ' ' || text[i] == '\t' ) ) i ++;
149                       
150                        /* Make sure we're still inside the string */
151                        if( i >= len ) return( NULL );
152                       
153                        /* Save the position */
154                        ret = text + i;
155                       
156                        /* Search for the end of this line */
157                        while( i < len && text[i] != '\r' && text[i] != '\n' ) i ++;
158                       
159                        /* Make sure we're still inside the string */
160                        if( i >= len ) return( NULL );
161                       
162                        /* Copy the found data */
163                        return( g_strndup( ret, text + i - ret ) );
164                }
165               
166                /* This wasn't the header we were looking for, skip to the next line. */
167                while( i < len && ( text[i] != '\r' && text[i] != '\n' ) ) i ++;
168                while( i < len && ( text[i] == '\r' || text[i] == '\n' ) ) i ++;
169               
170                /* End of headers? */
171                if( strncmp( text + i - 2, "\n\n", 2 ) == 0 ||
172                    strncmp( text + i - 4, "\r\n\r\n", 4 ) == 0 ||
173                    strncmp( text + i - 2, "\r\r", 2 ) == 0 )
174                {
175                        break;
176                }
177        }
178       
179        return( NULL );
180}
181
182/* *NOT* thread-safe, but that's not a problem for now... */
183char **msn_linesplit( char *line )
184{
185        static char **ret = NULL;
186        static int size = 3;
187        int i, n = 0;
188       
189        if( ret == NULL )
190                ret = g_new0( char*, size );
191       
192        for( i = 0; line[i] && line[i] == ' '; i ++ );
193        if( line[i] )
194        {
195                ret[n++] = line + i;
196                for( i ++; line[i]; i ++ )
197                {
198                        if( line[i] == ' ' )
199                                line[i] = 0;
200                        else if( line[i] != ' ' && !line[i-1] )
201                                ret[n++] = line + i;
202                       
203                        if( n >= size )
204                                ret = g_renew( char*, ret, size += 2 );
205                }
206        }
207        ret[n] = NULL;
208       
209        return( ret );
210}
211
212/* This one handles input from a MSN Messenger server. Both the NS and SB servers usually give
213   commands, but sometimes they give additional data (payload). This function tries to handle
214   this all in a nice way and send all data to the right places. */
215
216/* Return values: -1: Read error, abort connection.
217                   0: Command reported error; Abort *immediately*. (The connection does not exist anymore)
218                   1: OK */
219
220int msn_handler( struct msn_handler_data *h )
221{
222        int st;
223       
224        h->rxq = g_renew( char, h->rxq, h->rxlen + 1024 );
225        st = read( h->fd, h->rxq + h->rxlen, 1024 );
226        h->rxlen += st;
227       
228        if( st <= 0 )
229                return( -1 );
230       
231        while( st )
232        {
233                int i;
234               
235                if( h->msglen == 0 )
236                {
237                        for( i = 0; i < h->rxlen; i ++ )
238                        {
239                                if( h->rxq[i] == '\r' || h->rxq[i] == '\n' )
240                                {
241                                        char *cmd_text, **cmd;
242                                        int count;
243                                       
244                                        cmd_text = g_strndup( h->rxq, i );
245                                        cmd = msn_linesplit( cmd_text );
246                                        for( count = 0; cmd[count]; count ++ );
247                                        st = h->exec_command( h->data, cmd, count );
248                                        g_free( cmd_text );
249                                       
250                                        /* If the connection broke, don't continue. We don't even exist anymore. */
251                                        if( !st )
252                                                return( 0 );
253                                       
254                                        if( h->msglen )
255                                                h->cmd_text = g_strndup( h->rxq, i );
256                                       
257                                        /* Skip to the next non-emptyline */
258                                        while( i < h->rxlen && ( h->rxq[i] == '\r' || h->rxq[i] == '\n' ) ) i ++;
259                                       
260                                        break;
261                                }
262                        }
263                       
264                        /* If we reached the end of the buffer, there's still an incomplete command there.
265                           Return and wait for more data. */
266                        if( i == h->rxlen && h->rxq[i-1] != '\r' && h->rxq[i-1] != '\n' )
267                                break;
268                }
269                else
270                {
271                        char *msg, **cmd;
272                        int count;
273                       
274                        /* Do we have the complete message already? */
275                        if( h->msglen > h->rxlen )
276                                break;
277                       
278                        msg = g_strndup( h->rxq, h->msglen );
279                        cmd = msn_linesplit( h->cmd_text );
280                        for( count = 0; cmd[count]; count ++ );
281                       
282                        st = h->exec_message( h->data, msg, h->msglen, cmd, count );
283                        g_free( msg );
284                        g_free( h->cmd_text );
285                        h->cmd_text = NULL;
286                       
287                        if( !st )
288                                return( 0 );
289                       
290                        i = h->msglen;
291                        h->msglen = 0;
292                }
293               
294                /* More data after this block? */
295                if( i < h->rxlen )
296                {
297                        char *tmp;
298                       
299                        tmp = g_memdup( h->rxq + i, h->rxlen - i );
300                        g_free( h->rxq );
301                        h->rxq = tmp;
302                        h->rxlen -= i;
303                        i = 0;
304                }
305                else
306                /* If not, reset the rx queue and get lost. */
307                {
308                        g_free( h->rxq );
309                        h->rxq = g_new0( char, 1 );
310                        h->rxlen = 0;
311                        return( 1 );
312                }
313        }
314       
315        return( 1 );
316}
Note: See TracBrowser for help on using the repository browser.