Changeset 5ebff60 for lib/http_client.c


Ignore:
Timestamp:
2015-02-20T22:50:54Z (9 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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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}
Note: See TracChangeset for help on using the changeset viewer.