source: util.c @ 2a6ca4f

Last change on this file since 2a6ca4f was 2a6ca4f, checked in by Wilmer van der Gaast <wilmer@…>, at 2006-01-04T11:16:58Z

Better handling of IPv4 connections in IPv6 mode. (Wrapping/Unwrapping of ::ffff:style addresses.)

  • Property mode set to 100644
File size: 8.6 KB
Line 
1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2004 Wilmer van der Gaast and others                *
5  \********************************************************************/
6
7/*
8 * Various utility functions. Some are copied from Gaim to support the
9 * IM-modules, most are from BitlBee.
10 *
11 * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
12 *                          (and possibly other members of the Gaim team)
13 * Copyright 2002-2005 Wilmer van der Gaast <wilmer@gaast.net>
14 */
15
16/*
17  This program is free software; you can redistribute it and/or modify
18  it under the terms of the GNU General Public License as published by
19  the Free Software Foundation; either version 2 of the License, or
20  (at your option) any later version.
21
22  This program is distributed in the hope that it will be useful,
23  but WITHOUT ANY WARRANTY; without even the implied warranty of
24  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  GNU General Public License for more details.
26
27  You should have received a copy of the GNU General Public License with
28  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
29  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
30  Suite 330, Boston, MA  02111-1307  USA
31*/
32
33#define BITLBEE_CORE
34#include "nogaim.h"
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <glib.h>
39#include <time.h>
40
41void strip_linefeed(gchar *text)
42{
43        int i, j;
44        gchar *text2 = g_malloc(strlen(text) + 1);
45
46        for (i = 0, j = 0; text[i]; i++)
47                if (text[i] != '\r')
48                        text2[j++] = text[i];
49        text2[j] = '\0';
50
51        strcpy(text, text2);
52        g_free(text2);
53}
54
55char *add_cr(char *text)
56{
57        char *ret = NULL;
58        int count = 0, j;
59        unsigned int i;
60
61        if (text[0] == '\n')
62                count++;
63        for (i = 1; i < strlen(text); i++)
64                if (text[i] == '\n' && text[i - 1] != '\r')
65                        count++;
66
67        if (count == 0)
68                return g_strdup(text);
69
70        ret = g_malloc0(strlen(text) + count + 1);
71
72        i = 0; j = 0;
73        if (text[i] == '\n')
74                ret[j++] = '\r';
75        ret[j++] = text[i++];
76        for (; i < strlen(text); i++) {
77                if (text[i] == '\n' && text[i - 1] != '\r')
78                        ret[j++] = '\r';
79                ret[j++] = text[i];
80        }
81
82        return ret;
83}
84
85static char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" "0123456789+/";
86
87/* XXX Find bug */
88char *tobase64(const char *text)
89{
90        char *out = NULL;
91        const char *c;
92        unsigned int tmp = 0;
93        int len = 0, n = 0;
94
95        c = text;
96
97        while (*c) {
98                tmp = tmp << 8;
99                tmp += *c;
100                n++;
101
102                if (n == 3) {
103                        out = g_realloc(out, len + 4);
104                        out[len] = alphabet[(tmp >> 18) & 0x3f];
105                        out[len + 1] = alphabet[(tmp >> 12) & 0x3f];
106                        out[len + 2] = alphabet[(tmp >> 6) & 0x3f];
107                        out[len + 3] = alphabet[tmp & 0x3f];
108                        len += 4;
109                        tmp = 0;
110                        n = 0;
111                }
112                c++;
113        }
114        switch (n) {
115
116        case 2:
117                tmp <<= 8;
118                out = g_realloc(out, len + 5);
119                out[len] = alphabet[(tmp >> 18) & 0x3f];
120                out[len + 1] = alphabet[(tmp >> 12) & 0x3f];
121                out[len + 2] = alphabet[(tmp >> 6) & 0x3f];
122                out[len + 3] = '=';
123                out[len + 4] = 0;
124                break;
125        case 1:
126                tmp <<= 16;
127                out = g_realloc(out, len + 5);
128                out[len] = alphabet[(tmp >> 18) & 0x3f];
129                out[len + 1] = alphabet[(tmp >> 12) & 0x3f];
130                out[len + 2] = '=';
131                out[len + 3] = '=';
132                out[len + 4] = 0;
133                break;
134        case 0:
135                out = g_realloc(out, len + 1);
136                out[len] = 0;
137                break;
138        }
139        return out;
140}
141
142char *normalize(const char *s)
143{
144        static char buf[BUF_LEN];
145        char *t, *u;
146        int x = 0;
147
148        g_return_val_if_fail((s != NULL), NULL);
149
150        u = t = g_strdup(s);
151
152        strcpy(t, s);
153        g_strdown(t);
154
155        while (*t && (x < BUF_LEN - 1)) {
156                if (*t != ' ') {
157                        buf[x] = *t;
158                        x++;
159                }
160                t++;
161        }
162        buf[x] = '\0';
163        g_free(u);
164        return buf;
165}
166
167time_t get_time(int year, int month, int day, int hour, int min, int sec)
168{
169        struct tm tm;
170
171        tm.tm_year = year - 1900;
172        tm.tm_mon = month - 1;
173        tm.tm_mday = day;
174        tm.tm_hour = hour;
175        tm.tm_min = min;
176        tm.tm_sec = sec >= 0 ? sec : time(NULL) % 60;
177        return mktime(&tm);
178}
179
180typedef struct htmlentity
181{
182        char code[8];
183        char is[4];
184} htmlentity_t;
185
186/* FIXME: This is ISO8859-1(5) centric, so might cause problems with other charsets. */
187
188static const htmlentity_t ent[] =
189{
190        { "lt",     "<" },
191        { "gt",     ">" },
192        { "amp",    "&" },
193        { "quot",   "\"" },
194        { "aacute", "á" },
195        { "eacute", "é" },
196        { "iacute", "é" },
197        { "oacute", "ó" },
198        { "uacute", "ú" },
199        { "agrave", "à" },
200        { "egrave", "è" },
201        { "igrave", "ì" },
202        { "ograve", "ò" },
203        { "ugrave", "ù" },
204        { "acirc",  "â" },
205        { "ecirc",  "ê" },
206        { "icirc",  "î" },
207        { "ocirc",  "ô" },
208        { "ucirc",  "û" },
209        { "auml",   "ä" },
210        { "euml",   "ë" },
211        { "iuml",   "ï" },
212        { "ouml",   "ö" },
213        { "uuml",   "ü" },
214        { "nbsp",   " " },
215        { "",        ""  }
216};
217
218void strip_html( char *in )
219{
220        char *start = in;
221        char *out = g_malloc( strlen( in ) + 1 );
222        char *s = out, *cs;
223        int i, matched;
224       
225        memset( out, 0, strlen( in ) + 1 );
226       
227        while( *in )
228        {
229                if( *in == '<' && ( isalpha( *(in+1) ) || *(in+1) == '/' ) )
230                {
231                        /* If in points at a < and in+1 points at a letter or a slash, this is probably
232                           a HTML-tag. Try to find a closing > and continue there. If the > can't be
233                           found, assume that it wasn't a HTML-tag after all. */
234                       
235                        cs = in;
236                       
237                        while( *in && *in != '>' )
238                                in ++;
239                       
240                        if( *in )
241                        {
242                                if( g_strncasecmp( cs+1, "br", 2) == 0 )
243                                        *(s++) = '\n';
244                                in ++;
245                        }
246                        else
247                        {
248                                in = cs;
249                                *(s++) = *(in++);
250                        }
251                }
252                else if( *in == '&' )
253                {
254                        cs = ++in;
255                        while( *in && isalpha( *in ) )
256                                in ++;
257                       
258                        if( *in == ';' ) in ++;
259                        matched = 0;
260                       
261                        for( i = 0; *ent[i].code; i ++ )
262                                if( g_strncasecmp( ent[i].code, cs, strlen( ent[i].code ) ) == 0 )
263                                {
264                                        int j;
265                                       
266                                        for( j = 0; ent[i].is[j]; j ++ )
267                                                *(s++) = ent[i].is[j];
268                                       
269                                        matched = 1;
270                                        break;
271                                }
272
273                        /* None of the entities were matched, so return the string */
274                        if( !matched )
275                        {
276                                in = cs - 1;
277                                *(s++) = *(in++);
278                        }
279                }
280                else
281                {
282                        *(s++) = *(in++);
283                }
284        }
285       
286        strcpy( start, out );
287        g_free( out );
288}
289
290char *escape_html( const char *html )
291{
292        const char *c = html;
293        GString *ret;
294        char *str;
295       
296        if( html == NULL )
297                return( NULL );
298       
299        ret = g_string_new( "" );
300       
301        while( *c )
302        {
303                switch( *c )
304                {
305                        case '&':
306                                ret = g_string_append( ret, "&amp;" );
307                                break;
308                        case '<':
309                                ret = g_string_append( ret, "&lt;" );
310                                break;
311                        case '>':
312                                ret = g_string_append( ret, "&gt;" );
313                                break;
314                        case '"':
315                                ret = g_string_append( ret, "&quot;" );
316                                break;
317                        default:
318                                ret = g_string_append_c( ret, *c );
319                }
320                c ++;
321        }
322       
323        str = ret->str;
324        g_string_free( ret, FALSE );
325        return( str );
326}
327
328void info_string_append(GString *str, char *newline, char *name, char *value)
329{
330        if( value && value[0] )
331                g_string_sprintfa( str, "%s%s: %s", newline, name, value );
332}
333
334/* Decode%20a%20file%20name                                             */
335void http_decode( char *s )
336{
337        char *t;
338        int i, j, k;
339       
340        t = g_new( char, strlen( s ) + 1 );
341       
342        for( i = j = 0; s[i]; i ++, j ++ )
343        {
344                if( s[i] == '%' )
345                {
346                        if( sscanf( s + i + 1, "%2x", &k ) )
347                        {
348                                t[j] = k;
349                                i += 2;
350                        }
351                        else
352                        {
353                                *t = 0;
354                                break;
355                        }
356                }
357                else
358                {
359                        t[j] = s[i];
360                }
361        }
362        t[j] = 0;
363       
364        strcpy( s, t );
365        g_free( t );
366}
367
368/* Warning: This one explodes the string. Worst-cases can make the string 3x its original size! */
369/* This fuction is safe, but make sure you call it safely as well! */
370void http_encode( char *s )
371{
372        char *t;
373        int i, j;
374       
375        t = g_strdup( s );
376       
377        for( i = j = 0; t[i]; i ++, j ++ )
378        {
379                if( t[i] <= ' ' || ((unsigned char *)t)[i] >= 128 || t[i] == '%' )
380                {
381                        sprintf( s + j, "%%%02X", ((unsigned char*)t)[i] );
382                        j += 2;
383                }
384                else
385                {
386                        s[j] = t[i];
387                }
388        }
389        s[j] = 0;
390       
391        g_free( t );
392}
393
394/* Strip newlines from a string. Modifies the string passed to it. */ 
395char *strip_newlines( char *source )
396{
397        int i; 
398
399        for( i = 0; source[i] != '\0'; i ++ )
400                if( source[i] == '\n' || source[i] == '\r' )
401                        source[i] = ' ';
402       
403        return source;
404}
405
406#ifdef IPV6
407/* Wrap an IPv4 address into IPv6 space. Not thread-safe... */
408char *ipv6_wrap( char *src )
409{
410        static char dst[64];
411        int i;
412       
413        for( i = 0; src[i]; i ++ )
414                if( ( src[i] < '0' || src[i] > '9' ) && src[i] != '.' )
415                        break;
416       
417        /* Hmm, it's not even an IP... */
418        if( src[i] )
419                return src;
420       
421        g_snprintf( dst, sizeof( dst ), "::ffff:%s", src );
422       
423        return dst;
424}
425
426/* Unwrap an IPv4 address into IPv6 space. Thread-safe, because it's very simple. :-) */
427char *ipv6_unwrap( char *src )
428{
429        int i;
430       
431        if( g_strncasecmp( src, "::ffff:", 7 ) != 0 )
432                return src;
433       
434        for( i = 7; src[i]; i ++ )
435                if( ( src[i] < '0' || src[i] > '9' ) && src[i] != '.' )
436                        break;
437       
438        /* Hmm, it's not even an IP... */
439        if( src[i] )
440                return src;
441       
442        return ( src + 7 );
443}
444#endif
Note: See TracBrowser for help on using the repository browser.