Changeset 5ebff60 for lib


Ignore:
Timestamp:
2015-02-20T22:50:54Z (5 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:
lib
Files:
36 edited

Legend:

Unmodified
Added
Removed
  • lib/arc.c

    raf359b4 r5ebff60  
    2222\***************************************************************************/
    2323
    24 /* 
     24/*
    2525   This file implements ArcFour-encryption, which will mainly be used to
    2626   save IM passwords safely in the new XML-format. Possibly other uses will
     
    2929   way to crack BitlBee passwords now is to use a sniffer to get your hands
    3030   on the user's password.
    31    
     31
    3232   If you see that something's wrong in this implementation (I asked a
    3333   couple of people to look at it already, but who knows), please tell me.
    34    
     34
    3535   The reason I picked ArcFour is because it's pretty simple but effective,
    3636   so it will work without adding several KBs or an extra library dependency.
    37    
     37
    3838   (ArcFour is an RC4-compatible cipher. See for details:
    3939   http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt)
     
    5757#define ARC_CYCLES 1024
    5858
    59 struct arc_state *arc_keymaker( unsigned char *key, int kl, int cycles )
     59struct arc_state *arc_keymaker(unsigned char *key, int kl, int cycles)
    6060{
    6161        struct arc_state *st;
    6262        int i, j, tmp;
    6363        unsigned char S2[256];
    64        
    65         st = g_malloc( sizeof( struct arc_state ) );
     64
     65        st = g_malloc(sizeof(struct arc_state));
    6666        st->i = st->j = 0;
    67         if( kl <= 0 )
    68                 kl = strlen( (char*) key );
    69        
    70         for( i = 0; i < 256; i ++ )
    71         {
     67        if (kl <= 0) {
     68                kl = strlen((char *) key);
     69        }
     70
     71        for (i = 0; i < 256; i++) {
    7272                st->S[i] = i;
    73                 S2[i] = key[i%kl];
    74         }
    75        
    76         for( i = j = 0; i < 256; i ++ )
    77         {
    78                 j = ( j + st->S[i] + S2[i] ) & 0xff;
     73                S2[i] = key[i % kl];
     74        }
     75
     76        for (i = j = 0; i < 256; i++) {
     77                j = (j + st->S[i] + S2[i]) & 0xff;
    7978                tmp = st->S[i];
    8079                st->S[i] = st->S[j];
    8180                st->S[j] = tmp;
    8281        }
    83        
    84         memset( S2, 0, 256 );
     82
     83        memset(S2, 0, 256);
    8584        i = j = 0;
    86        
    87         for( i = 0; i < cycles; i ++ )
    88                 arc_getbyte( st );
    89        
     85
     86        for (i = 0; i < cycles; i++) {
     87                arc_getbyte(st);
     88        }
     89
    9090        return st;
    9191}
     
    9696   xor it with your cleartext. To decrypt, just give it the same key again
    9797   and start xorring.
    98    
     98
    9999   The function above initializes the byte generator, the next function can
    100100   be used to get bytes from the generator (and shuffle things a bit).
    101101*/
    102102
    103 unsigned char arc_getbyte( struct arc_state *st )
     103unsigned char arc_getbyte(struct arc_state *st)
    104104{
    105105        unsigned char tmp;
    106        
     106
    107107        /* Unfortunately the st-> stuff doesn't really improve readability here... */
    108         st->i ++;
     108        st->i++;
    109109        st->j += st->S[st->i];
    110110        tmp = st->S[st->i];
     
    112112        st->S[st->j] = tmp;
    113113        tmp = (st->S[st->i] + st->S[st->j]) & 0xff;
    114        
     114
    115115        return st->S[tmp];
    116116}
     
    122122   structures. These 6 bytes are also saved in the results, because of
    123123   course we'll need them in arc_decode().
    124    
     124
    125125   Because the length of the resulting string is unknown to the caller,
    126126   it should pass a char**. Since the encode/decode functions allocate
     
    129129   memory. And of course, don't forget to free() the result when you
    130130   don't need it anymore.
    131    
     131
    132132   Both functions return the number of bytes in the result string.
    133    
     133
    134134   Note that if you use the pad_to argument, you will need zero-termi-
    135135   nation to find back the original string length after decryption. So
     
    137137*/
    138138
    139 int arc_encode( char *clear, int clear_len, unsigned char **crypt, char *password, int pad_to )
     139int arc_encode(char *clear, int clear_len, unsigned char **crypt, char *password, int pad_to)
    140140{
    141141        struct arc_state *st;
     
    143143        char *padded = NULL;
    144144        int key_len, i, padded_len;
    145        
    146         key_len = strlen( password ) + ARC_IV_LEN;
    147         if( clear_len <= 0 )
    148                 clear_len = strlen( clear );
    149        
     145
     146        key_len = strlen(password) + ARC_IV_LEN;
     147        if (clear_len <= 0) {
     148                clear_len = strlen(clear);
     149        }
     150
    150151        /* Pad the string to the closest multiple of pad_to. This makes it
    151152           impossible to see the exact length of the password. */
    152         if( pad_to > 0 && ( clear_len % pad_to ) > 0 )
    153         {
    154                 padded_len = clear_len + pad_to - ( clear_len % pad_to );
    155                 padded = g_malloc( padded_len );
    156                 memcpy( padded, clear, clear_len );
    157                
     153        if (pad_to > 0 && (clear_len % pad_to) > 0) {
     154                padded_len = clear_len + pad_to - (clear_len % pad_to);
     155                padded = g_malloc(padded_len);
     156                memcpy(padded, clear, clear_len);
     157
    158158                /* First a \0 and then random data, so we don't have to do
    159159                   anything special when decrypting. */
    160160                padded[clear_len] = 0;
    161                 random_bytes( (unsigned char*) padded + clear_len + 1, padded_len - clear_len - 1 );
    162                
     161                random_bytes((unsigned char *) padded + clear_len + 1, padded_len - clear_len - 1);
     162
    163163                clear = padded;
    164164                clear_len = padded_len;
    165165        }
    166        
     166
    167167        /* Prepare buffers and the key + IV */
    168         *crypt = g_malloc( clear_len + ARC_IV_LEN );
    169         key = g_malloc( key_len );
    170         strcpy( (char*) key, password );
    171        
     168        *crypt = g_malloc(clear_len + ARC_IV_LEN);
     169        key = g_malloc(key_len);
     170        strcpy((char *) key, password);
     171
    172172        /* Add the salt. Save it for later (when decrypting) and, of course,
    173173           add it to the encryption key. */
    174         random_bytes( crypt[0], ARC_IV_LEN );
    175         memcpy( key + key_len - ARC_IV_LEN, crypt[0], ARC_IV_LEN );
    176        
     174        random_bytes(crypt[0], ARC_IV_LEN);
     175        memcpy(key + key_len - ARC_IV_LEN, crypt[0], ARC_IV_LEN);
     176
    177177        /* Generate the initial S[] from the IVed key. */
    178         st = arc_keymaker( key, key_len, ARC_CYCLES );
    179         g_free( key );
    180        
    181         for( i = 0; i < clear_len; i ++ )
    182                 crypt[0][i+ARC_IV_LEN] = clear[i] ^ arc_getbyte( st );
    183        
    184         g_free( st );
    185         g_free( padded );
    186        
     178        st = arc_keymaker(key, key_len, ARC_CYCLES);
     179        g_free(key);
     180
     181        for (i = 0; i < clear_len; i++) {
     182                crypt[0][i + ARC_IV_LEN] = clear[i] ^ arc_getbyte(st);
     183        }
     184
     185        g_free(st);
     186        g_free(padded);
     187
    187188        return clear_len + ARC_IV_LEN;
    188189}
    189190
    190 int arc_decode( unsigned char *crypt, int crypt_len, char **clear, const char *password )
     191int arc_decode(unsigned char *crypt, int crypt_len, char **clear, const char *password)
    191192{
    192193        struct arc_state *st;
    193194        unsigned char *key;
    194195        int key_len, clear_len, i;
    195        
    196         key_len = strlen( password ) + ARC_IV_LEN;
     196
     197        key_len = strlen(password) + ARC_IV_LEN;
    197198        clear_len = crypt_len - ARC_IV_LEN;
    198        
    199         if( clear_len < 0 )
    200         {
    201                 *clear = g_strdup( "" );
     199
     200        if (clear_len < 0) {
     201                *clear = g_strdup("");
    202202                return -1;
    203203        }
    204        
     204
    205205        /* Prepare buffers and the key + IV */
    206         *clear = g_malloc( clear_len + 1 );
    207         key = g_malloc( key_len );
    208         strcpy( (char*) key, password );
    209         for( i = 0; i < ARC_IV_LEN; i ++ )
    210                 key[key_len-ARC_IV_LEN+i] = crypt[i];
    211        
     206        *clear = g_malloc(clear_len + 1);
     207        key = g_malloc(key_len);
     208        strcpy((char *) key, password);
     209        for (i = 0; i < ARC_IV_LEN; i++) {
     210                key[key_len - ARC_IV_LEN + i] = crypt[i];
     211        }
     212
    212213        /* Generate the initial S[] from the IVed key. */
    213         st = arc_keymaker( key, key_len, ARC_CYCLES );
    214         g_free( key );
    215        
    216         for( i = 0; i < clear_len; i ++ )
    217                 clear[0][i] = crypt[i+ARC_IV_LEN] ^ arc_getbyte( st );
     214        st = arc_keymaker(key, key_len, ARC_CYCLES);
     215        g_free(key);
     216
     217        for (i = 0; i < clear_len; i++) {
     218                clear[0][i] = crypt[i + ARC_IV_LEN] ^ arc_getbyte(st);
     219        }
    218220        clear[0][i] = 0; /* Nice to have for plaintexts. */
    219        
    220         g_free( st );
    221        
     221
     222        g_free(st);
     223
    222224        return clear_len;
    223225}
  • lib/arc.h

    raf359b4 r5ebff60  
    2525/* See arc.c for more information. */
    2626
    27 struct arc_state
    28 {
     27struct arc_state {
    2928        unsigned char S[256];
    3029        unsigned char i, j;
     
    3534#endif
    3635
    37 G_GNUC_MALLOC struct arc_state *arc_keymaker( unsigned char *key, int kl, int cycles );
    38 unsigned char arc_getbyte( struct arc_state *st );
    39 int arc_encode( char *clear, int clear_len, unsigned char **crypt, char *password, int pad_to );
    40 int arc_decode( unsigned char *crypt, int crypt_len, char **clear, const char *password );
     36G_GNUC_MALLOC struct arc_state *arc_keymaker(unsigned char *key, int kl, int cycles);
     37unsigned char arc_getbyte(struct arc_state *st);
     38int arc_encode(char *clear, int clear_len, unsigned char **crypt, char *password, int pad_to);
     39int arc_decode(unsigned char *crypt, int crypt_len, char **clear, const char *password);
  • lib/base64.c

    raf359b4 r5ebff60  
    2929char *tobase64(const char *text)
    3030{
    31         return base64_encode((const unsigned char *)text, strlen(text));
     31        return base64_encode((const unsigned char *) text, strlen(text));
    3232}
    3333
     
    4242{
    4343        unsigned char *out;
     44
    4445        base64_decode(in, &out);
    45         return (char*) out;
     46        return (char *) out;
    4647}
    4748
     
    4950{
    5051        gsize len;
     52
    5153        *out = g_base64_decode(in, &len);
    5254
  • lib/base64.h

    raf359b4 r5ebff60  
    2626#include <gmodule.h>
    2727
    28 G_MODULE_EXPORT char *tobase64( const char *text );
    29 G_MODULE_EXPORT char *base64_encode( const unsigned char *in, int len );
    30 G_MODULE_EXPORT char *frombase64( const char *in );
    31 G_MODULE_EXPORT int base64_decode( const char *in, unsigned char **out );
     28G_MODULE_EXPORT char *tobase64(const char *text);
     29G_MODULE_EXPORT char *base64_encode(const unsigned char *in, int len);
     30G_MODULE_EXPORT char *frombase64(const char *in);
     31G_MODULE_EXPORT int base64_decode(const char *in, unsigned char **out);
  • lib/events.h

    raf359b4 r5ebff60  
    2626   This function (proxy_connect()) can be found in proxy.c. (It also
    2727   transparently handles HTTP/SOCKS proxies, when necessary.)
    28    
     28
    2929   This file offers some extra event handling toys, which will be handled
    3030   by GLib or libevent. The advantage of using libevent is that it can use
     
    4747typedef enum {
    4848        B_EV_IO_READ = 1 << 0,
    49         B_EV_IO_WRITE = 1 << 1,
    50         B_EV_FLAG_FORCE_ONCE = 1 << 16,
    51         B_EV_FLAG_FORCE_REPEAT = 1 << 17,
     49                B_EV_IO_WRITE = 1 << 1,
     50                B_EV_FLAG_FORCE_ONCE = 1 << 16,
     51                B_EV_FLAG_FORCE_REPEAT = 1 << 17,
    5252} b_input_condition;
    5353typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition cond);
     
    5959
    6060/* #define event_debug( x... ) printf( x ) */
    61 #define event_debug( x... )
     61#define event_debug(x ...)
    6262
    6363/* Call this once when the program starts. It'll initialize the event handler
  • lib/events_glib.c

    raf359b4 r5ebff60  
    1   /********************************************************************\
     1/********************************************************************\
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
     
    5050void b_main_init()
    5151{
    52         if( loop == NULL )
    53                 loop = g_main_new( FALSE );
     52        if (loop == NULL) {
     53                loop = g_main_new(FALSE);
     54        }
    5455}
    5556
    5657void b_main_run()
    5758{
    58         g_main_run( loop );
     59        g_main_run(loop);
    5960}
    6061
    6162void b_main_quit()
    6263{
    63         g_main_quit( loop );
     64        g_main_quit(loop);
    6465}
    6566
     
    6970        b_input_condition gaim_cond = 0;
    7071        gboolean st;
    71        
    72         if (condition & G_IO_NVAL)
     72
     73        if (condition & G_IO_NVAL) {
    7374                return FALSE;
     75        }
    7476
    75         if (condition & GAIM_READ_COND)
     77        if (condition & GAIM_READ_COND) {
    7678                gaim_cond |= B_EV_IO_READ;
    77         if (condition & GAIM_WRITE_COND)
     79        }
     80        if (condition & GAIM_WRITE_COND) {
    7881                gaim_cond |= B_EV_IO_WRITE;
    79        
    80         event_debug( "gaim_io_invoke( %d, %d, 0x%x )\n", g_io_channel_unix_get_fd(source), condition, data );
     82        }
     83
     84        event_debug("gaim_io_invoke( %d, %d, 0x%x )\n", g_io_channel_unix_get_fd(source), condition, data);
    8185
    8286        st = closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond);
    83        
    84         if( !st )
    85                 event_debug( "Returned FALSE, cancelling.\n" );
    86        
    87         if (closure->flags & B_EV_FLAG_FORCE_ONCE)
     87
     88        if (!st) {
     89                event_debug("Returned FALSE, cancelling.\n");
     90        }
     91
     92        if (closure->flags & B_EV_FLAG_FORCE_ONCE) {
    8893                return FALSE;
    89         else if (closure->flags & B_EV_FLAG_FORCE_REPEAT)
     94        } else if (closure->flags & B_EV_FLAG_FORCE_REPEAT) {
    9095                return TRUE;
    91         else
     96        } else {
    9297                return st;
     98        }
    9399}
    94100
    95101static void gaim_io_destroy(gpointer data)
    96102{
    97         event_debug( "gaim_io_destroy( 0x%x )\n", data );
     103        event_debug("gaim_io_destroy( 0x%x )\n", data);
    98104        g_free(data);
    99105}
     
    105111        GIOCondition cond = 0;
    106112        int st;
    107        
     113
    108114        closure->function = function;
    109115        closure->data = data;
    110116        closure->flags = condition;
    111        
    112         if (condition & B_EV_IO_READ)
     117
     118        if (condition & B_EV_IO_READ) {
    113119                cond |= GAIM_READ_COND;
    114         if (condition & B_EV_IO_WRITE)
     120        }
     121        if (condition & B_EV_IO_WRITE) {
    115122                cond |= GAIM_WRITE_COND;
    116        
     123        }
     124
    117125        channel = g_io_channel_unix_new(source);
    118126        st = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond,
    119127                                 gaim_io_invoke, closure, gaim_io_destroy);
    120        
    121         event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) = %d (%p)\n", source, condition, function, data, st, closure );
    122        
     128
     129        event_debug("b_input_add( %d, %d, 0x%x, 0x%x ) = %d (%p)\n", source, condition, function, data, st, closure);
     130
    123131        g_io_channel_unref(channel);
    124132        return st;
     
    131139           for now, BitlBee only looks at the "data" argument. */
    132140        gint st = g_timeout_add(timeout, (GSourceFunc) func, data);
    133        
    134         event_debug( "b_timeout_add( %d, %d, %d ) = %d\n", timeout, func, data, st );
    135        
     141
     142        event_debug("b_timeout_add( %d, %d, %d ) = %d\n", timeout, func, data, st);
     143
    136144        return st;
    137145}
     
    139147void b_event_remove(gint tag)
    140148{
    141         event_debug( "b_event_remove( %d )\n", tag );
    142        
    143         if (tag > 0)
     149        event_debug("b_event_remove( %d )\n", tag);
     150
     151        if (tag > 0) {
    144152                g_source_remove(tag);
     153        }
    145154}
    146155
    147 void closesocket( int fd )
     156void closesocket(int fd)
    148157{
    149         close( fd );
     158        close(fd);
    150159}
  • lib/events_libevent.c

    raf359b4 r5ebff60  
    1   /********************************************************************\
     1/********************************************************************\
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
     
    5353struct event_base *old_leh;
    5454
    55 struct b_event_data
    56 {
     55struct b_event_data {
    5756        guint id;
    5857        struct event evinfo;
     
    6564void b_main_init()
    6665{
    67         if( leh != NULL )
    68         {
     66        if (leh != NULL) {
    6967                /* Clean up the hash tables? */
    70                
     68
    7169                b_main_restart();
    7270                old_leh = leh;
    7371        }
    74        
     72
    7573        leh = event_init();
    76        
    77         id_hash = g_hash_table_new( g_int_hash, g_int_equal );
    78         read_hash = g_hash_table_new( g_int_hash, g_int_equal );
    79         write_hash = g_hash_table_new( g_int_hash, g_int_equal );
     74
     75        id_hash = g_hash_table_new(g_int_hash, g_int_equal);
     76        read_hash = g_hash_table_new(g_int_hash, g_int_equal);
     77        write_hash = g_hash_table_new(g_int_hash, g_int_equal);
    8078}
    8179
     
    8482        /* This while loop is necessary to exit the event loop and start a
    8583           different one (necessary for ForkDaemon mode). */
    86         while( event_base_dispatch( leh ) == 0 && !quitting )
    87         {
    88                 if( old_leh != NULL )
    89                 {
     84        while (event_base_dispatch(leh) == 0 && !quitting) {
     85                if (old_leh != NULL) {
    9086                        /* For some reason this just isn't allowed...
    9187                           Possibly a bug in older versions, will see later.
     
    9389                        old_leh = NULL;
    9490                }
    95                
    96                 event_debug( "New event loop.\n" );
     91
     92                event_debug("New event loop.\n");
    9793        }
    9894}
     
    10197{
    10298        struct timeval tv;
    103        
    104         memset( &tv, 0, sizeof( struct timeval ) );
    105         event_base_loopexit( leh, &tv );
    106        
    107         event_debug( "b_main_restart()\n" );
     99
     100        memset(&tv, 0, sizeof(struct timeval));
     101        event_base_loopexit(leh, &tv);
     102
     103        event_debug("b_main_restart()\n");
    108104}
    109105
     
    114110           we want to stop them. */
    115111        quitting = 1;
    116        
     112
    117113        b_main_restart();
    118114}
    119115
    120 static void b_event_passthrough( int fd, short event, void *data )
     116static void b_event_passthrough(int fd, short event, void *data)
    121117{
    122118        struct b_event_data *b_ev = data;
    123119        b_input_condition cond = 0;
    124120        gboolean st;
    125        
    126         if( fd >= 0 )
    127         {
    128                 if( event & EV_READ )
     121
     122        if (fd >= 0) {
     123                if (event & EV_READ) {
    129124                        cond |= B_EV_IO_READ;
    130                 if( event & EV_WRITE )
     125                }
     126                if (event & EV_WRITE) {
    131127                        cond |= B_EV_IO_WRITE;
    132         }
    133        
    134         event_debug( "b_event_passthrough( %d, %d, 0x%x ) (%d)\n", fd, event, (int) data, b_ev->id );
    135        
     128                }
     129        }
     130
     131        event_debug("b_event_passthrough( %d, %d, 0x%x ) (%d)\n", fd, event, (int) data, b_ev->id);
     132
    136133        /* Since the called function might cancel this handler already
    137134           (which free()s b_ev), we have to remember the ID here. */
    138135        id_cur = b_ev->id;
    139136        id_dead = 0;
    140        
    141         if( quitting )
    142         {
    143                 b_event_remove( id_cur );
     137
     138        if (quitting) {
     139                b_event_remove(id_cur);
    144140                return;
    145141        }
    146        
    147         st = b_ev->function( b_ev->data, fd, cond );
    148         if( id_dead )
    149         {
     142
     143        st = b_ev->function(b_ev->data, fd, cond);
     144        if (id_dead) {
    150145                /* This event was killed already, don't touch it! */
    151146                return;
    152         }
    153         else if( !st && !( b_ev->flags & B_EV_FLAG_FORCE_REPEAT ) )
    154         {
    155                 event_debug( "Handler returned FALSE: " );
    156                 b_event_remove( id_cur );
    157         }
    158         else if( fd == -1 )
    159         {
     147        } else if (!st && !(b_ev->flags & B_EV_FLAG_FORCE_REPEAT)) {
     148                event_debug("Handler returned FALSE: ");
     149                b_event_remove(id_cur);
     150        } else if (fd == -1) {
    160151                /* fd == -1 means it was a timer. These can't be auto-repeated
    161152                   so it has to be recreated every time. */
    162153                struct timeval tv;
    163                
     154
    164155                tv.tv_sec = b_ev->timeout / 1000;
    165                 tv.tv_usec = ( b_ev->timeout % 1000 ) * 1000;
    166                
    167                 evtimer_add( &b_ev->evinfo, &tv );
    168         }
    169 }
    170 
    171 gint b_input_add( gint fd, b_input_condition condition, b_event_handler function, gpointer data )
     156                tv.tv_usec = (b_ev->timeout % 1000) * 1000;
     157
     158                evtimer_add(&b_ev->evinfo, &tv);
     159        }
     160}
     161
     162gint b_input_add(gint fd, b_input_condition condition, b_event_handler function, gpointer data)
    172163{
    173164        struct b_event_data *b_ev;
    174        
    175         event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) ", fd, condition, function, data );
    176        
    177         if( ( condition & B_EV_IO_READ  && ( b_ev = g_hash_table_lookup( read_hash,  &fd ) ) ) ||
    178             ( condition & B_EV_IO_WRITE && ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) )
    179         {
     165
     166        event_debug("b_input_add( %d, %d, 0x%x, 0x%x ) ", fd, condition, function, data);
     167
     168        if ((condition & B_EV_IO_READ  && (b_ev = g_hash_table_lookup(read_hash,  &fd))) ||
     169            (condition & B_EV_IO_WRITE && (b_ev = g_hash_table_lookup(write_hash, &fd)))) {
    180170                /* We'll stick with this libevent entry, but give it a new BitlBee id. */
    181                 g_hash_table_remove( id_hash, &b_ev->id );
    182                
    183                 event_debug( "(replacing old handler (id = %d)) = %d\n", b_ev->id, id_next );
    184                
     171                g_hash_table_remove(id_hash, &b_ev->id);
     172
     173                event_debug("(replacing old handler (id = %d)) = %d\n", b_ev->id, id_next);
     174
    185175                b_ev->id = id_next++;
    186176                b_ev->function = function;
    187177                b_ev->data = data;
    188         }
    189         else
    190         {
     178        } else {
    191179                GIOCondition out_cond;
    192                
    193                 event_debug( "(new) = %d\n", id_next );
    194                
    195                 b_ev = g_new0( struct b_event_data, 1 );
     180
     181                event_debug("(new) = %d\n", id_next);
     182
     183                b_ev = g_new0(struct b_event_data, 1);
    196184                b_ev->id = id_next++;
    197185                b_ev->function = function;
    198186                b_ev->data = data;
    199                
     187
    200188                out_cond = EV_PERSIST;
    201                 if( condition & B_EV_IO_READ )
     189                if (condition & B_EV_IO_READ) {
    202190                        out_cond |= EV_READ;
    203                 if( condition & B_EV_IO_WRITE )
     191                }
     192                if (condition & B_EV_IO_WRITE) {
    204193                        out_cond |= EV_WRITE;
    205                
    206                 event_set( &b_ev->evinfo, fd, out_cond, b_event_passthrough, b_ev );
    207                 event_add( &b_ev->evinfo, NULL );
    208                
    209                 if( out_cond & EV_READ )
    210                         g_hash_table_insert( read_hash, &b_ev->evinfo.ev_fd, b_ev );
    211                 if( out_cond & EV_WRITE )
    212                         g_hash_table_insert( write_hash, &b_ev->evinfo.ev_fd, b_ev );
    213         }
    214        
     194                }
     195
     196                event_set(&b_ev->evinfo, fd, out_cond, b_event_passthrough, b_ev);
     197                event_add(&b_ev->evinfo, NULL);
     198
     199                if (out_cond & EV_READ) {
     200                        g_hash_table_insert(read_hash, &b_ev->evinfo.ev_fd, b_ev);
     201                }
     202                if (out_cond & EV_WRITE) {
     203                        g_hash_table_insert(write_hash, &b_ev->evinfo.ev_fd, b_ev);
     204                }
     205        }
     206
    215207        b_ev->flags = condition;
    216         g_hash_table_insert( id_hash, &b_ev->id, b_ev );
     208        g_hash_table_insert(id_hash, &b_ev->id, b_ev);
    217209        return b_ev->id;
    218210}
    219211
    220212/* TODO: Persistence for timers! */
    221 gint b_timeout_add( gint timeout, b_event_handler function, gpointer data )
    222 {
    223         struct b_event_data *b_ev = g_new0( struct b_event_data, 1 );
     213gint b_timeout_add(gint timeout, b_event_handler function, gpointer data)
     214{
     215        struct b_event_data *b_ev = g_new0(struct b_event_data, 1);
    224216        struct timeval tv;
    225        
     217
    226218        b_ev->id = id_next++;
    227219        b_ev->timeout = timeout;
    228220        b_ev->function = function;
    229221        b_ev->data = data;
    230        
     222
    231223        tv.tv_sec = timeout / 1000;
    232         tv.tv_usec = ( timeout % 1000 ) * 1000;
    233        
    234         evtimer_set( &b_ev->evinfo, b_event_passthrough, b_ev );
    235         evtimer_add( &b_ev->evinfo, &tv );
    236        
    237         event_debug( "b_timeout_add( %d, 0x%x, 0x%x ) = %d\n", timeout, function, data, b_ev->id );
    238        
    239         g_hash_table_insert( id_hash, &b_ev->id, b_ev );
    240        
     224        tv.tv_usec = (timeout % 1000) * 1000;
     225
     226        evtimer_set(&b_ev->evinfo, b_event_passthrough, b_ev);
     227        evtimer_add(&b_ev->evinfo, &tv);
     228
     229        event_debug("b_timeout_add( %d, 0x%x, 0x%x ) = %d\n", timeout, function, data, b_ev->id);
     230
     231        g_hash_table_insert(id_hash, &b_ev->id, b_ev);
     232
    241233        return b_ev->id;
    242234}
    243235
    244 void b_event_remove( gint id )
    245 {
    246         struct b_event_data *b_ev = g_hash_table_lookup( id_hash, &id );
    247        
    248         event_debug( "b_event_remove( %d )\n", id );
    249         if( b_ev )
    250         {
    251                 if( id == id_cur )
     236void b_event_remove(gint id)
     237{
     238        struct b_event_data *b_ev = g_hash_table_lookup(id_hash, &id);
     239
     240        event_debug("b_event_remove( %d )\n", id);
     241        if (b_ev) {
     242                if (id == id_cur) {
    252243                        id_dead = TRUE;
    253                
    254                 g_hash_table_remove( id_hash, &b_ev->id );
    255                 if( b_ev->evinfo.ev_fd >= 0 )
    256                 {
    257                         if( b_ev->evinfo.ev_events & EV_READ )
    258                                 g_hash_table_remove( read_hash, &b_ev->evinfo.ev_fd );
    259                         if( b_ev->evinfo.ev_events & EV_WRITE )
    260                                 g_hash_table_remove( write_hash, &b_ev->evinfo.ev_fd );
    261                 }
    262                
    263                 event_del( &b_ev->evinfo );
    264                 g_free( b_ev );
    265         }
    266         else
    267         {
    268                 event_debug( "Already removed?\n" );
    269         }
    270 }
    271 
    272 void closesocket( int fd )
     244                }
     245
     246                g_hash_table_remove(id_hash, &b_ev->id);
     247                if (b_ev->evinfo.ev_fd >= 0) {
     248                        if (b_ev->evinfo.ev_events & EV_READ) {
     249                                g_hash_table_remove(read_hash, &b_ev->evinfo.ev_fd);
     250                        }
     251                        if (b_ev->evinfo.ev_events & EV_WRITE) {
     252                                g_hash_table_remove(write_hash, &b_ev->evinfo.ev_fd);
     253                        }
     254                }
     255
     256                event_del(&b_ev->evinfo);
     257                g_free(b_ev);
     258        } else {
     259                event_debug("Already removed?\n");
     260        }
     261}
     262
     263void closesocket(int fd)
    273264{
    274265        struct b_event_data *b_ev;
    275        
     266
    276267        /* Since epoll() (the main reason we use libevent) automatically removes sockets from
    277268           the epoll() list when a socket gets closed and some modules have a habit of
     
    279270           get a little bit messed up. So this little function will remove the handlers
    280271           properly before closing a socket. */
    281        
    282         if( ( b_ev = g_hash_table_lookup( read_hash, &fd ) ) )
    283         {
    284                 event_debug( "Warning: fd %d still had a read event handler when shutting down.\n", fd );
    285                 b_event_remove( b_ev->id );
    286         }
    287         if( ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) )
    288         {
    289                 event_debug( "Warning: fd %d still had a write event handler when shutting down.\n", fd );
    290                 b_event_remove( b_ev->id );
    291         }
    292        
    293         close( fd );
    294 }
     272
     273        if ((b_ev = g_hash_table_lookup(read_hash, &fd))) {
     274                event_debug("Warning: fd %d still had a read event handler when shutting down.\n", fd);
     275                b_event_remove(b_ev->id);
     276        }
     277        if ((b_ev = g_hash_table_lookup(write_hash, &fd))) {
     278                event_debug("Warning: fd %d still had a write event handler when shutting down.\n", fd);
     279                b_event_remove(b_ev->id);
     280        }
     281
     282        close(fd);
     283}
  • lib/ftutil.c

    raf359b4 r5ebff60  
    2929
    3030#define ASSERTSOCKOP(op, msg) \
    31         if( (op) == -1 ) {\
    32                 g_snprintf( errmsg, sizeof( errmsg ), msg ": %s", strerror( errno ) ); \
     31        if ((op) == -1) { \
     32                g_snprintf(errmsg, sizeof(errmsg), msg ": %s", strerror(errno)); \
    3333                return -1; }
    3434
     
    3636 * Creates a listening socket and returns it in saddr_ptr.
    3737 */
    38 int ft_listen( struct sockaddr_storage *saddr_ptr, char *host, char *port, int copy_fd, int for_bitlbee_client, char **errptr )
     38int ft_listen(struct sockaddr_storage *saddr_ptr, char *host, char *port, int copy_fd, int for_bitlbee_client,
     39              char **errptr)
    3940{
    4041        int fd, gret, saddrlen;
    4142        struct addrinfo hints, *rp;
    42         socklen_t ssize = sizeof( struct sockaddr_storage );
     43        socklen_t ssize = sizeof(struct sockaddr_storage);
    4344        struct sockaddr_storage saddrs, *saddr = &saddrs;
    4445        static char errmsg[1024];
    4546        char *ftlisten = global.conf->ft_listen;
    4647
    47         if( errptr )
     48        if (errptr) {
    4849                *errptr = errmsg;
     50        }
    4951
    50         strcpy( port, "0" );
     52        strcpy(port, "0");
    5153
    5254        /* Format is <IP-A>[:<Port-A>];<IP-B>[:<Port-B>] where
     
    5456         * and B is for connections with IM peers.
    5557         */
    56         if( ftlisten )
    57         {
    58                 char *scolon = strchr( ftlisten, ';' );
     58        if (ftlisten) {
     59                char *scolon = strchr(ftlisten, ';');
    5960                char *colon;
    6061
    61                 if( scolon )
    62                 {
    63                         if( for_bitlbee_client )
    64                         {
     62                if (scolon) {
     63                        if (for_bitlbee_client) {
    6564                                *scolon = '\0';
    66                                 strncpy( host, ftlisten, HOST_NAME_MAX );
     65                                strncpy(host, ftlisten, HOST_NAME_MAX);
    6766                                *scolon = ';';
     67                        } else {
     68                                strncpy(host, scolon + 1, HOST_NAME_MAX);
    6869                        }
    69                         else
    70                         {
    71                                 strncpy( host, scolon + 1, HOST_NAME_MAX );
    72                         }
    73                 }
    74                 else
    75                 {
    76                         strncpy( host, ftlisten, HOST_NAME_MAX );
     70                } else {
     71                        strncpy(host, ftlisten, HOST_NAME_MAX);
    7772                }
    7873
    79                 if( ( colon = strchr( host, ':' ) ) )
    80                 {
     74                if ((colon = strchr(host, ':'))) {
    8175                        *colon = '\0';
    82                         strncpy( port, colon + 1, 5 );
     76                        strncpy(port, colon + 1, 5);
    8377                }
    84         }
    85         else if( copy_fd >= 0 && getsockname( copy_fd, (struct sockaddr*) &saddrs, &ssize ) == 0 &&
    86                  ( saddrs.ss_family == AF_INET || saddrs.ss_family == AF_INET6 ) &&
    87                  getnameinfo( (struct sockaddr*) &saddrs, ssize, host, HOST_NAME_MAX,
    88                               NULL, 0, NI_NUMERICHOST ) == 0 )
    89         {
     78        } else if (copy_fd >= 0 && getsockname(copy_fd, (struct sockaddr*) &saddrs, &ssize) == 0 &&
     79                   (saddrs.ss_family == AF_INET || saddrs.ss_family == AF_INET6) &&
     80                   getnameinfo((struct sockaddr*) &saddrs, ssize, host, HOST_NAME_MAX,
     81                               NULL, 0, NI_NUMERICHOST) == 0) {
    9082                /* We just took our local address on copy_fd, which is likely to be a
    9183                   sensible address from which we can do a file transfer now - the
    9284                   most sensible we can get easily. */
    93         }
    94         else
    95         {
    96                 ASSERTSOCKOP( gethostname( host, HOST_NAME_MAX + 1 ), "gethostname()" );
     85        } else {
     86                ASSERTSOCKOP(gethostname(host, HOST_NAME_MAX + 1), "gethostname()");
    9787        }
    9888
    99         memset( &hints, 0, sizeof( struct addrinfo ) );
     89        memset(&hints, 0, sizeof(struct addrinfo));
    10090        hints.ai_socktype = SOCK_STREAM;
    10191        hints.ai_flags = AI_NUMERICSERV;
    10292
    103         if ( ( gret = getaddrinfo( host, port, &hints, &rp ) ) != 0 )
    104         {
    105                 sprintf( errmsg, "getaddrinfo() failed: %s", gai_strerror( gret ) );
     93        if ((gret = getaddrinfo(host, port, &hints, &rp)) != 0) {
     94                sprintf(errmsg, "getaddrinfo() failed: %s", gai_strerror(gret));
    10695                return -1;
    10796        }
     
    10998        saddrlen = rp->ai_addrlen;
    11099
    111         memcpy( saddr, rp->ai_addr, saddrlen );
     100        memcpy(saddr, rp->ai_addr, saddrlen);
    112101
    113         freeaddrinfo( rp );
     102        freeaddrinfo(rp);
    114103
    115         ASSERTSOCKOP( fd = socket( saddr->ss_family, SOCK_STREAM, 0 ), "Opening socket" );
    116         ASSERTSOCKOP( bind( fd, ( struct sockaddr *)saddr, saddrlen ), "Binding socket" );
    117         ASSERTSOCKOP( listen( fd, 1 ), "Making socket listen" );
     104        ASSERTSOCKOP(fd = socket(saddr->ss_family, SOCK_STREAM, 0), "Opening socket");
     105        ASSERTSOCKOP(bind(fd, ( struct sockaddr *) saddr, saddrlen), "Binding socket");
     106        ASSERTSOCKOP(listen(fd, 1), "Making socket listen");
    118107
    119         if ( !inet_ntop( saddr->ss_family, saddr->ss_family == AF_INET ?
    120                         ( void * )&( ( struct sockaddr_in * ) saddr )->sin_addr.s_addr :
    121                         ( void * )&( ( struct sockaddr_in6 * ) saddr )->sin6_addr.s6_addr,
    122                         host, HOST_NAME_MAX ) )
    123         {
    124                 strcpy( errmsg, "inet_ntop failed on listening socket" );
     108        if (!inet_ntop(saddr->ss_family, saddr->ss_family == AF_INET ?
     109                       ( void * ) &(( struct sockaddr_in * ) saddr)->sin_addr.s_addr :
     110                       ( void * ) &(( struct sockaddr_in6 * ) saddr)->sin6_addr.s6_addr,
     111                       host, HOST_NAME_MAX)) {
     112                strcpy(errmsg, "inet_ntop failed on listening socket");
    125113                return -1;
    126114        }
    127115
    128         ssize = sizeof( struct sockaddr_storage );
    129         ASSERTSOCKOP( getsockname( fd, ( struct sockaddr *)saddr, &ssize ), "Getting socket name" );
     116        ssize = sizeof(struct sockaddr_storage);
     117        ASSERTSOCKOP(getsockname(fd, ( struct sockaddr *) saddr, &ssize), "Getting socket name");
    130118
    131         if( saddr->ss_family == AF_INET )
    132                 g_snprintf( port, 6, "%d", ntohs( ( (struct sockaddr_in *) saddr )->sin_port ) );
    133         else
    134                 g_snprintf( port, 6, "%d", ntohs( ( (struct sockaddr_in6 *) saddr )->sin6_port ) );
     119        if (saddr->ss_family == AF_INET) {
     120                g_snprintf(port, 6, "%d", ntohs(((struct sockaddr_in *) saddr)->sin_port));
     121        } else {
     122                g_snprintf(port, 6, "%d", ntohs(((struct sockaddr_in6 *) saddr)->sin6_port));
     123        }
    135124
    136         if( saddr_ptr )
    137                 memcpy( saddr_ptr, saddr, saddrlen );
     125        if (saddr_ptr) {
     126                memcpy(saddr_ptr, saddr, saddrlen);
     127        }
    138128
    139129        /* I hate static-length strings.. */
    140         host[HOST_NAME_MAX-1] = '\0';
     130        host[HOST_NAME_MAX - 1] = '\0';
    141131        port[5] = '\0';
    142        
     132
    143133        return fd;
    144134}
  • lib/ftutil.h

    raf359b4 r5ebff60  
    3838/* This function should be used with care. host should be AT LEAST a
    3939   char[HOST_NAME_MAX+1] and port AT LEAST a char[6]. */
    40 int ft_listen( struct sockaddr_storage *saddr_ptr, char *host, char *port, int copy_fd, int for_bitlbee_client, char **errptr );
     40int ft_listen(struct sockaddr_storage *saddr_ptr, char *host, char *port, int copy_fd, int for_bitlbee_client,
     41              char **errptr);
  • lib/http_client.c

    raf359b4 r5ebff60  
    1   /********************************************************************\
     1/********************************************************************\
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
     
    3232
    3333
    34 static gboolean http_connected( gpointer data, int source, b_input_condition cond );
    35 static gboolean http_ssl_connected( gpointer data, int returncode, void *source, b_input_condition cond );
    36 static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond );
    37 static void http_free( struct http_request *req );
    38 
    39 
    40 struct http_request *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data )
     34static gboolean http_connected(gpointer data, int source, b_input_condition cond);
     35static gboolean http_ssl_connected(gpointer data, int returncode, void *source, b_input_condition cond);
     36static gboolean http_incoming_data(gpointer data, int source, b_input_condition cond);
     37static void http_free(struct http_request *req);
     38
     39
     40struct http_request *http_dorequest(char *host, int port, int ssl, char *request, http_input_function func,
     41                                    gpointer data)
    4142{
    4243        struct http_request *req;
    4344        int error = 0;
    44        
    45         req = g_new0( struct http_request, 1 );
    46        
    47         if( ssl )
    48         {
    49                 req->ssl = ssl_connect( host, port, TRUE, http_ssl_connected, req );
    50                 if( req->ssl == NULL )
     45
     46        req = g_new0(struct http_request, 1);
     47
     48        if (ssl) {
     49                req->ssl = ssl_connect(host, port, TRUE, http_ssl_connected, req);
     50                if (req->ssl == NULL) {
    5151                        error = 1;
    52         }
    53         else
    54         {
    55                 req->fd = proxy_connect( host, port, http_connected, req );
    56                 if( req->fd < 0 )
     52                }
     53        } else {
     54                req->fd = proxy_connect(host, port, http_connected, req);
     55                if (req->fd < 0) {
    5756                        error = 1;
    58         }
    59        
    60         if( error )
    61         {
    62                 http_free( req );
     57                }
     58        }
     59
     60        if (error) {
     61                http_free(req);
    6362                return NULL;
    6463        }
    65        
     64
    6665        req->func = func;
    6766        req->data = data;
    68         req->request = g_strdup( request );
    69         req->request_length = strlen( request );
     67        req->request = g_strdup(request);
     68        req->request_length = strlen(request);
    7069        req->redir_ttl = 3;
    7170        req->content_length = -1;
    72        
    73         if( getenv( "BITLBEE_DEBUG" ) )
    74                 printf( "About to send HTTP request:\n%s\n", req->request );
    75        
     71
     72        if (getenv("BITLBEE_DEBUG")) {
     73                printf("About to send HTTP request:\n%s\n", req->request);
     74        }
     75
    7676        return req;
    7777}
    7878
    79 struct http_request *http_dorequest_url( char *url_string, http_input_function func, gpointer data )
    80 {
    81         url_t *url = g_new0( url_t, 1 );
     79struct http_request *http_dorequest_url(char *url_string, http_input_function func, gpointer data)
     80{
     81        url_t *url = g_new0(url_t, 1);
    8282        char *request;
    8383        void *ret;
    84        
    85         if( !url_set( url, url_string ) )
    86         {
    87                 g_free( url );
     84
     85        if (!url_set(url, url_string)) {
     86                g_free(url);
    8887                return NULL;
    8988        }
    90        
    91         if( url->proto != PROTO_HTTP && url->proto != PROTO_HTTPS )
    92         {
    93                 g_free( url );
     89
     90        if (url->proto != PROTO_HTTP && url->proto != PROTO_HTTPS) {
     91                g_free(url);
    9492                return NULL;
    9593        }
    96        
    97         request = g_strdup_printf( "GET %s HTTP/1.0\r\n"
    98                                    "Host: %s\r\n"
    99                                    "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n"
    100                                    "\r\n", url->file, url->host );
    101        
    102         ret = http_dorequest( url->host, url->port,
    103                               url->proto == PROTO_HTTPS, request, func, data );
    104        
    105         g_free( url );
    106         g_free( request );
     94
     95        request = g_strdup_printf("GET %s HTTP/1.0\r\n"
     96                                  "Host: %s\r\n"
     97                                  "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n"
     98                                  "\r\n", url->file, url->host);
     99
     100        ret = http_dorequest(url->host, url->port,
     101                             url->proto == PROTO_HTTPS, request, func, data);
     102
     103        g_free(url);
     104        g_free(request);
    107105        return ret;
    108106}
    109107
    110 /* This one is actually pretty simple... Might get more calls if we can't write 
     108/* This one is actually pretty simple... Might get more calls if we can't write
    111109   the whole request at once. */
    112 static gboolean http_connected( gpointer data, int source, b_input_condition cond )
     110static gboolean http_connected(gpointer data, int source, b_input_condition cond)
    113111{
    114112        struct http_request *req = data;
    115113        int st;
    116        
    117         if( source < 0 )
     114
     115        if (source < 0) {
    118116                goto error;
    119        
    120         if( req->inpa > 0 )
    121                 b_event_remove( req->inpa );
    122        
    123         sock_make_nonblocking( req->fd );
    124        
    125         if( req->ssl )
    126         {
    127                 st = ssl_write( req->ssl, req->request + req->bytes_written,
    128                                 req->request_length - req->bytes_written );
    129                 if( st < 0 )
    130                 {
    131                         if( ssl_errno != SSL_AGAIN )
    132                         {
    133                                 ssl_disconnect( req->ssl );
     117        }
     118
     119        if (req->inpa > 0) {
     120                b_event_remove(req->inpa);
     121        }
     122
     123        sock_make_nonblocking(req->fd);
     124
     125        if (req->ssl) {
     126                st = ssl_write(req->ssl, req->request + req->bytes_written,
     127                               req->request_length - req->bytes_written);
     128                if (st < 0) {
     129                        if (ssl_errno != SSL_AGAIN) {
     130                                ssl_disconnect(req->ssl);
    134131                                goto error;
    135132                        }
    136133                }
    137         }
    138         else
    139         {
    140                 st = write( source, req->request + req->bytes_written,
    141                                     req->request_length - req->bytes_written );
    142                 if( st < 0 )
    143                 {
    144                         if( !sockerr_again() )
    145                         {
    146                                 closesocket( req->fd );
     134        } else {
     135                st = write(source, req->request + req->bytes_written,
     136                           req->request_length - req->bytes_written);
     137                if (st < 0) {
     138                        if (!sockerr_again()) {
     139                                closesocket(req->fd);
    147140                                goto error;
    148141                        }
    149142                }
    150143        }
    151        
    152         if( st > 0 )
     144
     145        if (st > 0) {
    153146                req->bytes_written += st;
    154        
    155         if( req->bytes_written < req->request_length )
    156                 req->inpa = b_input_add( source,
    157                                          req->ssl ? ssl_getdirection( req->ssl ) : B_EV_IO_WRITE,
    158                                          http_connected, req );
    159         else
    160                 req->inpa = b_input_add( source, B_EV_IO_READ, http_incoming_data, req );
    161        
     147        }
     148
     149        if (req->bytes_written < req->request_length) {
     150                req->inpa = b_input_add(source,
     151                                        req->ssl ? ssl_getdirection(req->ssl) : B_EV_IO_WRITE,
     152                                        http_connected, req);
     153        } else {
     154                req->inpa = b_input_add(source, B_EV_IO_READ, http_incoming_data, req);
     155        }
     156
    162157        return FALSE;
    163        
     158
    164159error:
    165         if( req->status_string == NULL )
    166                 req->status_string = g_strdup( "Error while writing HTTP request" );
    167        
    168         req->func( req );
    169         http_free( req );
     160        if (req->status_string == NULL) {
     161                req->status_string = g_strdup("Error while writing HTTP request");
     162        }
     163
     164        req->func(req);
     165        http_free(req);
    170166        return FALSE;
    171167}
    172168
    173 static gboolean http_ssl_connected( gpointer data, int returncode, void *source, b_input_condition cond )
     169static gboolean http_ssl_connected(gpointer data, int returncode, void *source, b_input_condition cond)
    174170{
    175171        struct http_request *req = data;
    176        
    177         if( source == NULL )
    178         {
    179                 if( returncode != 0 )
    180                 {
    181                         char *err = ssl_verify_strerror( returncode );
     172
     173        if (source == NULL) {
     174                if (returncode != 0) {
     175                        char *err = ssl_verify_strerror(returncode);
    182176                        req->status_string = g_strdup_printf(
    183                                 "Certificate verification problem 0x%x: %s",
    184                                 returncode, err ? err : "Unknown" );
    185                         g_free( err );
    186                 }
    187                 return http_connected( data, -1, cond );
    188         }
    189        
    190         req->fd = ssl_getfd( source );
    191        
    192         return http_connected( data, req->fd, cond );
     177                                "Certificate verification problem 0x%x: %s",
     178                                returncode, err ? err : "Unknown");
     179                        g_free(err);
     180                }
     181                return http_connected(data, -1, cond);
     182        }
     183
     184        req->fd = ssl_getfd(source);
     185
     186        return http_connected(data, req->fd, cond);
    193187}
    194188
     
    200194} http_ret_t;
    201195
    202 static gboolean http_handle_headers( struct http_request *req );
    203 static http_ret_t http_process_chunked_data( struct http_request *req, const char *buffer, int len );
    204 static http_ret_t http_process_data( struct http_request *req, const char *buffer, int len );
    205 
    206 static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond )
     196static gboolean http_handle_headers(struct http_request *req);
     197static http_ret_t http_process_chunked_data(struct http_request *req, const char *buffer, int len);
     198static http_ret_t http_process_data(struct http_request *req, const char *buffer, int len);
     199
     200static gboolean http_incoming_data(gpointer data, int source, b_input_condition cond)
    207201{
    208202        struct http_request *req = data;
    209203        char buffer[4096];
    210204        int st;
    211        
    212         if( req->inpa > 0 )
    213         {
    214                 b_event_remove( req->inpa );
     205
     206        if (req->inpa > 0) {
     207                b_event_remove(req->inpa);
    215208                req->inpa = 0;
    216209        }
    217        
    218         if( req->ssl )
    219         {
    220                 st = ssl_read( req->ssl, buffer, sizeof( buffer ) );
    221                 if( st < 0 )
    222                 {
    223                         if( ssl_errno != SSL_AGAIN )
    224                         {
     210
     211        if (req->ssl) {
     212                st = ssl_read(req->ssl, buffer, sizeof(buffer));
     213                if (st < 0) {
     214                        if (ssl_errno != SSL_AGAIN) {
    225215                                /* goto cleanup; */
    226                                
     216
    227217                                /* YAY! We have to deal with crappy Microsoft
    228218                                   servers that LOVE to send invalid TLS
    229219                                   packets that abort connections! \o/ */
    230                                
     220
    231221                                goto eof;
    232222                        }
    233                 }
    234                 else if( st == 0 )
    235                 {
     223                } else if (st == 0) {
    236224                        goto eof;
    237225                }
    238         }
    239         else
    240         {
    241                 st = read( req->fd, buffer, sizeof( buffer ) );
    242                 if( st < 0 )
    243                 {
    244                         if( !sockerr_again() )
    245                         {
    246                                 req->status_string = g_strdup( strerror( errno ) );
     226        } else {
     227                st = read(req->fd, buffer, sizeof(buffer));
     228                if (st < 0) {
     229                        if (!sockerr_again()) {
     230                                req->status_string = g_strdup(strerror(errno));
    247231                                goto cleanup;
    248232                        }
    249                 }
    250                 else if( st == 0 )
    251                 {
     233                } else if (st == 0) {
    252234                        goto eof;
    253235                }
    254236        }
    255        
    256         if( st > 0 )
    257         {
     237
     238        if (st > 0) {
    258239                http_ret_t c;
    259                
    260                 if( req->flags & HTTPC_CHUNKED )
    261                         c = http_process_chunked_data( req, buffer, st );
    262                 else
    263                         c = http_process_data( req, buffer, st );
    264                
    265                 if( c == CR_EOF )
     240
     241                if (req->flags & HTTPC_CHUNKED) {
     242                        c = http_process_chunked_data(req, buffer, st);
     243                } else {
     244                        c = http_process_data(req, buffer, st);
     245                }
     246
     247                if (c == CR_EOF) {
    266248                        goto eof;
    267                 else if( c == CR_ERROR || c == CR_ABORT )
     249                } else if (c == CR_ERROR || c == CR_ABORT) {
    268250                        return FALSE;
    269         }
    270        
    271         if( req->content_length != -1 &&
    272             req->body_size >= req->content_length )
     251                }
     252        }
     253
     254        if (req->content_length != -1 &&
     255            req->body_size >= req->content_length) {
    273256                goto eof;
    274        
    275         if( ssl_pending( req->ssl ) )
    276                 return http_incoming_data( data, source, cond );
    277        
     257        }
     258
     259        if (ssl_pending(req->ssl)) {
     260                return http_incoming_data(data, source, cond);
     261        }
     262
    278263        /* There will be more! */
    279         req->inpa = b_input_add( req->fd,
    280                                  req->ssl ? ssl_getdirection( req->ssl ) : B_EV_IO_READ,
    281                                  http_incoming_data, req );
    282        
     264        req->inpa = b_input_add(req->fd,
     265                                req->ssl ? ssl_getdirection(req->ssl) : B_EV_IO_READ,
     266                                http_incoming_data, req);
     267
    283268        return FALSE;
    284269
    285270eof:
    286271        req->flags |= HTTPC_EOF;
    287        
     272
    288273        /* Maybe if the webserver is overloaded, or when there's bad SSL
    289274           support... */
    290         if( req->bytes_read == 0 )
    291         {
    292                 req->status_string = g_strdup( "Empty HTTP reply" );
     275        if (req->bytes_read == 0) {
     276                req->status_string = g_strdup("Empty HTTP reply");
    293277                goto cleanup;
    294278        }
     
    298282        req->inpa = 0;
    299283
    300         if( req->ssl )
    301                 ssl_disconnect( req->ssl );
    302         else
    303                 closesocket( req->fd );
    304        
    305         if( req->body_size < req->content_length )
    306         {
     284        if (req->ssl) {
     285                ssl_disconnect(req->ssl);
     286        } else {
     287                closesocket(req->fd);
     288        }
     289
     290        if (req->body_size < req->content_length) {
    307291                req->status_code = -1;
    308                 g_free( req->status_string );
    309                 req->status_string = g_strdup( "Response truncated" );
    310         }
    311        
    312         if( getenv( "BITLBEE_DEBUG" ) && req )
    313                 printf( "Finishing HTTP request with status: %s\n",
    314                         req->status_string ? req->status_string : "NULL" );
    315        
    316         req->func( req );
    317         http_free( req );
     292                g_free(req->status_string);
     293                req->status_string = g_strdup("Response truncated");
     294        }
     295
     296        if (getenv("BITLBEE_DEBUG") && req) {
     297                printf("Finishing HTTP request with status: %s\n",
     298                       req->status_string ? req->status_string : "NULL");
     299        }
     300
     301        req->func(req);
     302        http_free(req);
    318303        return FALSE;
    319304}
    320305
    321 static http_ret_t http_process_chunked_data( struct http_request *req, const char *buffer, int len )
     306static http_ret_t http_process_chunked_data(struct http_request *req, const char *buffer, int len)
    322307{
    323308        char *chunk, *eos, *s;
    324        
    325         if( len < 0 )
     309
     310        if (len < 0) {
    326311                return TRUE;
    327        
    328         if( len > 0 )
    329         {
    330                 req->cbuf = g_realloc( req->cbuf, req->cblen + len + 1 );
    331                 memcpy( req->cbuf + req->cblen, buffer, len );
     312        }
     313
     314        if (len > 0) {
     315                req->cbuf = g_realloc(req->cbuf, req->cblen + len + 1);
     316                memcpy(req->cbuf + req->cblen, buffer, len);
    332317                req->cblen += len;
    333318                req->cbuf[req->cblen] = '\0';
    334319        }
    335        
     320
    336321        /* Turns out writing a proper chunked-encoding state machine is not
    337322           that simple. :-( I've tested this one feeding it byte by byte so
     
    339324        chunk = req->cbuf;
    340325        eos = req->cbuf + req->cblen;
    341         while( TRUE )
    342         {
     326        while (TRUE) {
    343327                int clen = 0;
    344                
     328
    345329                /* Might be a \r\n from the last chunk. */
    346330                s = chunk;
    347                 while( g_ascii_isspace( *s ) )
    348                         s ++;
     331                while (g_ascii_isspace(*s)) {
     332                        s++;
     333                }
    349334                /* Chunk length. Might be incomplete. */
    350                 if( s < eos && sscanf( s, "%x", &clen ) != 1 )
     335                if (s < eos && sscanf(s, "%x", &clen) != 1) {
    351336                        return CR_ERROR;
    352                 while( g_ascii_isxdigit( *s ) )
    353                         s ++;
    354                
     337                }
     338                while (g_ascii_isxdigit(*s)) {
     339                        s++;
     340                }
     341
    355342                /* If we read anything here, it *must* be \r\n. */
    356                 if( strncmp( s, "\r\n", MIN( 2, eos - s ) ) != 0 )
     343                if (strncmp(s, "\r\n", MIN(2, eos - s)) != 0) {
    357344                        return CR_ERROR;
     345                }
    358346                s += 2;
    359                
    360                 if( s >= eos )
     347
     348                if (s >= eos) {
    361349                        break;
    362                
    363                 /* 0-length chunk means end of response. */     
    364                 if( clen == 0 )
     350                }
     351
     352                /* 0-length chunk means end of response. */
     353                if (clen == 0) {
    365354                        return CR_EOF;
    366                
     355                }
     356
    367357                /* Wait for the whole chunk to arrive. */
    368                 if( s + clen > eos )
     358                if (s + clen > eos) {
    369359                        break;
    370                 if( http_process_data( req, s, clen ) != CR_OK )
     360                }
     361                if (http_process_data(req, s, clen) != CR_OK) {
    371362                        return CR_ABORT;
    372                
     363                }
     364
    373365                chunk = s + clen;
    374366        }
    375        
    376         if( chunk != req->cbuf )
    377         {
     367
     368        if (chunk != req->cbuf) {
    378369                req->cblen = eos - chunk;
    379                 s = g_memdup( chunk, req->cblen + 1 );
    380                 g_free( req->cbuf );
     370                s = g_memdup(chunk, req->cblen + 1);
     371                g_free(req->cbuf);
    381372                req->cbuf = s;
    382373        }
    383        
     374
    384375        return CR_OK;
    385376}
    386377
    387 static http_ret_t http_process_data( struct http_request *req, const char *buffer, int len )
    388 {
    389         if( len <= 0 )
     378static http_ret_t http_process_data(struct http_request *req, const char *buffer, int len)
     379{
     380        if (len <= 0) {
    390381                return CR_OK;
    391        
    392         if( !req->reply_body )
    393         {
    394                 req->reply_headers = g_realloc( req->reply_headers, req->bytes_read + len + 1 );
    395                 memcpy( req->reply_headers + req->bytes_read, buffer, len );
     382        }
     383
     384        if (!req->reply_body) {
     385                req->reply_headers = g_realloc(req->reply_headers, req->bytes_read + len + 1);
     386                memcpy(req->reply_headers + req->bytes_read, buffer, len);
    396387                req->bytes_read += len;
    397388                req->reply_headers[req->bytes_read] = '\0';
    398                
    399                 if( strstr( req->reply_headers, "\r\n\r\n" ) ||
    400                     strstr( req->reply_headers, "\n\n" ) )
    401                 {
     389
     390                if (strstr(req->reply_headers, "\r\n\r\n") ||
     391                    strstr(req->reply_headers, "\n\n")) {
    402392                        /* We've now received all headers. Look for something
    403393                           interesting. */
    404                         if( !http_handle_headers( req ) )
     394                        if (!http_handle_headers(req)) {
    405395                                return CR_ABORT;
    406                        
     396                        }
     397
    407398                        /* Start parsing the body as chunked if required. */
    408                         if( req->flags & HTTPC_CHUNKED )
    409                                 return http_process_chunked_data( req, NULL, 0 );
    410                 }
    411         }
    412         else
    413         {
     399                        if (req->flags & HTTPC_CHUNKED) {
     400                                return http_process_chunked_data(req, NULL, 0);
     401                        }
     402                }
     403        } else {
    414404                int pos = req->reply_body - req->sbuf;
    415                 req->sbuf = g_realloc( req->sbuf, req->sblen + len + 1 );
    416                 memcpy( req->sbuf + req->sblen, buffer, len );
     405                req->sbuf = g_realloc(req->sbuf, req->sblen + len + 1);
     406                memcpy(req->sbuf + req->sblen, buffer, len);
    417407                req->bytes_read += len;
    418408                req->sblen += len;
     
    421411                req->body_size = req->sblen - pos;
    422412        }
    423        
    424         if( ( req->flags & HTTPC_STREAMING ) && req->reply_body )
    425                 req->func( req );
    426        
     413
     414        if ((req->flags & HTTPC_STREAMING) && req->reply_body) {
     415                req->func(req);
     416        }
     417
    427418        return CR_OK;
    428419}
     
    430421/* Splits headers and body. Checks result code, in case of 300s it'll handle
    431422   redirects. If this returns FALSE, don't call any callbacks! */
    432 static gboolean http_handle_headers( struct http_request *req )
     423static gboolean http_handle_headers(struct http_request *req)
    433424{
    434425        char *end1, *end2, *s;
    435426        int evil_server = 0;
    436        
     427
    437428        /* Zero termination is very convenient. */
    438429        req->reply_headers[req->bytes_read] = '\0';
    439        
     430
    440431        /* Find the separation between headers and body, and keep stupid
    441432           webservers in mind. */
    442         end1 = strstr( req->reply_headers, "\r\n\r\n" );
    443         end2 = strstr( req->reply_headers, "\n\n" );
    444        
    445         if( end2 && end2 < end1 )
    446         {
     433        end1 = strstr(req->reply_headers, "\r\n\r\n");
     434        end2 = strstr(req->reply_headers, "\n\n");
     435
     436        if (end2 && end2 < end1) {
    447437                end1 = end2 + 1;
    448438                evil_server = 1;
    449         }
    450         else if( end1 )
    451         {
     439        } else if (end1) {
    452440                end1 += 2;
    453         }
    454         else
    455         {
    456                 req->status_string = g_strdup( "Malformed HTTP reply" );
     441        } else {
     442                req->status_string = g_strdup("Malformed HTTP reply");
    457443                return TRUE;
    458444        }
    459        
     445
    460446        *end1 = '\0';
    461        
    462         if( getenv( "BITLBEE_DEBUG" ) )
    463                 printf( "HTTP response headers:\n%s\n", req->reply_headers );
    464        
    465         if( evil_server )
     447
     448        if (getenv("BITLBEE_DEBUG")) {
     449                printf("HTTP response headers:\n%s\n", req->reply_headers);
     450        }
     451
     452        if (evil_server) {
    466453                req->reply_body = end1 + 1;
    467         else
     454        } else {
    468455                req->reply_body = end1 + 2;
    469        
     456        }
     457
    470458        /* Separately allocated space for headers and body. */
    471459        req->sblen = req->body_size = req->reply_headers + req->bytes_read - req->reply_body;
    472         req->sbuf = req->reply_body = g_memdup( req->reply_body, req->body_size + 1 );
    473         req->reply_headers = g_realloc( req->reply_headers, end1 - req->reply_headers + 1 );
    474        
    475         if( ( end1 = strchr( req->reply_headers, ' ' ) ) != NULL )
    476         {
    477                 if( sscanf( end1 + 1, "%hd", &req->status_code ) != 1 )
    478                 {
    479                         req->status_string = g_strdup( "Can't parse status code" );
     460        req->sbuf = req->reply_body = g_memdup(req->reply_body, req->body_size + 1);
     461        req->reply_headers = g_realloc(req->reply_headers, end1 - req->reply_headers + 1);
     462
     463        if ((end1 = strchr(req->reply_headers, ' ')) != NULL) {
     464                if (sscanf(end1 + 1, "%hd", &req->status_code) != 1) {
     465                        req->status_string = g_strdup("Can't parse status code");
    480466                        req->status_code = -1;
    481                 }
    482                 else
    483                 {
     467                } else {
    484468                        char *eol;
    485                        
    486                         if( evil_server )
    487                                 eol = strchr( end1, '\n' );
    488                         else
    489                                 eol = strchr( end1, '\r' );
    490                        
    491                         req->status_string = g_strndup( end1 + 1, eol - end1 - 1 );
    492                        
     469
     470                        if (evil_server) {
     471                                eol = strchr(end1, '\n');
     472                        } else {
     473                                eol = strchr(end1, '\r');
     474                        }
     475
     476                        req->status_string = g_strndup(end1 + 1, eol - end1 - 1);
     477
    493478                        /* Just to be sure... */
    494                         if( ( eol = strchr( req->status_string, '\r' ) ) )
     479                        if ((eol = strchr(req->status_string, '\r'))) {
    495480                                *eol = 0;
    496                         if( ( eol = strchr( req->status_string, '\n' ) ) )
     481                        }
     482                        if ((eol = strchr(req->status_string, '\n'))) {
    497483                                *eol = 0;
    498                 }
    499         }
    500         else
    501         {
    502                 req->status_string = g_strdup( "Can't locate status code" );
     484                        }
     485                }
     486        } else {
     487                req->status_string = g_strdup("Can't locate status code");
    503488                req->status_code = -1;
    504489        }
    505        
    506         if( ( ( req->status_code >= 301 && req->status_code <= 303 ) ||
    507               req->status_code == 307 ) && req->redir_ttl-- > 0 )
    508         {
     490
     491        if (((req->status_code >= 301 && req->status_code <= 303) ||
     492             req->status_code == 307) && req->redir_ttl-- > 0) {
    509493                char *loc, *new_request, *new_host;
    510494                int error = 0, new_port, new_proto;
    511                
     495
    512496                /* We might fill it again, so let's not leak any memory. */
    513                 g_free( req->status_string );
     497                g_free(req->status_string);
    514498                req->status_string = NULL;
    515                
    516                 loc = strstr( req->reply_headers, "\nLocation: " );
    517                 if( loc == NULL ) /* We can't handle this redirect... */
    518                 {
    519                         req->status_string = g_strdup( "Can't locate Location: header" );
     499
     500                loc = strstr(req->reply_headers, "\nLocation: ");
     501                if (loc == NULL) { /* We can't handle this redirect... */
     502                        req->status_string = g_strdup("Can't locate Location: header");
    520503                        return TRUE;
    521504                }
    522                
     505
    523506                loc += 11;
    524                 while( *loc == ' ' )
    525                         loc ++;
    526                
     507                while (*loc == ' ') {
     508                        loc++;
     509                }
     510
    527511                /* TODO/FIXME: Possibly have to handle relative redirections,
    528512                   and rewrite Host: headers. Not necessary for now, it's
    529513                   enough for passport authentication like this. */
    530                
    531                 if( *loc == '/' )
    532                 {
     514
     515                if (*loc == '/') {
    533516                        /* Just a different pathname... */
    534                        
     517
    535518                        /* Since we don't cache the servername, and since we
    536519                           don't need this yet anyway, I won't implement it. */
    537                        
    538                         req->status_string = g_strdup( "Can't handle relative redirects" );
    539                        
     520
     521                        req->status_string = g_strdup("Can't handle relative redirects");
     522
    540523                        return TRUE;
    541                 }
    542                 else
    543                 {
     524                } else {
    544525                        /* A whole URL */
    545526                        url_t *url;
    546527                        char *s, *version, *headers;
    547528                        const char *new_method;
    548                        
    549                         s = strstr( loc, "\r\n" );
    550                         if( s == NULL )
     529
     530                        s = strstr(loc, "\r\n");
     531                        if (s == NULL) {
    551532                                return TRUE;
    552                        
    553                         url = g_new0( url_t, 1 );
     533                        }
     534
     535                        url = g_new0(url_t, 1);
    554536                        *s = 0;
    555                        
    556                         if( !url_set( url, loc ) )
    557                         {
    558                                 req->status_string = g_strdup( "Malformed redirect URL" );
    559                                 g_free( url );
     537
     538                        if (!url_set(url, loc)) {
     539                                req->status_string = g_strdup("Malformed redirect URL");
     540                                g_free(url);
    560541                                return TRUE;
    561542                        }
    562                        
     543
    563544                        /* Find all headers and, if necessary, the POST request contents.
    564545                           Skip the old Host: header though. This crappy code here means
    565546                           anything using this http_client MUST put the Host: header at
    566547                           the top. */
    567                         if( !( ( s = strstr( req->request, "\r\nHost: " ) ) &&
    568                                ( s = strstr( s + strlen( "\r\nHost: " ), "\r\n" ) ) ) )
    569                         {
    570                                 req->status_string = g_strdup( "Error while rebuilding request string" );
    571                                 g_free( url );
     548                        if (!((s = strstr(req->request, "\r\nHost: ")) &&
     549                              (s = strstr(s + strlen("\r\nHost: "), "\r\n")))) {
     550                                req->status_string = g_strdup("Error while rebuilding request string");
     551                                g_free(url);
    572552                                return TRUE;
    573553                        }
    574554                        headers = s;
    575                        
     555
    576556                        /* More or less HTTP/1.0 compliant, from my reading of RFC 2616.
    577557                           Always perform a GET request unless we received a 301. 303 was
    578558                           meant for this but it's HTTP/1.1-only and we're specifically
    579559                           speaking HTTP/1.0. ...
    580                            
     560
    581561                           Well except someone at identi.ca's didn't bother reading any
    582562                           RFCs and just return HTTP/1.1-specific status codes to HTTP/1.0
    583563                           requests. Fuckers. So here we are, handle 301..303,307. */
    584                         if( strncmp( req->request, "GET", 3 ) == 0 )
     564                        if (strncmp(req->request, "GET", 3) == 0) {
    585565                                /* GETs never become POSTs. */
    586566                                new_method = "GET";
    587                         else if( req->status_code == 302 || req->status_code == 303 )
     567                        } else if (req->status_code == 302 || req->status_code == 303) {
    588568                                /* 302 de-facto becomes GET, 303 as specified by RFC 2616#10.3.3 */
    589569                                new_method = "GET";
    590                         else
     570                        } else {
    591571                                /* 301 de-facto should stay POST, 307 specifally RFC 2616#10.3.8 */
    592572                                new_method = "POST";
    593                        
    594                         if( ( version = strstr( req->request, " HTTP/" ) ) &&
    595                             ( s = strstr( version, "\r\n" ) ) )
    596                         {
    597                                 version ++;
    598                                 version = g_strndup( version, s - version );
    599                         }
    600                         else
    601                                 version = g_strdup( "HTTP/1.0" );
    602                        
     573                        }
     574
     575                        if ((version = strstr(req->request, " HTTP/")) &&
     576                            (s = strstr(version, "\r\n"))) {
     577                                version++;
     578                                version = g_strndup(version, s - version);
     579                        } else {
     580                                version = g_strdup("HTTP/1.0");
     581                        }
     582
    603583                        /* Okay, this isn't fun! We have to rebuild the request... :-( */
    604                         new_request = g_strdup_printf( "%s %s %s\r\nHost: %s%s",
    605                                                        new_method, url->file, version,
    606                                                        url->host, headers );
    607                        
    608                         new_host = g_strdup( url->host );
     584                        new_request = g_strdup_printf("%s %s %s\r\nHost: %s%s",
     585                                                      new_method, url->file, version,
     586                                                      url->host, headers);
     587
     588                        new_host = g_strdup(url->host);
    609589                        new_port = url->port;
    610590                        new_proto = url->proto;
    611                        
     591
    612592                        /* If we went from POST to GET, truncate the request content. */
    613                         if( new_request[0] != req->request[0] && new_request[0] == 'G' &&
    614                             ( s = strstr( new_request, "\r\n\r\n" ) ) )
     593                        if (new_request[0] != req->request[0] && new_request[0] == 'G' &&
     594                            (s = strstr(new_request, "\r\n\r\n"))) {
    615595                                s[4] = '\0';
    616                        
    617                         g_free( url );
    618                         g_free( version );
    619                 }
    620                
    621                 if( req->ssl )
    622                         ssl_disconnect( req->ssl );
    623                 else
    624                         closesocket( req->fd );
    625                
     596                        }
     597
     598                        g_free(url);
     599                        g_free(version);
     600                }
     601
     602                if (req->ssl) {
     603                        ssl_disconnect(req->ssl);
     604                } else {
     605                        closesocket(req->fd);
     606                }
     607
    626608                req->fd = -1;
    627609                req->ssl = NULL;
    628                
    629                 if( getenv( "BITLBEE_DEBUG" ) )
    630                         printf( "New headers for redirected HTTP request:\n%s\n", new_request );
    631        
    632                 if( new_proto == PROTO_HTTPS )
    633                 {
    634                         req->ssl = ssl_connect( new_host, new_port, TRUE, http_ssl_connected, req );
    635                         if( req->ssl == NULL )
     610
     611                if (getenv("BITLBEE_DEBUG")) {
     612                        printf("New headers for redirected HTTP request:\n%s\n", new_request);
     613                }
     614
     615                if (new_proto == PROTO_HTTPS) {
     616                        req->ssl = ssl_connect(new_host, new_port, TRUE, http_ssl_connected, req);
     617                        if (req->ssl == NULL) {
    636618                                error = 1;
    637                 }
    638                 else
    639                 {
    640                         req->fd = proxy_connect( new_host, new_port, http_connected, req );
    641                         if( req->fd < 0 )
     619                        }
     620                } else {
     621                        req->fd = proxy_connect(new_host, new_port, http_connected, req);
     622                        if (req->fd < 0) {
    642623                                error = 1;
    643                 }
    644                 g_free( new_host );
    645                
    646                 if( error )
    647                 {
    648                         req->status_string = g_strdup( "Connection problem during redirect" );
    649                         g_free( new_request );
     624                        }
     625                }
     626                g_free(new_host);
     627
     628                if (error) {
     629                        req->status_string = g_strdup("Connection problem during redirect");
     630                        g_free(new_request);
    650631                        return TRUE;
    651632                }
    652                
    653                 g_free( req->request );
    654                 g_free( req->reply_headers );
    655                 g_free( req->sbuf );
     633
     634                g_free(req->request);
     635                g_free(req->reply_headers);
     636                g_free(req->sbuf);
    656637                req->request = new_request;
    657                 req->request_length = strlen( new_request );
     638                req->request_length = strlen(new_request);
    658639                req->bytes_read = req->bytes_written = req->inpa = 0;
    659640                req->reply_headers = req->reply_body = NULL;
    660641                req->sbuf = req->cbuf = NULL;
    661642                req->sblen = req->cblen = 0;
    662                
     643
    663644                return FALSE;
    664645        }
    665646
    666         if( ( s = get_rfc822_header( req->reply_headers, "Content-Length", 0 ) ) &&
    667             sscanf( s, "%d", &req->content_length ) != 1 )
     647        if ((s = get_rfc822_header(req->reply_headers, "Content-Length", 0)) &&
     648            sscanf(s, "%d", &req->content_length) != 1) {
    668649                req->content_length = -1;
    669         g_free( s );
    670        
    671         if( ( s = get_rfc822_header( req->reply_headers, "Transfer-Encoding", 0 ) ) )
    672         {
    673                 if( strcasestr( s, "chunked" ) )
    674                 {
     650        }
     651        g_free(s);
     652
     653        if ((s = get_rfc822_header(req->reply_headers, "Transfer-Encoding", 0))) {
     654                if (strcasestr(s, "chunked")) {
    675655                        req->flags |= HTTPC_CHUNKED;
    676656                        req->cbuf = req->sbuf;
    677657                        req->cblen = req->sblen;
    678                        
    679                         req->reply_body = req->sbuf = g_strdup( "" );
     658
     659                        req->reply_body = req->sbuf = g_strdup("");
    680660                        req->body_size = req->sblen = 0;
    681661                }
    682                 g_free( s );
    683         }
    684        
     662                g_free(s);
     663        }
     664
    685665        return TRUE;
    686666}
    687667
    688 void http_flush_bytes( struct http_request *req, size_t len )
    689 {
    690         if( len <= 0 || len > req->body_size || !( req->flags & HTTPC_STREAMING ) )
     668void http_flush_bytes(struct http_request *req, size_t len)
     669{
     670        if (len <= 0 || len > req->body_size || !(req->flags & HTTPC_STREAMING)) {
    691671                return;
    692        
     672        }
     673
    693674        req->reply_body += len;
    694675        req->body_size -= len;
    695        
    696         if( req->reply_body - req->sbuf >= 512 )
    697         {
    698                 char *new = g_memdup( req->reply_body, req->body_size + 1 );
    699                 g_free( req->sbuf );
     676
     677        if (req->reply_body - req->sbuf >= 512) {
     678                char *new = g_memdup(req->reply_body, req->body_size + 1);
     679                g_free(req->sbuf);
    700680                req->reply_body = req->sbuf = new;
    701681                req->sblen = req->body_size;
     
    703683}
    704684
    705 void http_close( struct http_request *req )
    706 {
    707         if( !req )
     685void http_close(struct http_request *req)
     686{
     687        if (!req) {
    708688                return;
    709        
    710         if( req->inpa > 0 )
    711                 b_event_remove( req->inpa );
    712        
    713         if( req->ssl )
    714                 ssl_disconnect( req->ssl );
    715         else
    716                 closesocket( req->fd );
    717        
    718         http_free( req );
    719 }
    720 
    721 static void http_free( struct http_request *req )
    722 {
    723         g_free( req->request );
    724         g_free( req->reply_headers );
    725         g_free( req->status_string );
    726         g_free( req->sbuf );
    727         g_free( req->cbuf );
    728         g_free( req );
    729 }
     689        }
     690
     691        if (req->inpa > 0) {
     692                b_event_remove(req->inpa);
     693        }
     694
     695        if (req->ssl) {
     696                ssl_disconnect(req->ssl);
     697        } else {
     698                closesocket(req->fd);
     699        }
     700
     701        http_free(req);
     702}
     703
     704static void http_free(struct http_request *req)
     705{
     706        g_free(req->request);
     707        g_free(req->reply_headers);
     708        g_free(req->status_string);
     709        g_free(req->sbuf);
     710        g_free(req->cbuf);
     711        g_free(req);
     712}
  • lib/http_client.h

    raf359b4 r5ebff60  
    1   /********************************************************************\
     1/********************************************************************\
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
     
    2828   response to come back. Initially written for MS Passport authentication,
    2929   but used for many other things now like OAuth and Twitter.
    30    
     30
    3131   It's very useful for doing quick requests without blocking the whole
    3232   program. Unfortunately it doesn't support fancy stuff like HTTP keep-
     
    3838struct http_request;
    3939
    40 typedef enum http_client_flags
    41 {
     40typedef enum http_client_flags {
    4241        HTTPC_STREAMING = 1,
    4342        HTTPC_EOF = 2,
    4443        HTTPC_CHUNKED = 4,
    45        
     44
    4645        /* Let's reserve 0x1000000+ for lib users. */
    4746} http_client_flags_t;
    4847
    4948/* Your callback function should look like this: */
    50 typedef void (*http_input_function)( struct http_request * );
     49typedef void (*http_input_function)(struct http_request *);
    5150
    5251/* This structure will be filled in by the http_dorequest* functions, and
    5352   it will be passed to the callback function. Use the data field to add
    5453   your own data. */
    55 struct http_request
    56 {
     54struct http_request {
    5755        char *request;          /* The request to send to the server. */
    5856        int request_length;     /* Its size. */
     
    6563        short redir_ttl;        /* You can set it to 0 if you don't want
    6664                                   http_client to follow them. */
    67        
     65
    6866        http_client_flags_t flags;
    69        
     67
    7068        http_input_function func;
    7169        gpointer data;
    72        
     70
    7371        /* Please don't touch the things down here, you shouldn't need them. */
    7472        void *ssl;
    7573        int fd;
    76        
     74
    7775        int inpa;
    7876        int bytes_written;
    7977        int bytes_read;
    8078        int content_length;     /* "Content-Length:" header or -1 */
    81        
     79
    8280        /* Used in streaming mode. Caller should read from reply_body. */
    8381        char *sbuf;
    8482        size_t sblen;
    85        
     83
    8684        /* Chunked encoding only. Raw chunked stream is decoded from here. */
    8785        char *cbuf;
     
    9391   you want to add some extra headers. As you can see, HTTPS connections
    9492   are also supported (using ssl_client). */
    95 struct http_request *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data );
    96 struct http_request *http_dorequest_url( char *url_string, http_input_function func, gpointer data );
     93struct http_request *http_dorequest(char *host, int port, int ssl, char *request, http_input_function func,
     94                                    gpointer data);
     95struct http_request *http_dorequest_url(char *url_string, http_input_function func, gpointer data);
    9796
    9897/* For streaming connections only; flushes len bytes at the start of the buffer. */
    99 void http_flush_bytes( struct http_request *req, size_t len );
    100 void http_close( struct http_request *req );
     98void http_flush_bytes(struct http_request *req, size_t len);
     99void http_close(struct http_request *req);
  • lib/ini.c

    raf359b4 r5ebff60  
    1   /********************************************************************\
     1/********************************************************************\
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
     
    2626#include "bitlbee.h"
    2727
    28 ini_t *ini_open( char *file )
     28ini_t *ini_open(char *file)
    2929{
    3030        int fd;
    3131        ini_t *ini = NULL;
    3232        struct stat fi;
    33        
    34         if( ( fd = open( file, O_RDONLY ) ) != -1 &&
    35             fstat( fd, &fi ) == 0 &&
     33
     34        if ((fd = open(file, O_RDONLY)) != -1 &&
     35            fstat(fd, &fi) == 0 &&
    3636            fi.st_size <= 16384 &&
    37             ( ini = g_malloc( sizeof( ini_t ) + fi.st_size + 1 ) ) &&
    38             read( fd, ini->file, fi.st_size ) == fi.st_size )
    39         {
    40                 memset( ini, 0, sizeof( ini_t ) );
     37            (ini = g_malloc(sizeof(ini_t) + fi.st_size + 1)) &&
     38            read(fd, ini->file, fi.st_size) == fi.st_size) {
     39                memset(ini, 0, sizeof(ini_t));
    4140                ini->size = fi.st_size;
    4241                ini->file[ini->size] = 0;
    4342                ini->cur = ini->file;
    4443                ini->c_section = "";
    45                
    46                 close( fd );
    47                
     44
     45                close(fd);
     46
    4847                return ini;
    4948        }
    5049
    51         if( fd >= 0 )
    52                 close( fd );
    53        
    54         ini_close( ini );
     50        if (fd >= 0) {
     51                close(fd);
     52        }
     53
     54        ini_close(ini);
    5555
    5656        return NULL;
     
    5959/* Strips leading and trailing whitespace and returns a pointer to the first
    6060   non-ws character of the given string. */
    61 static char *ini_strip_whitespace( char *in )
     61static char *ini_strip_whitespace(char *in)
    6262{
    6363        char *e;
    6464
    65         while( g_ascii_isspace( *in ) )
     65        while (g_ascii_isspace(*in)) {
    6666                in++;
     67        }
    6768
    68         e = in + strlen( in ) - 1;
    69         while( e > in && g_ascii_isspace( *e ) )
     69        e = in + strlen(in) - 1;
     70        while (e > in && g_ascii_isspace(*e)) {
    7071                e--;
     72        }
    7173        e[1] = 0;
    72        
     74
    7375        return in;
    7476}
    7577
    76 int ini_read( ini_t *file )
     78int ini_read(ini_t *file)
    7779{
    7880        char *s;
    79        
    80         while( file->cur && file->cur < file->file + file->size )
    81         {
     81
     82        while (file->cur && file->cur < file->file + file->size) {
    8283                char *e, *next;
    83                
     84
    8485                file->line++;
    8586
    8687                /* Find the end of line */
    87                 if( ( e = strchr( file->cur, '\n' ) ) != NULL )
    88                 {
     88                if ((e = strchr(file->cur, '\n')) != NULL) {
    8989                        *e = 0;
    9090                        next = e + 1;
    91                 }
    92                 else
    93                 {
     91                } else {
    9492                        /* No more lines. */
    95                         e = file->cur + strlen( file->cur );
     93                        e = file->cur + strlen(file->cur);
    9694                        next = NULL;
    9795                }
    98                
     96
    9997                /* Comment? */
    100                 if( ( s = strchr( file->cur, '#' ) ) != NULL )
     98                if ((s = strchr(file->cur, '#')) != NULL) {
    10199                        *s = 0;
    102                
    103                 file->cur = ini_strip_whitespace( file->cur );
    104                
    105                 if( *file->cur == '[' )
    106                 {
     100                }
     101
     102                file->cur = ini_strip_whitespace(file->cur);
     103
     104                if (*file->cur == '[') {
    107105                        file->cur++;
    108                         if( ( s = strchr( file->cur, ']' ) ) != NULL )
    109                         {
     106                        if ((s = strchr(file->cur, ']')) != NULL) {
    110107                                *s = 0;
    111108                                file->c_section = file->cur;
    112109                        }
    113                 }
    114                 else if( ( s = strchr( file->cur, '=' ) ) != NULL )
    115                 {
     110                } else if ((s = strchr(file->cur, '=')) != NULL) {
    116111                        *s = 0;
    117                         file->key = ini_strip_whitespace( file->cur );
    118                         file->value = ini_strip_whitespace( s + 1 );
    119                        
    120                         if( ( s = strchr( file->key, '.' ) ) != NULL )
    121                         {
     112                        file->key = ini_strip_whitespace(file->cur);
     113                        file->value = ini_strip_whitespace(s + 1);
     114
     115                        if ((s = strchr(file->key, '.')) != NULL) {
    122116                                *s = 0;
    123117                                file->section = file->key;
    124118                                file->key = s + 1;
    125                         }
    126                         else
    127                         {
     119                        } else {
    128120                                file->section = file->c_section;
    129121                        }
    130                        
     122
    131123                        file->cur = next;
    132124                        return 1;
     
    136128                file->cur = next;
    137129        }
    138        
     130
    139131        return 0;
    140132}
    141133
    142 void ini_close( ini_t *file )
     134void ini_close(ini_t *file)
    143135{
    144         g_free( file );
     136        g_free(file);
    145137}
  • lib/ini.h

    raf359b4 r5ebff60  
    1   /********************************************************************\
     1/********************************************************************\
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
     
    2727#define _INI_H
    2828
    29 typedef struct
    30 {
     29typedef struct {
    3130        int line;
    3231        char *c_section;
     
    3938} ini_t;
    4039
    41 ini_t *ini_open( char *file );
    42 int ini_read( ini_t *file );
    43 void ini_close( ini_t *file );
     40ini_t *ini_open(char *file);
     41int ini_read(ini_t *file);
     42void ini_close(ini_t *file);
    4443
    4544#endif
  • lib/json.c

    raf359b4 r5ebff60  
    3939
    4040#ifdef __cplusplus
    41    const struct _json_value json_value_none; /* zero-d by ctor */
     41const struct _json_value json_value_none;    /* zero-d by ctor */
    4242#else
    43    const struct _json_value json_value_none = { 0 };
     43const struct _json_value json_value_none = { 0 };
    4444#endif
    4545
     
    5151typedef unsigned int json_uchar;
    5252
    53 static unsigned char hex_value (json_char c)
     53static unsigned char hex_value(json_char c)
    5454{
    55    if (g_ascii_isdigit(c))
    56       return c - '0';
    57 
    58    switch (c) {
    59       case 'a': case 'A': return 0x0A;
    60       case 'b': case 'B': return 0x0B;
    61       case 'c': case 'C': return 0x0C;
    62       case 'd': case 'D': return 0x0D;
    63       case 'e': case 'E': return 0x0E;
    64       case 'f': case 'F': return 0x0F;
    65       default: return 0xFF;
    66    }
     55        if (g_ascii_isdigit(c)) {
     56                return c - '0';
     57        }
     58
     59        switch (c) {
     60        case 'a': case 'A': return 0x0A;
     61        case 'b': case 'B': return 0x0B;
     62        case 'c': case 'C': return 0x0C;
     63        case 'd': case 'D': return 0x0D;
     64        case 'e': case 'E': return 0x0E;
     65        case 'f': case 'F': return 0x0F;
     66        default: return 0xFF;
     67        }
    6768}
    6869
    69 typedef struct
     70typedef struct {
     71        unsigned long used_memory;
     72
     73        unsigned int uint_max;
     74        unsigned long ulong_max;
     75
     76        json_settings settings;
     77        int first_pass;
     78
     79} json_state;
     80
     81static void * default_alloc(size_t size, int zero, void * user_data)
    7082{
    71    unsigned long used_memory;
    72 
    73    unsigned int uint_max;
    74    unsigned long ulong_max;
    75 
    76    json_settings settings;
    77    int first_pass;
    78 
    79 } json_state;
    80 
    81 static void * default_alloc (size_t size, int zero, void * user_data)
     83        return zero ? calloc(1, size) : malloc(size);
     84}
     85
     86static void default_free(void * ptr, void * user_data)
    8287{
    83    return zero ? calloc (1, size) : malloc (size);
     88        free(ptr);
    8489}
    8590
    86 static void default_free (void * ptr, void * user_data)
     91static void * json_alloc(json_state * state, unsigned long size, int zero)
    8792{
    88    free (ptr);
     93        if ((state->ulong_max - state->used_memory) < size) {
     94                return 0;
     95        }
     96
     97        if (state->settings.max_memory
     98            && (state->used_memory += size) > state->settings.max_memory) {
     99                return 0;
     100        }
     101
     102        return state->settings.mem_alloc(size, zero, state->settings.user_data);
    89103}
    90104
    91 static void * json_alloc (json_state * state, unsigned long size, int zero)
     105static int new_value
     106        (json_state * state, json_value ** top, json_value ** root, json_value ** alloc, json_type type)
    92107{
    93    if ((state->ulong_max - state->used_memory) < size)
    94       return 0;
    95 
    96    if (state->settings.max_memory
    97          && (state->used_memory += size) > state->settings.max_memory)
    98    {
    99       return 0;
    100    }
    101 
    102    return state->settings.mem_alloc (size, zero, state->settings.user_data);
     108        json_value * value;
     109        int values_size;
     110
     111        if (!state->first_pass) {
     112                value = *top = *alloc;
     113                *alloc = (*alloc)->_reserved.next_alloc;
     114
     115                if (!*root) {
     116                        *root = value;
     117                }
     118
     119                switch (value->type) {
     120                case json_array:
     121
     122                        if (!(value->u.array.values = (json_value **) json_alloc
     123                                                              (state, value->u.array.length * sizeof(json_value *),
     124                                                              0))) {
     125                                return 0;
     126                        }
     127
     128                        value->u.array.length = 0;
     129                        break;
     130
     131                case json_object:
     132
     133                        values_size = sizeof(*value->u.object.values) * value->u.object.length;
     134
     135                        if (!((*(void **) &value->u.object.values) = json_alloc
     136                                                                             (state, values_size +
     137                                                                             ((unsigned long) value->u.object.values),
     138                                                                             0))) {
     139                                return 0;
     140                        }
     141
     142                        value->_reserved.object_mem = (*(char **) &value->u.object.values) + values_size;
     143
     144                        value->u.object.length = 0;
     145                        break;
     146
     147                case json_string:
     148
     149                        if (!(value->u.string.ptr = (json_char *) json_alloc
     150                                                            (state, (value->u.string.length + 1) * sizeof(json_char),
     151                                                            0))) {
     152                                return 0;
     153                        }
     154
     155                        value->u.string.length = 0;
     156                        break;
     157
     158                default:
     159                        break;
     160                }
     161                ;
     162
     163                return 1;
     164        }
     165
     166        value = (json_value *) json_alloc(state, sizeof(json_value), 1);
     167
     168        if (!value) {
     169                return 0;
     170        }
     171
     172        if (!*root) {
     173                *root = value;
     174        }
     175
     176        value->type = type;
     177        value->parent = *top;
     178
     179        if (*alloc) {
     180                (*alloc)->_reserved.next_alloc = value;
     181        }
     182
     183        *alloc = *top = value;
     184
     185        return 1;
    103186}
    104187
    105 static int new_value
    106    (json_state * state, json_value ** top, json_value ** root, json_value ** alloc, json_type type)
     188#define e_off \
     189        ((int) (i - cur_line_begin))
     190
     191#define whitespace \
     192case '\n': ++cur_line;  cur_line_begin = i; \
     193case ' ': case '\t': case '\r'
     194
     195#define string_add(b)  \
     196        do { if (!state.first_pass) { string [string_length] = b; } ++string_length; } while (0);
     197
     198static const long
     199        flag_next             = 1 << 0,
     200        flag_reproc           = 1 << 1,
     201        flag_need_comma       = 1 << 2,
     202        flag_seek_value       = 1 << 3,
     203        flag_escaped          = 1 << 4,
     204        flag_string           = 1 << 5,
     205        flag_need_colon       = 1 << 6,
     206        flag_done             = 1 << 7,
     207        flag_num_negative     = 1 << 8,
     208        flag_num_zero         = 1 << 9,
     209        flag_num_e            = 1 << 10,
     210        flag_num_e_got_sign   = 1 << 11,
     211        flag_num_e_negative   = 1 << 12,
     212        flag_line_comment     = 1 << 13,
     213        flag_block_comment    = 1 << 14;
     214
     215json_value * json_parse_ex(json_settings * settings,
     216                           const json_char * json,
     217                           size_t length,
     218                           char * error_buf)
    107219{
    108    json_value * value;
    109    int values_size;
    110 
    111    if (!state->first_pass)
    112    {
    113       value = *top = *alloc;
    114       *alloc = (*alloc)->_reserved.next_alloc;
    115 
    116       if (!*root)
    117          *root = value;
    118 
    119       switch (value->type)
    120       {
    121          case json_array:
    122 
    123             if (! (value->u.array.values = (json_value **) json_alloc
    124                (state, value->u.array.length * sizeof (json_value *), 0)) )
    125             {
    126                return 0;
    127             }
    128 
    129             value->u.array.length = 0;
    130             break;
    131 
    132          case json_object:
    133 
    134             values_size = sizeof (*value->u.object.values) * value->u.object.length;
    135 
    136             if (! ((*(void **) &value->u.object.values) = json_alloc
    137                   (state, values_size + ((unsigned long) value->u.object.values), 0)) )
    138             {
    139                return 0;
    140             }
    141 
    142             value->_reserved.object_mem = (*(char **) &value->u.object.values) + values_size;
    143 
    144             value->u.object.length = 0;
    145             break;
    146 
    147          case json_string:
    148 
    149             if (! (value->u.string.ptr = (json_char *) json_alloc
    150                (state, (value->u.string.length + 1) * sizeof (json_char), 0)) )
    151             {
    152                return 0;
    153             }
    154 
    155             value->u.string.length = 0;
    156             break;
    157 
    158          default:
    159             break;
    160       };
    161 
    162       return 1;
    163    }
    164 
    165    value = (json_value *) json_alloc (state, sizeof (json_value), 1);
    166 
    167    if (!value)
    168       return 0;
    169 
    170    if (!*root)
    171       *root = value;
    172 
    173    value->type = type;
    174    value->parent = *top;
    175 
    176    if (*alloc)
    177       (*alloc)->_reserved.next_alloc = value;
    178 
    179    *alloc = *top = value;
    180 
    181    return 1;
     220        json_char error [json_error_max];
     221        unsigned int cur_line;
     222        const json_char * cur_line_begin, * i, * end;
     223        json_value * top, * root, * alloc = 0;
     224        json_state state = { 0 };
     225        long flags;
     226        long num_digits = 0, num_e = 0;
     227        json_int_t num_fraction = 0;
     228
     229        /* Skip UTF-8 BOM
     230         */
     231        if (length >= 3 && ((unsigned char) json [0]) == 0xEF
     232            && ((unsigned char) json [1]) == 0xBB
     233            && ((unsigned char) json [2]) == 0xBF) {
     234                json += 3;
     235                length -= 3;
     236        }
     237
     238        error[0] = '\0';
     239        end = (json + length);
     240
     241        memcpy(&state.settings, settings, sizeof(json_settings));
     242
     243        if (!state.settings.mem_alloc) {
     244                state.settings.mem_alloc = default_alloc;
     245        }
     246
     247        if (!state.settings.mem_free) {
     248                state.settings.mem_free = default_free;
     249        }
     250
     251        memset(&state.uint_max, 0xFF, sizeof(state.uint_max));
     252        memset(&state.ulong_max, 0xFF, sizeof(state.ulong_max));
     253
     254        state.uint_max -= 8; /* limit of how much can be added before next check */
     255        state.ulong_max -= 8;
     256
     257        for (state.first_pass = 1; state.first_pass >= 0; --state.first_pass) {
     258                json_uchar uchar;
     259                unsigned char uc_b1, uc_b2, uc_b3, uc_b4;
     260                json_char * string = 0;
     261                unsigned int string_length = 0;
     262
     263                top = root = 0;
     264                flags = flag_seek_value;
     265
     266                cur_line = 1;
     267                cur_line_begin = json;
     268
     269                for (i = json;; ++i) {
     270                        json_char b = (i == end ? 0 : *i);
     271
     272                        if (flags & flag_string) {
     273                                if (!b) {
     274                                        sprintf(error, "Unexpected EOF in string (at %d:%d)", cur_line, e_off);
     275                                        goto e_failed;
     276                                }
     277
     278                                if (string_length > state.uint_max) {
     279                                        goto e_overflow;
     280                                }
     281
     282                                if (flags & flag_escaped) {
     283                                        flags &= ~flag_escaped;
     284
     285                                        switch (b) {
     286                                        case 'b':  string_add('\b');  break;
     287                                        case 'f':  string_add('\f');  break;
     288                                        case 'n':  string_add('\n');  break;
     289                                        case 'r':  string_add('\r');  break;
     290                                        case 't':  string_add('\t');  break;
     291                                        case 'u':
     292
     293                                                if (end - i < 4 ||
     294                                                    (uc_b1 = hex_value(*++i)) == 0xFF || (uc_b2 = hex_value(*++i)) ==
     295                                                    0xFF
     296                                                    || (uc_b3 = hex_value(*++i)) == 0xFF || (uc_b4 = hex_value(*++i)) ==
     297                                                    0xFF) {
     298                                                        sprintf(error, "Invalid character value `%c` (at %d:%d)", b,
     299                                                                cur_line, e_off);
     300                                                        goto e_failed;
     301                                                }
     302
     303                                                uc_b1 = (uc_b1 << 4) | uc_b2;
     304                                                uc_b2 = (uc_b3 << 4) | uc_b4;
     305                                                uchar = (uc_b1 << 8) | uc_b2;
     306
     307                                                if ((uchar & 0xF800) == 0xD800) {
     308                                                        json_uchar uchar2;
     309
     310                                                        if (end - i < 6 || (*++i) != '\\' || (*++i) != 'u' ||
     311                                                            (uc_b1 = hex_value(*++i)) == 0xFF ||
     312                                                            (uc_b2 = hex_value(*++i)) == 0xFF
     313                                                            || (uc_b3 = hex_value(*++i)) == 0xFF ||
     314                                                            (uc_b4 = hex_value(*++i)) == 0xFF) {
     315                                                                sprintf(error,
     316                                                                        "Invalid character value `%c` (at %d:%d)", b,
     317                                                                        cur_line, e_off);
     318                                                                goto e_failed;
     319                                                        }
     320
     321                                                        uc_b1 = (uc_b1 << 4) | uc_b2;
     322                                                        uc_b2 = (uc_b3 << 4) | uc_b4;
     323                                                        uchar2 = (uc_b1 << 8) | uc_b2;
     324
     325                                                        uchar = 0x010000 | ((uchar & 0x3FF) << 10) | (uchar2 & 0x3FF);
     326                                                }
     327
     328                                                if (sizeof(json_char) >= sizeof(json_uchar) || (uchar <= 0x7F)) {
     329                                                        string_add((json_char) uchar);
     330                                                        break;
     331                                                }
     332
     333                                                if (uchar <= 0x7FF) {
     334                                                        if (state.first_pass) {
     335                                                                string_length += 2;
     336                                                        } else {                    string [string_length++] = 0xC0 |
     337                                                                                                               (uchar >>
     338                                                                                                                6);
     339                                                                                    string [string_length++] = 0x80 |
     340                                                                                                               (uchar &
     341                                                                                                                0x3F); }
     342
     343                                                        break;
     344                                                }
     345
     346                                                if (uchar <= 0xFFFF) {
     347                                                        if (state.first_pass) {
     348                                                                string_length += 3;
     349                                                        } else {                    string [string_length++] = 0xE0 |
     350                                                                                                               (uchar >>
     351                                                                                                                12);
     352                                                                                    string [string_length++] = 0x80 |
     353                                                                                                               ((uchar
     354                                                                                                                 >> 6) &
     355                                                                                                                0x3F);
     356                                                                                    string [string_length++] = 0x80 |
     357                                                                                                               (uchar &
     358                                                                                                                0x3F); }
     359
     360                                                        break;
     361                                                }
     362
     363                                                if (state.first_pass) {
     364                                                        string_length += 4;
     365                                                } else {                string [string_length++] = 0xF0 | (uchar >> 18);
     366                                                                        string [string_length++] = 0x80 |
     367                                                                                                   ((uchar >>
     368                                                                                                     12) & 0x3F);
     369                                                                        string [string_length++] = 0x80 |
     370                                                                                                   ((uchar >>
     371                                                                                                     6) & 0x3F);
     372                                                                        string [string_length++] = 0x80 |
     373                                                                                                   (uchar & 0x3F); }
     374
     375                                                break;
     376
     377                                        default:
     378                                                string_add(b);
     379                                        }
     380                                        ;
     381
     382                                        continue;
     383                                }
     384
     385                                if (b == '\\') {
     386                                        flags |= flag_escaped;
     387                                        continue;
     388                                }
     389
     390                                if (b == '"') {
     391                                        if (!state.first_pass) {
     392                                                string [string_length] = 0;
     393                                        }
     394
     395                                        flags &= ~flag_string;
     396                                        string = 0;
     397
     398                                        switch (top->type) {
     399                                        case json_string:
     400
     401                                                top->u.string.length = string_length;
     402                                                flags |= flag_next;
     403
     404                                                break;
     405
     406                                        case json_object:
     407
     408                                                if (state.first_pass) {
     409                                                        (*(json_char **) &top->u.object.values) += string_length + 1;
     410                                                } else {
     411                                                        top->u.object.values [top->u.object.length].name
     412                                                                = (json_char *) top->_reserved.object_mem;
     413
     414                                                        top->u.object.values [top->u.object.length].name_length
     415                                                                = string_length;
     416
     417                                                        (*(json_char **) &top->_reserved.object_mem) += string_length +
     418                                                                                                        1;
     419                                                }
     420
     421                                                flags |= flag_seek_value | flag_need_colon;
     422                                                continue;
     423
     424                                        default:
     425                                                break;
     426                                        }
     427                                        ;
     428                                } else {
     429                                        string_add(b);
     430                                        continue;
     431                                }
     432                        }
     433
     434                        if (state.settings.settings & json_enable_comments) {
     435                                if (flags & (flag_line_comment | flag_block_comment)) {
     436                                        if (flags & flag_line_comment) {
     437                                                if (b == '\r' || b == '\n' || !b) {
     438                                                        flags &= ~flag_line_comment;
     439                                                        --i; /* so null can be reproc'd */
     440                                                }
     441
     442                                                continue;
     443                                        }
     444
     445                                        if (flags & flag_block_comment) {
     446                                                if (!b) {
     447                                                        sprintf(error, "%d:%d: Unexpected EOF in block comment",
     448                                                                cur_line, e_off);
     449                                                        goto e_failed;
     450                                                }
     451
     452                                                if (b == '*' && i < (end - 1) && i [1] == '/') {
     453                                                        flags &= ~flag_block_comment;
     454                                                        ++i; /* skip closing sequence */
     455                                                }
     456
     457                                                continue;
     458                                        }
     459                                } else if (b == '/') {
     460                                        if (!(flags & (flag_seek_value | flag_done)) && top->type != json_object) {
     461                                                sprintf(error, "%d:%d: Comment not allowed here", cur_line, e_off);
     462                                                goto e_failed;
     463                                        }
     464
     465                                        if (++i == end) {
     466                                                sprintf(error, "%d:%d: EOF unexpected", cur_line, e_off);
     467                                                goto e_failed;
     468                                        }
     469
     470                                        switch (b = *i) {
     471                                        case '/':
     472                                                flags |= flag_line_comment;
     473                                                continue;
     474
     475                                        case '*':
     476                                                flags |= flag_block_comment;
     477                                                continue;
     478
     479                                        default:
     480                                                sprintf(error, "%d:%d: Unexpected `%c` in comment opening sequence",
     481                                                        cur_line, e_off, b);
     482                                                goto e_failed;
     483                                        }
     484                                        ;
     485                                }
     486                        }
     487
     488                        if (flags & flag_done) {
     489                                if (!b) {
     490                                        break;
     491                                }
     492
     493                                switch (b) {
     494whitespace:
     495                                        continue;
     496
     497                                default:
     498                                        sprintf(error, "%d:%d: Trailing garbage: `%c`", cur_line, e_off, b);
     499                                        goto e_failed;
     500                                }
     501                                ;
     502                        }
     503
     504                        if (flags & flag_seek_value) {
     505                                switch (b) {
     506whitespace:
     507                                        continue;
     508
     509                                case ']':
     510
     511                                        if (top->type == json_array) {
     512                                                flags = (flags & ~(flag_need_comma | flag_seek_value)) | flag_next;
     513                                        } else {              sprintf(error, "%d:%d: Unexpected ]", cur_line, e_off);
     514                                                              goto e_failed; }
     515
     516                                        break;
     517
     518                                default:
     519
     520                                        if (flags & flag_need_comma) {
     521                                                if (b == ',') {
     522                                                        flags &= ~flag_need_comma;
     523                                                        continue;
     524                                                } else { sprintf(error, "%d:%d: Expected , before %c", cur_line, e_off,
     525                                                                 b);
     526                                                         goto e_failed; }
     527                                        }
     528
     529                                        if (flags & flag_need_colon) {
     530                                                if (b == ':') {
     531                                                        flags &= ~flag_need_colon;
     532                                                        continue;
     533                                                } else { sprintf(error, "%d:%d: Expected : before %c", cur_line, e_off,
     534                                                                 b);
     535                                                         goto e_failed; }
     536                                        }
     537
     538                                        flags &= ~flag_seek_value;
     539
     540                                        switch (b) {
     541                                        case '{':
     542
     543                                                if (!new_value(&state, &top, &root, &alloc, json_object)) {
     544                                                        goto e_alloc_failure;
     545                                                }
     546
     547                                                continue;
     548
     549                                        case '[':
     550
     551                                                if (!new_value(&state, &top, &root, &alloc, json_array)) {
     552                                                        goto e_alloc_failure;
     553                                                }
     554
     555                                                flags |= flag_seek_value;
     556                                                continue;
     557
     558                                        case '"':
     559
     560                                                if (!new_value(&state, &top, &root, &alloc, json_string)) {
     561                                                        goto e_alloc_failure;
     562                                                }
     563
     564                                                flags |= flag_string;
     565
     566                                                string = top->u.string.ptr;
     567                                                string_length = 0;
     568
     569                                                continue;
     570
     571                                        case 't':
     572
     573                                                if ((end - i) < 3 || *(++i) != 'r' || *(++i) != 'u' || *(++i) != 'e') {
     574                                                        goto e_unknown_value;
     575                                                }
     576
     577                                                if (!new_value(&state, &top, &root, &alloc, json_boolean)) {
     578                                                        goto e_alloc_failure;
     579                                                }
     580
     581                                                top->u.boolean = 1;
     582
     583                                                flags |= flag_next;
     584                                                break;
     585
     586                                        case 'f':
     587
     588                                                if ((end - i) < 4 || *(++i) != 'a' || *(++i) != 'l' || *(++i) != 's' ||
     589                                                    *(++i) != 'e') {
     590                                                        goto e_unknown_value;
     591                                                }
     592
     593                                                if (!new_value(&state, &top, &root, &alloc, json_boolean)) {
     594                                                        goto e_alloc_failure;
     595                                                }
     596
     597                                                flags |= flag_next;
     598                                                break;
     599
     600                                        case 'n':
     601
     602                                                if ((end - i) < 3 || *(++i) != 'u' || *(++i) != 'l' || *(++i) != 'l') {
     603                                                        goto e_unknown_value;
     604                                                }
     605
     606                                                if (!new_value(&state, &top, &root, &alloc, json_null)) {
     607                                                        goto e_alloc_failure;
     608                                                }
     609
     610                                                flags |= flag_next;
     611                                                break;
     612
     613                                        default:
     614
     615                                                if (g_ascii_isdigit(b) || b == '-') {
     616                                                        if (!new_value(&state, &top, &root, &alloc, json_integer)) {
     617                                                                goto e_alloc_failure;
     618                                                        }
     619
     620                                                        if (!state.first_pass) {
     621                                                                while (g_ascii_isdigit(b) || b == '+' || b == '-'
     622                                                                       || b == 'e' || b == 'E' || b == '.') {
     623                                                                        if ((++i) == end) {
     624                                                                                b = 0;
     625                                                                                break;
     626                                                                        }
     627
     628                                                                        b = *i;
     629                                                                }
     630
     631                                                                flags |= flag_next | flag_reproc;
     632                                                                break;
     633                                                        }
     634
     635                                                        flags &= ~(flag_num_negative | flag_num_e |
     636                                                                   flag_num_e_got_sign | flag_num_e_negative |
     637                                                                   flag_num_zero);
     638
     639                                                        num_digits = 0;
     640                                                        num_fraction = 0;
     641                                                        num_e = 0;
     642
     643                                                        if (b != '-') {
     644                                                                flags |= flag_reproc;
     645                                                                break;
     646                                                        }
     647
     648                                                        flags |= flag_num_negative;
     649                                                        continue;
     650                                                } else { sprintf(error, "%d:%d: Unexpected %c when seeking value",
     651                                                                 cur_line, e_off, b);
     652                                                         goto e_failed; }
     653                                        }
     654                                        ;
     655                                }
     656                                ;
     657                        } else {
     658                                switch (top->type) {
     659                                case json_object:
     660
     661                                        switch (b) {
     662whitespace:
     663                                                continue;
     664
     665                                        case '"':
     666
     667                                                if (flags & flag_need_comma) {
     668                                                        sprintf(error, "%d:%d: Expected , before \"", cur_line, e_off);
     669                                                        goto e_failed;
     670                                                }
     671
     672                                                flags |= flag_string;
     673
     674                                                string = (json_char *) top->_reserved.object_mem;
     675                                                string_length = 0;
     676
     677                                                break;
     678
     679                                        case '}':
     680
     681                                                flags = (flags & ~flag_need_comma) | flag_next;
     682                                                break;
     683
     684                                        case ',':
     685
     686                                                if (flags & flag_need_comma) {
     687                                                        flags &= ~flag_need_comma;
     688                                                        break;
     689                                                }
     690
     691                                        default:
     692
     693                                                sprintf(error, "%d:%d: Unexpected `%c` in object", cur_line, e_off, b);
     694                                                goto e_failed;
     695                                        }
     696                                        ;
     697
     698                                        break;
     699
     700                                case json_integer:
     701                                case json_double:
     702
     703                                        if (g_ascii_isdigit(b)) {
     704                                                ++num_digits;
     705
     706                                                if (top->type == json_integer || flags & flag_num_e) {
     707                                                        if (!(flags & flag_num_e)) {
     708                                                                if (flags & flag_num_zero) {
     709                                                                        sprintf(error,
     710                                                                                "%d:%d: Unexpected `0` before `%c`",
     711                                                                                cur_line, e_off, b);
     712                                                                        goto e_failed;
     713                                                                }
     714
     715                                                                if (num_digits == 1 && b == '0') {
     716                                                                        flags |= flag_num_zero;
     717                                                                }
     718                                                        } else {
     719                                                                flags |= flag_num_e_got_sign;
     720                                                                num_e = (num_e * 10) + (b - '0');
     721                                                                continue;
     722                                                        }
     723
     724                                                        top->u.integer = (top->u.integer * 10) + (b - '0');
     725                                                        continue;
     726                                                }
     727
     728                                                num_fraction = (num_fraction * 10) + (b - '0');
     729                                                continue;
     730                                        }
     731
     732                                        if (b == '+' || b == '-') {
     733                                                if ((flags & flag_num_e) && !(flags & flag_num_e_got_sign)) {
     734                                                        flags |= flag_num_e_got_sign;
     735
     736                                                        if (b == '-') {
     737                                                                flags |= flag_num_e_negative;
     738                                                        }
     739
     740                                                        continue;
     741                                                }
     742                                        } else if (b == '.' && top->type == json_integer) {
     743                                                if (!num_digits) {
     744                                                        sprintf(error, "%d:%d: Expected digit before `.`", cur_line,
     745                                                                e_off);
     746                                                        goto e_failed;
     747                                                }
     748
     749                                                top->type = json_double;
     750                                                top->u.dbl = (double) top->u.integer;
     751
     752                                                num_digits = 0;
     753                                                continue;
     754                                        }
     755
     756                                        if (!(flags & flag_num_e)) {
     757                                                if (top->type == json_double) {
     758                                                        if (!num_digits) {
     759                                                                sprintf(error, "%d:%d: Expected digit after `.`",
     760                                                                        cur_line, e_off);
     761                                                                goto e_failed;
     762                                                        }
     763
     764                                                        top->u.dbl += ((double) num_fraction) /
     765                                                                      (pow(10, (double) num_digits));
     766                                                }
     767
     768                                                if (b == 'e' || b == 'E') {
     769                                                        flags |= flag_num_e;
     770
     771                                                        if (top->type == json_integer) {
     772                                                                top->type = json_double;
     773                                                                top->u.dbl = (double) top->u.integer;
     774                                                        }
     775
     776                                                        num_digits = 0;
     777                                                        flags &= ~flag_num_zero;
     778
     779                                                        continue;
     780                                                }
     781                                        } else {
     782                                                if (!num_digits) {
     783                                                        sprintf(error, "%d:%d: Expected digit after `e`", cur_line,
     784                                                                e_off);
     785                                                        goto e_failed;
     786                                                }
     787
     788                                                top->u.dbl *=
     789                                                        pow(10,
     790                                                            (double) (flags & flag_num_e_negative ? -num_e : num_e));
     791                                        }
     792
     793                                        if (flags & flag_num_negative) {
     794                                                if (top->type == json_integer) {
     795                                                        top->u.integer = -top->u.integer;
     796                                                } else {
     797                                                        top->u.dbl = -top->u.dbl;
     798                                                }
     799                                        }
     800
     801                                        flags |= flag_next | flag_reproc;
     802                                        break;
     803
     804                                default:
     805                                        break;
     806                                }
     807                                ;
     808                        }
     809
     810                        if (flags & flag_reproc) {
     811                                flags &= ~flag_reproc;
     812                                --i;
     813                        }
     814
     815                        if (flags & flag_next) {
     816                                flags = (flags & ~flag_next) | flag_need_comma;
     817
     818                                if (!top->parent) {
     819                                        /* root value done */
     820
     821                                        flags |= flag_done;
     822                                        continue;
     823                                }
     824
     825                                if (top->parent->type == json_array) {
     826                                        flags |= flag_seek_value;
     827                                }
     828
     829                                if (!state.first_pass) {
     830                                        json_value * parent = top->parent;
     831
     832                                        switch (parent->type) {
     833                                        case json_object:
     834
     835                                                parent->u.object.values
     836                                                [parent->u.object.length].value = top;
     837
     838                                                break;
     839
     840                                        case json_array:
     841
     842                                                parent->u.array.values
     843                                                [parent->u.array.length] = top;
     844
     845                                                break;
     846
     847                                        default:
     848                                                break;
     849                                        }
     850                                        ;
     851                                }
     852
     853                                if ((++top->parent->u.array.length) > state.uint_max) {
     854                                        goto e_overflow;
     855                                }
     856
     857                                top = top->parent;
     858
     859                                continue;
     860                        }
     861                }
     862
     863                alloc = root;
     864        }
     865
     866        return root;
     867
     868e_unknown_value:
     869
     870        sprintf(error, "%d:%d: Unknown value", cur_line, e_off);
     871        goto e_failed;
     872
     873e_alloc_failure:
     874
     875        strcpy(error, "Memory allocation failure");
     876        goto e_failed;
     877
     878e_overflow:
     879
     880        sprintf(error, "%d:%d: Too long (caught overflow)", cur_line, e_off);
     881        goto e_failed;
     882
     883e_failed:
     884
     885        if (error_buf) {
     886                if (*error) {
     887                        strcpy(error_buf, error);
     888                } else {
     889                        strcpy(error_buf, "Unknown error");
     890                }
     891        }
     892
     893        if (state.first_pass) {
     894                alloc = root;
     895        }
     896
     897        while (alloc) {
     898                top = alloc->_reserved.next_alloc;
     899                state.settings.mem_free(alloc, state.settings.user_data);
     900                alloc = top;
     901        }
     902
     903        if (!state.first_pass) {
     904                json_value_free_ex(&state.settings, root);
     905        }
     906
     907        return 0;
    182908}
    183909
    184 #define e_off \
    185    ((int) (i - cur_line_begin))
    186 
    187 #define whitespace \
    188    case '\n': ++ cur_line;  cur_line_begin = i; \
    189    case ' ': case '\t': case '\r'
    190 
    191 #define string_add(b)  \
    192    do { if (!state.first_pass) string [string_length] = b;  ++ string_length; } while (0);
    193 
    194 static const long
    195    flag_next             = 1 << 0,
    196    flag_reproc           = 1 << 1,
    197    flag_need_comma       = 1 << 2,
    198    flag_seek_value       = 1 << 3,
    199    flag_escaped          = 1 << 4,
    200    flag_string           = 1 << 5,
    201    flag_need_colon       = 1 << 6,
    202    flag_done             = 1 << 7,
    203    flag_num_negative     = 1 << 8,
    204    flag_num_zero         = 1 << 9,
    205    flag_num_e            = 1 << 10,
    206    flag_num_e_got_sign   = 1 << 11,
    207    flag_num_e_negative   = 1 << 12,
    208    flag_line_comment     = 1 << 13,
    209    flag_block_comment    = 1 << 14;
    210 
    211 json_value * json_parse_ex (json_settings * settings,
    212                             const json_char * json,
    213                             size_t length,
    214                             char * error_buf)
     910json_value * json_parse(const json_char * json, size_t length)
    215911{
    216    json_char error [json_error_max];
    217    unsigned int cur_line;
    218    const json_char * cur_line_begin, * i, * end;
    219    json_value * top, * root, * alloc = 0;
    220    json_state state = { 0 };
    221    long flags;
    222    long num_digits = 0, num_e = 0;
    223    json_int_t num_fraction = 0;
    224 
    225    /* Skip UTF-8 BOM
    226     */
    227    if (length >= 3 && ((unsigned char) json [0]) == 0xEF
    228                    && ((unsigned char) json [1]) == 0xBB
    229                    && ((unsigned char) json [2]) == 0xBF)
    230    {
    231       json += 3;
    232       length -= 3;
    233    }
    234 
    235    error[0] = '\0';
    236    end = (json + length);
    237 
    238    memcpy (&state.settings, settings, sizeof (json_settings));
    239 
    240    if (!state.settings.mem_alloc)
    241       state.settings.mem_alloc = default_alloc;
    242 
    243    if (!state.settings.mem_free)
    244       state.settings.mem_free = default_free;
    245 
    246    memset (&state.uint_max, 0xFF, sizeof (state.uint_max));
    247    memset (&state.ulong_max, 0xFF, sizeof (state.ulong_max));
    248 
    249    state.uint_max -= 8; /* limit of how much can be added before next check */
    250    state.ulong_max -= 8;
    251 
    252    for (state.first_pass = 1; state.first_pass >= 0; -- state.first_pass)
    253    {
    254       json_uchar uchar;
    255       unsigned char uc_b1, uc_b2, uc_b3, uc_b4;
    256       json_char * string = 0;
    257       unsigned int string_length = 0;
    258 
    259       top = root = 0;
    260       flags = flag_seek_value;
    261 
    262       cur_line = 1;
    263       cur_line_begin = json;
    264 
    265       for (i = json ;; ++ i)
    266       {
    267          json_char b = (i == end ? 0 : *i);
    268          
    269          if (flags & flag_string)
    270          {
    271             if (!b)
    272             {  sprintf (error, "Unexpected EOF in string (at %d:%d)", cur_line, e_off);
    273                goto e_failed;
    274             }
    275 
    276             if (string_length > state.uint_max)
    277                goto e_overflow;
    278 
    279             if (flags & flag_escaped)
    280             {
    281                flags &= ~ flag_escaped;
    282 
    283                switch (b)
    284                {
    285                   case 'b':  string_add ('\b');  break;
    286                   case 'f':  string_add ('\f');  break;
    287                   case 'n':  string_add ('\n');  break;
    288                   case 'r':  string_add ('\r');  break;
    289                   case 't':  string_add ('\t');  break;
    290                   case 'u':
    291 
    292                     if (end - i < 4 ||
    293                         (uc_b1 = hex_value (*++ i)) == 0xFF || (uc_b2 = hex_value (*++ i)) == 0xFF
    294                           || (uc_b3 = hex_value (*++ i)) == 0xFF || (uc_b4 = hex_value (*++ i)) == 0xFF)
    295                     {
    296                         sprintf (error, "Invalid character value `%c` (at %d:%d)", b, cur_line, e_off);
    297                         goto e_failed;
    298                     }
    299 
    300                     uc_b1 = (uc_b1 << 4) | uc_b2;
    301                     uc_b2 = (uc_b3 << 4) | uc_b4;
    302                     uchar = (uc_b1 << 8) | uc_b2;
    303 
    304                     if ((uchar & 0xF800) == 0xD800) {
    305                         json_uchar uchar2;
    306                        
    307                         if (end - i < 6 || (*++ i) != '\\' || (*++ i) != 'u' ||
    308                             (uc_b1 = hex_value (*++ i)) == 0xFF || (uc_b2 = hex_value (*++ i)) == 0xFF
    309                               || (uc_b3 = hex_value (*++ i)) == 0xFF || (uc_b4 = hex_value (*++ i)) == 0xFF)
    310                         {
    311                             sprintf (error, "Invalid character value `%c` (at %d:%d)", b, cur_line, e_off);
    312                             goto e_failed;
    313                         }
    314 
    315                         uc_b1 = (uc_b1 << 4) | uc_b2;
    316                         uc_b2 = (uc_b3 << 4) | uc_b4;
    317                         uchar2 = (uc_b1 << 8) | uc_b2;
    318                        
    319                         uchar = 0x010000 | ((uchar & 0x3FF) << 10) | (uchar2 & 0x3FF);
    320                     }
    321 
    322                     if (sizeof (json_char) >= sizeof (json_uchar) || (uchar <= 0x7F))
    323                     {
    324                        string_add ((json_char) uchar);
    325                        break;
    326                     }
    327 
    328                     if (uchar <= 0x7FF)
    329                     {
    330                         if (state.first_pass)
    331                            string_length += 2;
    332                         else
    333                         {  string [string_length ++] = 0xC0 | (uchar >> 6);
    334                            string [string_length ++] = 0x80 | (uchar & 0x3F);
    335                         }
    336 
    337                         break;
    338                     }
    339 
    340                     if (uchar <= 0xFFFF) {
    341                         if (state.first_pass)
    342                            string_length += 3;
    343                         else
    344                         {  string [string_length ++] = 0xE0 | (uchar >> 12);
    345                            string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);
    346                            string [string_length ++] = 0x80 | (uchar & 0x3F);
    347                         }
    348                        
    349                         break;
    350                     }
    351 
    352                     if (state.first_pass)
    353                        string_length += 4;
    354                     else
    355                     {  string [string_length ++] = 0xF0 | (uchar >> 18);
    356                        string [string_length ++] = 0x80 | ((uchar >> 12) & 0x3F);
    357                        string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);
    358                        string [string_length ++] = 0x80 | (uchar & 0x3F);
    359                     }
    360 
    361                     break;
    362 
    363                   default:
    364                      string_add (b);
    365                };
    366 
    367                continue;
    368             }
    369 
    370             if (b == '\\')
    371             {
    372                flags |= flag_escaped;
    373                continue;
    374             }
    375 
    376             if (b == '"')
    377             {
    378                if (!state.first_pass)
    379                   string [string_length] = 0;
    380 
    381                flags &= ~ flag_string;
    382                string = 0;
    383 
    384                switch (top->type)
    385                {
    386                   case json_string:
    387 
    388                      top->u.string.length = string_length;
    389                      flags |= flag_next;
    390 
    391                      break;
    392 
    393                   case json_object:
    394 
    395                      if (state.first_pass)
    396                         (*(json_char **) &top->u.object.values) += string_length + 1;
    397                      else
    398                      { 
    399                         top->u.object.values [top->u.object.length].name
    400                            = (json_char *) top->_reserved.object_mem;
    401 
    402                         top->u.object.values [top->u.object.length].name_length
    403                            = string_length;
    404 
    405                         (*(json_char **) &top->_reserved.object_mem) += string_length + 1;
    406                      }
    407 
    408                      flags |= flag_seek_value | flag_need_colon;
    409                      continue;
    410 
    411                   default:
    412                      break;
    413                };
    414             }
    415             else
    416             {
    417                string_add (b);
    418                continue;
    419             }
    420          }
    421 
    422          if (state.settings.settings & json_enable_comments)
    423          {
    424             if (flags & (flag_line_comment | flag_block_comment))
    425             {
    426                if (flags & flag_line_comment)
    427                {
    428                   if (b == '\r' || b == '\n' || !b)
    429                   {
    430                      flags &= ~ flag_line_comment;
    431                      -- i;  /* so null can be reproc'd */
    432                   }
    433 
    434                   continue;
    435                }
    436 
    437                if (flags & flag_block_comment)
    438                {
    439                   if (!b)
    440                   {  sprintf (error, "%d:%d: Unexpected EOF in block comment", cur_line, e_off);
    441                      goto e_failed;
    442                   }
    443 
    444                   if (b == '*' && i < (end - 1) && i [1] == '/')
    445                   {
    446                      flags &= ~ flag_block_comment;
    447                      ++ i;  /* skip closing sequence */
    448                   }
    449 
    450                   continue;
    451                }
    452             }
    453             else if (b == '/')
    454             {
    455                if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object)
    456                {
    457                   sprintf (error, "%d:%d: Comment not allowed here", cur_line, e_off);
    458                   goto e_failed;
    459                }
    460 
    461                if (++ i == end)
    462                {  sprintf (error, "%d:%d: EOF unexpected", cur_line, e_off);
    463                   goto e_failed;
    464                }
    465 
    466                switch (b = *i)
    467                {
    468                   case '/':
    469                      flags |= flag_line_comment;
    470                      continue;
    471 
    472                   case '*':
    473                      flags |= flag_block_comment;
    474                      continue;
    475 
    476                   default:
    477                      sprintf (error, "%d:%d: Unexpected `%c` in comment opening sequence", cur_line, e_off, b);
    478                      goto e_failed;
    479                };
    480             }
    481          }
    482 
    483          if (flags & flag_done)
    484          {
    485             if (!b)
    486                break;
    487 
    488             switch (b)
    489             {
    490                whitespace:
    491                   continue;
    492 
    493                default:
    494                   sprintf (error, "%d:%d: Trailing garbage: `%c`", cur_line, e_off, b);
    495                   goto e_failed;
    496             };
    497          }
    498 
    499          if (flags & flag_seek_value)
    500          {
    501             switch (b)
    502             {
    503                whitespace:
    504                   continue;
    505 
    506                case ']':
    507 
    508                   if (top->type == json_array)
    509                      flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next;
    510                   else
    511                   {  sprintf (error, "%d:%d: Unexpected ]", cur_line, e_off);
    512                      goto e_failed;
    513                   }
    514 
    515                   break;
    516 
    517                default:
    518 
    519                   if (flags & flag_need_comma)
    520                   {
    521                      if (b == ',')
    522                      {  flags &= ~ flag_need_comma;
    523                         continue;
    524                      }
    525                      else
    526                      {  sprintf (error, "%d:%d: Expected , before %c", cur_line, e_off, b);
    527                         goto e_failed;
    528                      }
    529                   }
    530 
    531                   if (flags & flag_need_colon)
    532                   {
    533                      if (b == ':')
    534                      {  flags &= ~ flag_need_colon;
    535                         continue;
    536                      }
    537                      else
    538                      {  sprintf (error, "%d:%d: Expected : before %c", cur_line, e_off, b);
    539                         goto e_failed;
    540                      }
    541                   }
    542 
    543                   flags &= ~ flag_seek_value;
    544 
    545                   switch (b)
    546                   {
    547                      case '{':
    548 
    549                         if (!new_value (&state, &top, &root, &alloc, json_object))
    550                            goto e_alloc_failure;
    551 
    552                         continue;
    553 
    554                      case '[':
    555 
    556                         if (!new_value (&state, &top, &root, &alloc, json_array))
    557                            goto e_alloc_failure;
    558 
    559                         flags |= flag_seek_value;
    560                         continue;
    561 
    562                      case '"':
    563 
    564                         if (!new_value (&state, &top, &root, &alloc, json_string))
    565                            goto e_alloc_failure;
    566 
    567                         flags |= flag_string;
    568 
    569                         string = top->u.string.ptr;
    570                         string_length = 0;
    571 
    572                         continue;
    573 
    574                      case 't':
    575 
    576                         if ((end - i) < 3 || *(++ i) != 'r' || *(++ i) != 'u' || *(++ i) != 'e')
    577                            goto e_unknown_value;
    578 
    579                         if (!new_value (&state, &top, &root, &alloc, json_boolean))
    580                            goto e_alloc_failure;
    581 
    582                         top->u.boolean = 1;
    583 
    584                         flags |= flag_next;
    585                         break;
    586 
    587                      case 'f':
    588 
    589                         if ((end - i) < 4 || *(++ i) != 'a' || *(++ i) != 'l' || *(++ i) != 's' || *(++ i) != 'e')
    590                            goto e_unknown_value;
    591 
    592                         if (!new_value (&state, &top, &root, &alloc, json_boolean))
    593                            goto e_alloc_failure;
    594 
    595                         flags |= flag_next;
    596                         break;
    597 
    598                      case 'n':
    599 
    600                         if ((end - i) < 3 || *(++ i) != 'u' || *(++ i) != 'l' || *(++ i) != 'l')
    601                            goto e_unknown_value;
    602 
    603                         if (!new_value (&state, &top, &root, &alloc, json_null))
    604                            goto e_alloc_failure;
    605 
    606                         flags |= flag_next;
    607                         break;
    608 
    609                      default:
    610 
    611                         if (g_ascii_isdigit (b) || b == '-')
    612                         {
    613                            if (!new_value (&state, &top, &root, &alloc, json_integer))
    614                               goto e_alloc_failure;
    615 
    616                            if (!state.first_pass)
    617                            {
    618                               while (g_ascii_isdigit (b) || b == '+' || b == '-'
    619                                         || b == 'e' || b == 'E' || b == '.')
    620                               {
    621                                  if ( (++ i) == end)
    622                                  {
    623                                     b = 0;
    624                                     break;
    625                                  }
    626 
    627                                  b = *i;
    628                               }
    629 
    630                               flags |= flag_next | flag_reproc;
    631                               break;
    632                            }
    633 
    634                            flags &= ~ (flag_num_negative | flag_num_e |
    635                                         flag_num_e_got_sign | flag_num_e_negative |
    636                                            flag_num_zero);
    637 
    638                            num_digits = 0;
    639                            num_fraction = 0;
    640                            num_e = 0;
    641 
    642                            if (b != '-')
    643                            {
    644                               flags |= flag_reproc;
    645                               break;
    646                            }
    647 
    648                            flags |= flag_num_negative;
    649                            continue;
    650                         }
    651                         else
    652                         {  sprintf (error, "%d:%d: Unexpected %c when seeking value", cur_line, e_off, b);
    653                            goto e_failed;
    654                         }
    655                   };
    656             };
    657          }
    658          else
    659          {
    660             switch (top->type)
    661             {
    662             case json_object:
    663                
    664                switch (b)
    665                {
    666                   whitespace:
    667                      continue;
    668 
    669                   case '"':
    670 
    671                      if (flags & flag_need_comma)
    672                      {
    673                         sprintf (error, "%d:%d: Expected , before \"", cur_line, e_off);
    674                         goto e_failed;
    675                      }
    676 
    677                      flags |= flag_string;
    678 
    679                      string = (json_char *) top->_reserved.object_mem;
    680                      string_length = 0;
    681 
    682                      break;
    683                  
    684                   case '}':
    685 
    686                      flags = (flags & ~ flag_need_comma) | flag_next;
    687                      break;
    688 
    689                   case ',':
    690 
    691                      if (flags & flag_need_comma)
    692                      {
    693                         flags &= ~ flag_need_comma;
    694                         break;
    695                      }
    696 
    697                   default:
    698 
    699                      sprintf (error, "%d:%d: Unexpected `%c` in object", cur_line, e_off, b);
    700                      goto e_failed;
    701                };
    702 
    703                break;
    704 
    705             case json_integer:
    706             case json_double:
    707 
    708                if (g_ascii_isdigit (b))
    709                {
    710                   ++ num_digits;
    711 
    712                   if (top->type == json_integer || flags & flag_num_e)
    713                   {
    714                      if (! (flags & flag_num_e))
    715                      {
    716                         if (flags & flag_num_zero)
    717                         {  sprintf (error, "%d:%d: Unexpected `0` before `%c`", cur_line, e_off, b);
    718                            goto e_failed;
    719                         }
    720 
    721                         if (num_digits == 1 && b == '0')
    722                            flags |= flag_num_zero;
    723                      }
    724                      else
    725                      {
    726                         flags |= flag_num_e_got_sign;
    727                         num_e = (num_e * 10) + (b - '0');
    728                         continue;
    729                      }
    730 
    731                      top->u.integer = (top->u.integer * 10) + (b - '0');
    732                      continue;
    733                   }
    734 
    735                   num_fraction = (num_fraction * 10) + (b - '0');
    736                   continue;
    737                }
    738 
    739                if (b == '+' || b == '-')
    740                {
    741                   if ( (flags & flag_num_e) && !(flags & flag_num_e_got_sign))
    742                   {
    743                      flags |= flag_num_e_got_sign;
    744 
    745                      if (b == '-')
    746                         flags |= flag_num_e_negative;
    747 
    748                      continue;
    749                   }
    750                }
    751                else if (b == '.' && top->type == json_integer)
    752                {
    753                   if (!num_digits)
    754                   {  sprintf (error, "%d:%d: Expected digit before `.`", cur_line, e_off);
    755                      goto e_failed;
    756                   }
    757 
    758                   top->type = json_double;
    759                   top->u.dbl = (double) top->u.integer;
    760 
    761                   num_digits = 0;
    762                   continue;
    763                }
    764 
    765                if (! (flags & flag_num_e))
    766                {
    767                   if (top->type == json_double)
    768                   {
    769                      if (!num_digits)
    770                      {  sprintf (error, "%d:%d: Expected digit after `.`", cur_line, e_off);
    771                         goto e_failed;
    772                      }
    773 
    774                      top->u.dbl += ((double) num_fraction) / (pow (10, (double) num_digits));
    775                   }
    776 
    777                   if (b == 'e' || b == 'E')
    778                   {
    779                      flags |= flag_num_e;
    780 
    781                      if (top->type == json_integer)
    782                      {
    783                         top->type = json_double;
    784                         top->u.dbl = (double) top->u.integer;
    785                      }
    786 
    787                      num_digits = 0;
    788                      flags &= ~ flag_num_zero;
    789 
    790                      continue;
    791                   }
    792                }
    793                else
    794                {
    795                   if (!num_digits)
    796                   {  sprintf (error, "%d:%d: Expected digit after `e`", cur_line, e_off);
    797                      goto e_failed;
    798                   }
    799 
    800                   top->u.dbl *= pow (10, (double) (flags & flag_num_e_negative ? - num_e : num_e));
    801                }
    802 
    803                if (flags & flag_num_negative)
    804                {
    805                   if (top->type == json_integer)
    806                      top->u.integer = - top->u.integer;
    807                   else
    808                      top->u.dbl = - top->u.dbl;
    809                }
    810 
    811                flags |= flag_next | flag_reproc;
    812                break;
    813 
    814             default:
    815                break;
    816             };
    817          }
    818 
    819          if (flags & flag_reproc)
    820          {
    821             flags &= ~ flag_reproc;
    822             -- i;
    823          }
    824 
    825          if (flags & flag_next)
    826          {
    827             flags = (flags & ~ flag_next) | flag_need_comma;
    828 
    829             if (!top->parent)
    830             {
    831                /* root value done */
    832 
    833                flags |= flag_done;
    834                continue;
    835             }
    836 
    837             if (top->parent->type == json_array)
    838                flags |= flag_seek_value;
    839                
    840             if (!state.first_pass)
    841             {
    842                json_value * parent = top->parent;
    843 
    844                switch (parent->type)
    845                {
    846                   case json_object:
    847 
    848                      parent->u.object.values
    849                         [parent->u.object.length].value = top;
    850 
    851                      break;
    852 
    853                   case json_array:
    854 
    855                      parent->u.array.values
    856                            [parent->u.array.length] = top;
    857 
    858                      break;
    859 
    860                   default:
    861                      break;
    862                };
    863             }
    864 
    865             if ( (++ top->parent->u.array.length) > state.uint_max)
    866                goto e_overflow;
    867 
    868             top = top->parent;
    869 
    870             continue;
    871          }
    872       }
    873 
    874       alloc = root;
    875    }
    876 
    877    return root;
    878 
    879 e_unknown_value:
    880 
    881    sprintf (error, "%d:%d: Unknown value", cur_line, e_off);
    882    goto e_failed;
    883 
    884 e_alloc_failure:
    885 
    886    strcpy (error, "Memory allocation failure");
    887    goto e_failed;
    888 
    889 e_overflow:
    890 
    891    sprintf (error, "%d:%d: Too long (caught overflow)", cur_line, e_off);
    892    goto e_failed;
    893 
    894 e_failed:
    895 
    896    if (error_buf)
    897    {
    898       if (*error)
    899          strcpy (error_buf, error);
    900       else
    901          strcpy (error_buf, "Unknown error");
    902    }
    903 
    904    if (state.first_pass)
    905       alloc = root;
    906 
    907    while (alloc)
    908    {
    909       top = alloc->_reserved.next_alloc;
    910       state.settings.mem_free (alloc, state.settings.user_data);
    911       alloc = top;
    912    }
    913 
    914    if (!state.first_pass)
    915       json_value_free_ex (&state.settings, root);
    916 
    917    return 0;
     912        json_settings settings = { 0 };
     913
     914        return json_parse_ex(&settings, json, length, 0);
    918915}
    919916
    920 json_value * json_parse (const json_char * json, size_t length)
     917void json_value_free_ex(json_settings * settings, json_value * value)
    921918{
    922    json_settings settings = { 0 };
    923    return json_parse_ex (&settings, json, length, 0);
     919        json_value * cur_value;
     920
     921        if (!value) {
     922                return;
     923        }
     924
     925        value->parent = 0;
     926
     927        while (value) {
     928                switch (value->type) {
     929                case json_array:
     930
     931                        if (!value->u.array.length) {
     932                                settings->mem_free(value->u.array.values, settings->user_data);
     933                                break;
     934                        }
     935
     936                        value = value->u.array.values [--value->u.array.length];
     937                        continue;
     938
     939                case json_object:
     940
     941                        if (!value->u.object.length) {
     942                                settings->mem_free(value->u.object.values, settings->user_data);
     943                                break;
     944                        }
     945
     946                        value = value->u.object.values [--value->u.object.length].value;
     947                        continue;
     948
     949                case json_string:
     950
     951                        settings->mem_free(value->u.string.ptr, settings->user_data);
     952                        break;
     953
     954                default:
     955                        break;
     956                }
     957                ;
     958
     959                cur_value = value;
     960                value = value->parent;
     961                settings->mem_free(cur_value, settings->user_data);
     962        }
    924963}
    925964
    926 void json_value_free_ex (json_settings * settings, json_value * value)
     965void json_value_free(json_value * value)
    927966{
    928    json_value * cur_value;
    929 
    930    if (!value)
    931       return;
    932 
    933    value->parent = 0;
    934 
    935    while (value)
    936    {
    937       switch (value->type)
    938       {
    939          case json_array:
    940 
    941             if (!value->u.array.length)
    942             {
    943                settings->mem_free (value->u.array.values, settings->user_data);
    944                break;
    945             }
    946 
    947             value = value->u.array.values [-- value->u.array.length];
    948             continue;
    949 
    950          case json_object:
    951 
    952             if (!value->u.object.length)
    953             {
    954                settings->mem_free (value->u.object.values, settings->user_data);
    955                break;
    956             }
    957 
    958             value = value->u.object.values [-- value->u.object.length].value;
    959             continue;
    960 
    961          case json_string:
    962 
    963             settings->mem_free (value->u.string.ptr, settings->user_data);
    964             break;
    965 
    966          default:
    967             break;
    968       };
    969 
    970       cur_value = value;
    971       value = value->parent;
    972       settings->mem_free (cur_value, settings->user_data);
    973    }
     967        json_settings settings = { 0 };
     968
     969        settings.mem_free = default_free;
     970        json_value_free_ex(&settings, value);
    974971}
    975972
    976 void json_value_free (json_value * value)
    977 {
    978    json_settings settings = { 0 };
    979    settings.mem_free = default_free;
    980    json_value_free_ex (&settings, value);
    981 }
    982 
  • lib/json.h

    raf359b4 r5ebff60  
    5151   #include <string.h>
    5252
    53    extern "C"
    54    {
    55 
    56 #endif
    57 
    58 typedef struct
     53extern "C"
    5954{
    60    unsigned long max_memory;
    61    int settings;
    62 
    63    /* Custom allocator support (leave null to use malloc/free)
    64     */
    65 
    66    void * (* mem_alloc) (size_t, int zero, void * user_data);
    67    void (* mem_free) (void *, void * user_data);
    68 
    69    void * user_data;  /* will be passed to mem_alloc and mem_free */
     55
     56#endif
     57
     58typedef struct {
     59        unsigned long max_memory;
     60        int settings;
     61
     62        /* Custom allocator support (leave null to use malloc/free)
     63         */
     64
     65        void * (*mem_alloc)(size_t, int zero, void * user_data);
     66        void (* mem_free)(void *, void * user_data);
     67
     68        void * user_data; /* will be passed to mem_alloc and mem_free */
    7069
    7170} json_settings;
     
    7372#define json_enable_comments  0x01
    7473
    75 typedef enum
    76 {
    77    json_none,
    78    json_object,
    79    json_array,
    80    json_integer,
    81    json_double,
    82    json_string,
    83    json_boolean,
    84    json_null
     74typedef enum {
     75        json_none,
     76        json_object,
     77        json_array,
     78        json_integer,
     79        json_double,
     80        json_string,
     81        json_boolean,
     82        json_null
    8583
    8684} json_type;
     
    8886extern const struct _json_value json_value_none;
    8987
    90 typedef struct _json_value
    91 {
    92    struct _json_value * parent;
    93 
    94    json_type type;
    95 
    96    union
    97    {
    98       int boolean;
    99       json_int_t integer;
    100       double dbl;
    101 
    102       struct
    103       {
    104          unsigned int length;
    105          json_char * ptr; /* null terminated */
    106 
    107       } string;
    108 
    109       struct
    110       {
    111          unsigned int length;
    112 
    113          struct
    114          {
    115             json_char * name;
    116             unsigned int name_length;
    117 
    118             struct _json_value * value;
    119 
    120          } * values;
    121 
    122          #if defined(__cplusplus) && __cplusplus >= 201103L
    123          decltype(values) begin () const
    124          {  return values;
    125          }
    126          decltype(values) end () const
    127          {  return values + length;
    128          }
    129          #endif
    130 
    131       } object;
    132 
    133       struct
    134       {
    135          unsigned int length;
    136          struct _json_value ** values;
    137 
    138          #if defined(__cplusplus) && __cplusplus >= 201103L
    139          decltype(values) begin () const
    140          {  return values;
    141          }
    142          decltype(values) end () const
    143          {  return values + length;
    144          }
    145          #endif
    146 
    147       } array;
    148 
    149    } u;
    150 
    151    union
    152    {
    153       struct _json_value * next_alloc;
    154       void * object_mem;
    155 
    156    } _reserved;
    157 
    158 
    159    /* Some C++ operator sugar */
     88typedef struct _json_value {
     89        struct _json_value * parent;
     90
     91        json_type type;
     92
     93        union {
     94                int boolean;
     95                json_int_t integer;
     96                double dbl;
     97
     98                struct {
     99                        unsigned int length;
     100                        json_char * ptr; /* null terminated */
     101
     102                } string;
     103
     104                struct {
     105                        unsigned int length;
     106
     107                        struct {
     108                                json_char * name;
     109                                unsigned int name_length;
     110
     111                                struct _json_value * value;
     112
     113                        } * values;
     114
     115         #if defined(__cplusplus) && __cplusplus >= 201103L
     116                        decltype(values) begin() const
     117                        {  return values; }
     118                        decltype(values) end() const
     119                        {  return values + length; }
     120         #endif
     121
     122                } object;
     123
     124                struct {
     125                        unsigned int length;
     126                        struct _json_value ** values;
     127
     128         #if defined(__cplusplus) && __cplusplus >= 201103L
     129                        decltype(values) begin() const
     130                        {  return values; }
     131                        decltype(values) end() const
     132                        {  return values + length; }
     133         #endif
     134
     135                } array;
     136
     137        } u;
     138
     139        union {
     140                struct _json_value * next_alloc;
     141                void * object_mem;
     142
     143        } _reserved;
     144
     145
     146        /* Some C++ operator sugar */
    160147
    161148   #ifdef __cplusplus
    162149
    163       public:
    164 
    165          inline _json_value ()
    166          {  memset (this, 0, sizeof (_json_value));
    167          }
    168 
    169          inline const struct _json_value &operator [] (int index) const
    170          {
    171             if (type != json_array || index < 0
    172                      || ((unsigned int) index) >= u.array.length)
    173             {
    174                return json_value_none;
    175             }
    176 
    177             return *u.array.values [index];
    178          }
    179 
    180          inline const struct _json_value &operator [] (const char * index) const
    181          {
    182             if (type != json_object)
    183                return json_value_none;
    184 
    185             for (unsigned int i = 0; i < u.object.length; ++ i)
    186                if (!strcmp (u.object.values [i].name, index))
    187                   return *u.object.values [i].value;
    188 
    189             return json_value_none;
    190          }
    191 
    192          inline operator const char * () const
    193          { 
    194             switch (type)
    195             {
    196                case json_string:
    197                   return u.string.ptr;
    198 
    199                default:
    200                   return "";
    201             };
    202          }
    203 
    204          inline operator json_int_t () const
    205          { 
    206             switch (type)
    207             {
    208                case json_integer:
    209                   return u.integer;
    210 
    211                case json_double:
    212                   return (json_int_t) u.dbl;
    213 
    214                default:
    215                   return 0;
    216             };
    217          }
    218 
    219          inline operator bool () const
    220          { 
    221             if (type != json_boolean)
    222                return false;
    223 
    224             return u.boolean != 0;
    225          }
    226 
    227          inline operator double () const
    228          { 
    229             switch (type)
    230             {
    231                case json_integer:
    232                   return (double) u.integer;
    233 
    234                case json_double:
    235                   return u.dbl;
    236 
    237                default:
    238                   return 0;
    239             };
    240          }
     150public:
     151
     152        inline _json_value ()
     153        {
     154                memset(this, 0, sizeof(_json_value));
     155        }
     156
     157        inline const struct _json_value &operator [](int index) const
     158        {
     159                if (type != json_array || index < 0
     160                    || ((unsigned int)index) >= u.array.length) {
     161                        return json_value_none;
     162                }
     163
     164                return *u.array.values [index];
     165        }
     166
     167        inline const struct _json_value &operator [](const char * index) const
     168        {
     169                if (type != json_object) {
     170                        return json_value_none;
     171                }
     172
     173                for (unsigned int i = 0; i < u.object.length; ++i) {
     174                        if (!strcmp(u.object.values [i].name, index)) {
     175                                return *u.object.values [i].value;
     176                        }
     177                }
     178
     179                return json_value_none;
     180        }
     181
     182        inline operator const char *() const
     183        {
     184                switch (type) {
     185                case json_string:
     186                        return u.string.ptr;
     187
     188                default:
     189                        return "";
     190                }
     191                ;
     192        }
     193
     194        inline operator json_int_t() const
     195        {
     196                switch (type) {
     197                case json_integer:
     198                        return u.integer;
     199
     200                case json_double:
     201                        return (json_int_t)u.dbl;
     202
     203                default:
     204                        return 0;
     205                }
     206                ;
     207        }
     208
     209        inline operator bool() const
     210        {
     211                if (type != json_boolean) {
     212                        return false;
     213                }
     214
     215                return u.boolean != 0;
     216        }
     217
     218        inline operator double() const
     219        {
     220                switch (type) {
     221                case json_integer:
     222                        return (double)u.integer;
     223
     224                case json_double:
     225                        return u.dbl;
     226
     227                default:
     228                        return 0;
     229                }
     230                ;
     231        }
    241232
    242233   #endif
     
    244235} json_value;
    245236
    246 json_value * json_parse (const json_char * json,
    247                          size_t length);
     237json_value * json_parse(const json_char * json,
     238                        size_t length);
    248239
    249240#define json_error_max 128
    250 json_value * json_parse_ex (json_settings * settings,
    251                             const json_char * json,
    252                             size_t length,
    253                             char * error);
    254 
    255 void json_value_free (json_value *);
     241json_value * json_parse_ex(json_settings * settings,
     242                           const json_char * json,
     243                           size_t length,
     244                           char * error);
     245
     246void json_value_free(json_value *);
    256247
    257248
     
    259250 * use a custom mem_free.
    260251 */
    261 void json_value_free_ex (json_settings * settings,
    262                          json_value *);
     252void json_value_free_ex(json_settings * settings,
     253                        json_value *);
    263254
    264255
    265256#ifdef __cplusplus
    266    } /* extern "C" */
    267 #endif
    268 
    269 #endif
    270 
    271 
     257}    /* extern "C" */
     258#endif
     259
     260#endif
     261
     262
  • lib/json_util.c

    raf359b4 r5ebff60  
    2828#include "json_util.h"
    2929
    30 json_value *json_o_get( const json_value *obj, const json_char *name )
    31 { 
     30json_value *json_o_get(const json_value *obj, const json_char *name)
     31{
    3232        int i;
    33        
    34         if( !obj || obj->type != json_object )
     33
     34        if (!obj || obj->type != json_object) {
    3535                return NULL;
     36        }
    3637
    37         for( i = 0; i < obj->u.object.length; ++ i)
    38                 if( strcmp( obj->u.object.values[i].name, name ) == 0 )
     38        for (i = 0; i < obj->u.object.length; ++i) {
     39                if (strcmp(obj->u.object.values[i].name, name) == 0) {
    3940                        return obj->u.object.values[i].value;
     41                }
     42        }
    4043
    4144        return NULL;
    4245}
    4346
    44 const char *json_o_str( const json_value *obj, const json_char *name )
    45 { 
    46         json_value *ret = json_o_get( obj, name );
    47        
    48         if( ret && ret->type == json_string )
     47const char *json_o_str(const json_value *obj, const json_char *name)
     48{
     49        json_value *ret = json_o_get(obj, name);
     50
     51        if (ret && ret->type == json_string) {
    4952                return ret->u.string.ptr;
    50         else
     53        } else {
    5154                return NULL;
     55        }
    5256}
    5357
    54 char *json_o_strdup( const json_value *obj, const json_char *name )
     58char *json_o_strdup(const json_value *obj, const json_char *name)
    5559{
    56         json_value *ret = json_o_get( obj, name );
    57        
    58         if( ret && ret->type == json_string && ret->u.string.ptr )
    59                 return g_memdup( ret->u.string.ptr, ret->u.string.length + 1 );
    60         else
     60        json_value *ret = json_o_get(obj, name);
     61
     62        if (ret && ret->type == json_string && ret->u.string.ptr) {
     63                return g_memdup(ret->u.string.ptr, ret->u.string.length + 1);
     64        } else {
    6165                return NULL;
     66        }
    6267}
  • lib/json_util.h

    raf359b4 r5ebff60  
    2626#define JSON_O_FOREACH(o, k, v) \
    2727        char *k; json_value *v; int __i; \
    28         for( __i = 0; ( __i < (o)->u.object.length ) && \
    29                       ( k = (o)->u.object.values[__i].name ) && \
    30                       ( v = (o)->u.object.values[__i].value ); \
    31                       __i ++ )
     28        for (__i = 0; (__i < (o)->u.object.length) && \
     29             (k = (o)->u.object.values[__i].name) && \
     30             (v = (o)->u.object.values[__i].value); \
     31             __i ++)
    3232
    33 json_value *json_o_get( const json_value *obj, const json_char *name );
    34 const char *json_o_str( const json_value *obj, const json_char *name );
    35 char *json_o_strdup( const json_value *obj, const json_char *name );
     33json_value *json_o_get(const json_value *obj, const json_char *name);
     34const char *json_o_str(const json_value *obj, const json_char *name);
     35char *json_o_strdup(const json_value *obj, const json_char *name);
  • lib/md5.c

    raf359b4 r5ebff60  
    1919{
    2020        gsize digest_len = MD5_HASH_SIZE;
     21
    2122        g_checksum_get_digest(*ctx, digest, &digest_len);
    2223        g_checksum_free(*ctx);
     
    2829{
    2930        md5_state_t copy = g_checksum_copy(*ctx);
     31
    3032        md5_finish(&copy, digest);
    3133}
  • lib/misc.c

    raf359b4 r5ebff60  
    1   /********************************************************************\
     1/********************************************************************\
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
     
    5555        gchar *text2 = g_malloc(strlen(text) + 1);
    5656
    57         for (i = 0, j = 0; text[i]; i++)
    58                 if (text[i] != '\r')
     57        for (i = 0, j = 0; text[i]; i++) {
     58                if (text[i] != '\r') {
    5959                        text2[j++] = text[i];
     60                }
     61        }
    6062        text2[j] = '\0';
    6163
     
    7577        tm.tm_min = min;
    7678        tm.tm_sec = sec >= 0 ? sec : time(NULL) % 60;
    77        
     79
    7880        return mktime(&tm);
    7981}
    8082
    81 time_t mktime_utc( struct tm *tp )
     83time_t mktime_utc(struct tm *tp)
    8284{
    8385        struct tm utc;
    8486        time_t res, tres;
    85        
     87
    8688        tp->tm_isdst = -1;
    87         res = mktime( tp );
     89        res = mktime(tp);
    8890        /* Problem is, mktime() just gave us the GMT timestamp for the
    8991           given local time... While the given time WAS NOT local. So
    9092           we should fix this now.
    91            
     93
    9294           Now I could choose between messing with environment variables
    9395           (kludgy) or using timegm() (not portable)... Or doing the
    9496           following, which I actually prefer...
    95            
     97
    9698           tzset() may also work but in other places I actually want to
    9799           use local time.
    98            
     100
    99101           FFFFFFFFFFFFFFFFFFFFFUUUUUUUUUUUUUUUUUUUU!! */
    100         gmtime_r( &res, &utc );
     102        gmtime_r(&res, &utc);
    101103        utc.tm_isdst = -1;
    102         if( utc.tm_hour == tp->tm_hour && utc.tm_min == tp->tm_min )
     104        if (utc.tm_hour == tp->tm_hour && utc.tm_min == tp->tm_min) {
    103105                /* Sweet! We're in UTC right now... */
    104106                return res;
    105        
    106         tres = mktime( &utc );
     107        }
     108
     109        tres = mktime(&utc);
    107110        res += res - tres;
    108        
     111
    109112        /* Yes, this is a hack. And it will go wrong around DST changes.
    110113           BUT this is more likely to be threadsafe than messing with
    111114           environment variables, and possibly more portable... */
    112        
     115
    113116        return res;
    114117}
    115118
    116 typedef struct htmlentity
    117 {
     119typedef struct htmlentity {
    118120        char code[7];
    119121        char is[3];
     
    151153};
    152154
    153 void strip_html( char *in )
     155void strip_html(char *in)
    154156{
    155157        char *start = in;
    156         char out[strlen(in)+1];
     158        char out[strlen(in) + 1];
    157159        char *s = out, *cs;
    158160        int i, matched;
    159161        int taglen;
    160        
    161         memset( out, 0, sizeof( out ) );
    162        
    163         while( *in )
    164         {
    165                 if( *in == '<' && ( g_ascii_isalpha( *(in+1) ) || *(in+1) == '/' ) )
    166                 {
     162
     163        memset(out, 0, sizeof(out));
     164
     165        while (*in) {
     166                if (*in == '<' && (g_ascii_isalpha(*(in + 1)) || *(in + 1) == '/')) {
    167167                        /* If in points at a < and in+1 points at a letter or a slash, this is probably
    168168                           a HTML-tag. Try to find a closing > and continue there. If the > can't be
    169169                           found, assume that it wasn't a HTML-tag after all. */
    170                        
     170
    171171                        cs = in;
    172                        
    173                         while( *in && *in != '>' )
    174                                 in ++;
    175                        
     172
     173                        while (*in && *in != '>') {
     174                                in++;
     175                        }
     176
    176177                        taglen = in - cs - 1;   /* not <0 because the above loop runs at least once */
    177                         if( *in )
    178                         {
    179                                 if( g_strncasecmp( cs+1, "b", taglen) == 0 )
     178                        if (*in) {
     179                                if (g_strncasecmp(cs + 1, "b", taglen) == 0) {
    180180                                        *(s++) = '\x02';
    181                                 else if( g_strncasecmp( cs+1, "/b", taglen) == 0 )
     181                                } else if (g_strncasecmp(cs + 1, "/b", taglen) == 0) {
    182182                                        *(s++) = '\x02';
    183                                 else if( g_strncasecmp( cs+1, "i", taglen) == 0 )
     183                                } else if (g_strncasecmp(cs + 1, "i", taglen) == 0) {
    184184                                        *(s++) = '\x1f';
    185                                 else if( g_strncasecmp( cs+1, "/i", taglen) == 0 )
     185                                } else if (g_strncasecmp(cs + 1, "/i", taglen) == 0) {
    186186                                        *(s++) = '\x1f';
    187                                 else if( g_strncasecmp( cs+1, "br", taglen) == 0 )
     187                                } else if (g_strncasecmp(cs + 1, "br", taglen) == 0) {
    188188                                        *(s++) = '\n';
    189                                 in ++;
    190                         }
    191                         else
    192                         {
     189                                }
     190                                in++;
     191                        } else {
    193192                                in = cs;
    194193                                *(s++) = *(in++);
    195194                        }
    196                 }
    197                 else if( *in == '&' )
    198                 {
     195                } else if (*in == '&') {
    199196                        cs = ++in;
    200                         while( *in && g_ascii_isalpha( *in ) )
    201                                 in ++;
    202                        
    203                         if( *in == ';' ) in ++;
     197                        while (*in && g_ascii_isalpha(*in)) {
     198                                in++;
     199                        }
     200
     201                        if (*in == ';') {
     202                                in++;
     203                        }
    204204                        matched = 0;
    205                        
    206                         for( i = 0; *ent[i].code; i ++ )
    207                                 if( g_strncasecmp( ent[i].code, cs, strlen( ent[i].code ) ) == 0 )
    208                                 {
     205
     206                        for (i = 0; *ent[i].code; i++) {
     207                                if (g_strncasecmp(ent[i].code, cs, strlen(ent[i].code)) == 0) {
    209208                                        int j;
    210                                        
    211                                         for( j = 0; ent[i].is[j]; j ++ )
     209
     210                                        for (j = 0; ent[i].is[j]; j++) {
    212211                                                *(s++) = ent[i].is[j];
    213                                        
     212                                        }
     213
    214214                                        matched = 1;
    215215                                        break;
    216216                                }
     217                        }
    217218
    218219                        /* None of the entities were matched, so return the string */
    219                         if( !matched )
    220                         {
     220                        if (!matched) {
    221221                                in = cs - 1;
    222222                                *(s++) = *(in++);
    223223                        }
    224                 }
    225                 else
    226                 {
     224                } else {
    227225                        *(s++) = *(in++);
    228226                }
    229227        }
    230        
    231         strcpy( start, out );
    232 }
    233 
    234 char *escape_html( const char *html )
     228
     229        strcpy(start, out);
     230}
     231
     232char *escape_html(const char *html)
    235233{
    236234        const char *c = html;
    237235        GString *ret;
    238236        char *str;
    239        
    240         if( html == NULL )
    241                 return( NULL );
    242        
    243         ret = g_string_new( "" );
    244        
    245         while( *c )
    246         {
    247                 switch( *c )
    248                 {
    249                         case '&':
    250                                 ret = g_string_append( ret, "&amp;" );
    251                                 break;
    252                         case '<':
    253                                 ret = g_string_append( ret, "&lt;" );
    254                                 break;
    255                         case '>':
    256                                 ret = g_string_append( ret, "&gt;" );
    257                                 break;
    258                         case '"':
    259                                 ret = g_string_append( ret, "&quot;" );
    260                                 break;
    261                         default:
    262                                 ret = g_string_append_c( ret, *c );
    263                 }
    264                 c ++;
    265         }
    266        
     237
     238        if (html == NULL) {
     239                return(NULL);
     240        }
     241
     242        ret = g_string_new("");
     243
     244        while (*c) {
     245                switch (*c) {
     246                case '&':
     247                        ret = g_string_append(ret, "&amp;");
     248                        break;
     249                case '<':
     250                        ret = g_string_append(ret, "&lt;");
     251                        break;
     252                case '>':
     253                        ret = g_string_append(ret, "&gt;");
     254                        break;
     255                case '"':
     256                        ret = g_string_append(ret, "&quot;");
     257                        break;
     258                default:
     259                        ret = g_string_append_c(ret, *c);
     260                }
     261                c++;
     262        }
     263
    267264        str = ret->str;
    268         g_string_free( ret, FALSE );
    269         return( str );
     265        g_string_free(ret, FALSE);
     266        return(str);
    270267}