source: util.c @ c88999c

Last change on this file since c88999c was c88999c, checked in by Wilmer van der Gaast <wilmer@…>, at 2005-12-27T15:20:35Z

Forgot to actually move those functions in previous commit. And *argh*, don't commit things done for debugging!

  • Property mode set to 100644
File size: 9.1 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
41char *utf8_to_str(const char *in)
42{
43        int n = 0, i = 0;
44        int inlen;
45        char *result;
46
47        if (!in)
48                return NULL;
49
50        inlen = strlen(in);
51
52        result = g_malloc(inlen + 1);
53
54        while (n <= inlen - 1) {
55                long c = (long)in[n];
56                if (c < 0x80)
57                        result[i++] = (char)c;
58                else {
59                        if ((c & 0xC0) == 0xC0)
60                                result[i++] =
61                                    (char)(((c & 0x03) << 6) | (((unsigned char)in[++n]) & 0x3F));
62                        else if ((c & 0xE0) == 0xE0) {
63                                if (n + 2 <= inlen) {
64                                        result[i] =
65                                            (char)(((c & 0xF) << 4) | (((unsigned char)in[++n]) & 0x3F));
66                                        result[i] =
67                                            (char)(((unsigned char)result[i]) |
68                                                   (((unsigned char)in[++n]) & 0x3F));
69                                        i++;
70                                } else
71                                        n += 2;
72                        } else if ((c & 0xF0) == 0xF0)
73                                n += 3;
74                        else if ((c & 0xF8) == 0xF8)
75                                n += 4;
76                        else if ((c & 0xFC) == 0xFC)
77                                n += 5;
78                }
79                n++;
80        }
81        result[i] = '\0';
82
83        return result;
84}
85
86char *str_to_utf8(const char *in)
87{
88        int n = 0, i = 0;
89        int inlen;
90        char *result = NULL;
91
92        if (!in)
93                return NULL;
94
95        inlen = strlen(in);
96
97        result = g_malloc(inlen * 2 + 1);
98
99        while (n < inlen) {
100                long c = (long)in[n];
101                if (c == 27) {
102                        n += 2;
103                        if (in[n] == 'x')
104                                n++;
105                        if (in[n] == '3')
106                                n++;
107                        n += 2;
108                        continue;
109                }
110                /* why are we removing newlines and carriage returns?
111                if ((c == 0x0D) || (c == 0x0A)) {
112                        n++;
113                        continue;
114                }
115                */
116                if (c < 128)
117                        result[i++] = (char)c;
118                else {
119                        result[i++] = (char)((c >> 6) | 192);
120                        result[i++] = (char)((c & 63) | 128);
121                }
122                n++;
123        }
124        result[i] = '\0';
125
126        return result;
127}
128
129void strip_linefeed(gchar *text)
130{
131        int i, j;
132        gchar *text2 = g_malloc(strlen(text) + 1);
133
134        for (i = 0, j = 0; text[i]; i++)
135                if (text[i] != '\r')
136                        text2[j++] = text[i];
137        text2[j] = '\0';
138
139        strcpy(text, text2);
140        g_free(text2);
141}
142
143char *add_cr(char *text)
144{
145        char *ret = NULL;
146        int count = 0, j;
147        unsigned int i;
148
149        if (text[0] == '\n')
150                count++;
151        for (i = 1; i < strlen(text); i++)
152                if (text[i] == '\n' && text[i - 1] != '\r')
153                        count++;
154
155        if (count == 0)
156                return g_strdup(text);
157
158        ret = g_malloc0(strlen(text) + count + 1);
159
160        i = 0; j = 0;
161        if (text[i] == '\n')
162                ret[j++] = '\r';
163        ret[j++] = text[i++];
164        for (; i < strlen(text); i++) {
165                if (text[i] == '\n' && text[i - 1] != '\r')
166                        ret[j++] = '\r';
167                ret[j++] = text[i];
168        }
169
170        return ret;
171}
172
173static char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" "0123456789+/";
174
175/* XXX Find bug */
176char *tobase64(const char *text)
177{
178        char *out = NULL;
179        const char *c;
180        unsigned int tmp = 0;
181        int len = 0, n = 0;
182
183        c = text;
184
185        while (*c) {
186                tmp = tmp << 8;
187                tmp += *c;
188                n++;
189
190                if (n == 3) {
191                        out = g_realloc(out, len + 4);
192                        out[len] = alphabet[(tmp >> 18) & 0x3f];
193                        out[len + 1] = alphabet[(tmp >> 12) & 0x3f];
194                        out[len + 2] = alphabet[(tmp >> 6) & 0x3f];
195                        out[len + 3] = alphabet[tmp & 0x3f];
196                        len += 4;
197                        tmp = 0;
198                        n = 0;
199                }
200                c++;
201        }
202        switch (n) {
203
204        case 2:
205                tmp <<= 8;
206                out = g_realloc(out, len + 5);
207                out[len] = alphabet[(tmp >> 18) & 0x3f];
208                out[len + 1] = alphabet[(tmp >> 12) & 0x3f];
209                out[len + 2] = alphabet[(tmp >> 6) & 0x3f];
210                out[len + 3] = '=';
211                out[len + 4] = 0;
212                break;
213        case 1:
214                tmp <<= 16;
215                out = g_realloc(out, len + 5);
216                out[len] = alphabet[(tmp >> 18) & 0x3f];
217                out[len + 1] = alphabet[(tmp >> 12) & 0x3f];
218                out[len + 2] = '=';
219                out[len + 3] = '=';
220                out[len + 4] = 0;
221                break;
222        case 0:
223                out = g_realloc(out, len + 1);
224                out[len] = 0;
225                break;
226        }
227        return out;
228}
229
230char *normalize(const char *s)
231{
232        static char buf[BUF_LEN];
233        char *t, *u;
234        int x = 0;
235
236        g_return_val_if_fail((s != NULL), NULL);
237
238        u = t = g_strdup(s);
239
240        strcpy(t, s);
241        g_strdown(t);
242
243        while (*t && (x < BUF_LEN - 1)) {
244                if (*t != ' ') {
245                        buf[x] = *t;
246                        x++;
247                }
248                t++;
249        }
250        buf[x] = '\0';
251        g_free(u);
252        return buf;
253}
254
255time_t get_time(int year, int month, int day, int hour, int min, int sec)
256{
257        struct tm tm;
258
259        tm.tm_year = year - 1900;
260        tm.tm_mon = month - 1;
261        tm.tm_mday = day;
262        tm.tm_hour = hour;
263        tm.tm_min = min;
264        tm.tm_sec = sec >= 0 ? sec : time(NULL) % 60;
265        return mktime(&tm);
266}
267
268typedef struct htmlentity
269{
270        char code[8];
271        char is;
272} htmlentity_t;
273
274/* FIXME: This is ISO8859-1(5) centric, so might cause problems with other charsets. */
275
276static htmlentity_t ent[] =
277{
278        { "lt",     '<' },
279        { "gt",     '>' },
280        { "amp",    '&' },
281        { "quot",   '"' },
282        { "aacute", 'á' },
283        { "eacute", 'é' },
284        { "iacute", 'é' },
285        { "oacute", 'ó' },
286        { "uacute", 'ú' },
287        { "agrave", 'à' },
288        { "egrave", 'è' },
289        { "igrave", 'ì' },
290        { "ograve", 'ò' },
291        { "ugrave", 'ù' },
292        { "acirc",  'â' },
293        { "ecirc",  'ê' },
294        { "icirc",  'î' },
295        { "ocirc",  'ô' },
296        { "ucirc",  'û' },
297        { "nbsp",   ' ' },
298        { "",        0  }
299};
300
301void strip_html( char *in )
302{
303        char *start = in;
304        char *out = g_malloc( strlen( in ) + 1 );
305        char *s = out, *cs;
306        int i, matched;
307       
308        memset( out, 0, strlen( in ) + 1 );
309       
310        while( *in )
311        {
312                if( *in == '<' && ( isalpha( *(in+1) ) || *(in+1) == '/' ) )
313                {
314                        /* If in points at a < and in+1 points at a letter or a slash, this is probably
315                           a HTML-tag. Try to find a closing > and continue there. If the > can't be
316                           found, assume that it wasn't a HTML-tag after all. */
317                       
318                        cs = in;
319                       
320                        while( *in && *in != '>' )
321                                in ++;
322                       
323                        if( *in )
324                        {
325                                if( g_strncasecmp( cs+1, "br", 2) == 0 )
326                                        *(s++) = '\n';
327                                in ++;
328                        }
329                        else
330                        {
331                                in = cs;
332                                *(s++) = *(in++);
333                        }
334                }
335                else if( *in == '&' )
336                {
337                        cs = ++in;
338                        while( *in && isalpha( *in ) )
339                                in ++;
340                       
341                        if( *in == ';' ) in ++;
342                        matched = 0;
343                       
344                        for( i = 0; *ent[i].code; i ++ )
345                                if( g_strncasecmp( ent[i].code, cs, strlen( ent[i].code ) ) == 0 )
346                                {
347                                        *(s++) = ent[i].is;
348                                        matched = 1;
349                                        break;
350                                }
351
352                        /* None of the entities were matched, so return the string */
353                        if( !matched )
354                        {
355                                in = cs - 1;
356                                *(s++) = *(in++);
357                        }
358                }
359                else
360                {
361                        *(s++) = *(in++);
362                }
363        }
364       
365        strcpy( start, out );
366        g_free( out );
367}
368
369char *escape_html( const char *html )
370{
371        const char *c = html;
372        GString *ret;
373        char *str;
374       
375        if( html == NULL )
376                return( NULL );
377       
378        ret = g_string_new( "" );
379       
380        while( *c )
381        {
382                switch( *c )
383                {
384                        case '&':
385                                ret = g_string_append( ret, "&amp;" );
386                                break;
387                        case '<':
388                                ret = g_string_append( ret, "&lt;" );
389                                break;
390                        case '>':
391                                ret = g_string_append( ret, "&gt;" );
392                                break;
393                        case '"':
394                                ret = g_string_append( ret, "&quot;" );
395                                break;
396                        default:
397                                ret = g_string_append_c( ret, *c );
398                }
399                c ++;
400        }
401       
402        str = ret->str;
403        g_string_free( ret, FALSE );
404        return( str );
405}
406
407void info_string_append(GString *str, char *newline, char *name, char *value)
408{
409        if( value && value[0] )
410                g_string_sprintfa( str, "%s%s: %s", newline, name, value );
411}
412
413/* Decode%20a%20file%20name                                             */
414void http_decode( char *s )
415{
416        char *t;
417        int i, j, k;
418       
419        t = g_new( char, strlen( s ) + 1 );
420       
421        for( i = j = 0; s[i]; i ++, j ++ )
422        {
423                if( s[i] == '%' )
424                {
425                        if( sscanf( s + i + 1, "%2x", &k ) )
426                        {
427                                t[j] = k;
428                                i += 2;
429                        }
430                        else
431                        {
432                                *t = 0;
433                                break;
434                        }
435                }
436                else
437                {
438                        t[j] = s[i];
439                }
440        }
441        t[j] = 0;
442       
443        strcpy( s, t );
444        g_free( t );
445}
446
447/* Warning: This one explodes the string. Worst-cases can make the string 3x its original size! */
448/* This fuction is safe, but make sure you call it safely as well! */
449void http_encode( char *s )
450{
451        char *t;
452        int i, j;
453       
454        t = g_strdup( s );
455       
456        for( i = j = 0; t[i]; i ++, j ++ )
457        {
458                if( t[i] <= ' ' || ((unsigned char *)t)[i] >= 128 || t[i] == '%' )
459                {
460                        sprintf( s + j, "%%%02X", ((unsigned char*)t)[i] );
461                        j += 2;
462                }
463                else
464                {
465                        s[j] = t[i];
466                }
467        }
468        s[j] = 0;
469       
470        g_free( t );
471}
472
473/* Strip newlines from a string. Modifies the string passed to it. */ 
474char *strip_newlines( char *source )
475{
476        int i; 
477
478        for( i = 0; source[i] != '\0'; i ++ )
479                if( source[i] == '\n' || source[i] == '\r' )
480                        source[i] = ' ';
481       
482        return source;
483}
Note: See TracBrowser for help on using the repository browser.