Changeset 6e9ae72 for lib


Ignore:
Timestamp:
2011-12-17T13:50:01Z (8 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
18c6d36
Parents:
87dddee (diff), 17f057d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Mainline merge.

Location:
lib
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • lib/http_client.c

    r87dddee r6e9ae72  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2005 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2011 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    6969        req->request_length = strlen( request );
    7070        req->redir_ttl = 3;
     71       
     72        if( getenv( "BITLBEE_DEBUG" ) )
     73                printf( "About to send HTTP request:\n%s\n", req->request );
    7174       
    7275        return( req );
     
    240243                                 http_incoming_data, req );
    241244       
    242         return FALSE;
     245        if( ssl_pending( req->ssl ) )
     246                return http_incoming_data( data, source, cond );
     247        else
     248                return FALSE;
    243249
    244250got_reply:
     
    275281       
    276282        *end1 = 0;
     283       
     284        if( getenv( "BITLBEE_DEBUG" ) )
     285                printf( "HTTP response headers:\n%s\n", req->reply_headers );
    277286       
    278287        if( evil_server )
     
    314323        }
    315324       
    316         if( ( req->status_code == 301 || req->status_code == 302 ) && req->redir_ttl-- > 0 )
     325        if( ( ( req->status_code >= 301 && req->status_code <= 303 ) ||
     326              req->status_code == 307 ) && req->redir_ttl-- > 0 )
    317327        {
    318328                char *loc, *new_request, *new_host;
     
    354364                        url_t *url;
    355365                        char *s;
     366                        const char *new_method;
    356367                       
    357368                        s = strstr( loc, "\r\n" );
     
    369380                        }
    370381                       
    371                         /* Okay, this isn't fun! We have to rebuild the request... :-( */
    372                         new_request = g_malloc( req->request_length + strlen( url->file ) );
    373                        
    374                         /* So, now I just allocated enough memory, so I'm
    375                            going to use strcat(), whether you like it or not. :-) */
    376                        
    377                         sprintf( new_request, "GET %s HTTP/1.0", url->file );
    378                        
    379                         s = strstr( req->request, "\r\n" );
    380                         if( s == NULL )
     382                        /* Find all headers and, if necessary, the POST request contents.
     383                           Skip the old Host: header though. This crappy code here means
     384                           anything using this http_client MUST put the Host: header at
     385                           the top. */
     386                        if( !( ( s = strstr( req->request, "\r\nHost: " ) ) &&
     387                               ( s = strstr( s + strlen( "\r\nHost: " ), "\r\n" ) ) ) )
    381388                        {
    382389                                req->status_string = g_strdup( "Error while rebuilding request string" );
    383                                 g_free( new_request );
    384390                                g_free( url );
    385391                                goto cleanup;
    386392                        }
    387393                       
    388                         strcat( new_request, s );
     394                        /* More or less HTTP/1.0 compliant, from my reading of RFC 2616.
     395                           Always perform a GET request unless we received a 301. 303 was
     396                           meant for this but it's HTTP/1.1-only and we're specifically
     397                           speaking HTTP/1.0. ...
     398                           
     399                           Well except someone at identi.ca's didn't bother reading any
     400                           RFCs and just return HTTP/1.1-specific status codes to HTTP/1.0
     401                           requests. Fuckers. So here we are, handle 301..303,307. */
     402                        if( strncmp( req->request, "GET", 3 ) == 0 )
     403                                /* GETs never become POSTs. */
     404                                new_method = "GET";
     405                        else if( req->status_code == 302 || req->status_code == 303 )
     406                                /* 302 de-facto becomes GET, 303 as specified by RFC 2616#10.3.3 */
     407                                new_method = "GET";
     408                        else
     409                                /* 301 de-facto should stay POST, 307 specifally RFC 2616#10.3.8 */
     410                                new_method = "POST";
     411                       
     412                        /* Okay, this isn't fun! We have to rebuild the request... :-( */
     413                        new_request = g_strdup_printf( "%s %s HTTP/1.0\r\nHost: %s%s",
     414                                                       new_method, url->file, url->host, s );
     415                       
    389416                        new_host = g_strdup( url->host );
    390417                        new_port = url->port;
    391418                        new_proto = url->proto;
     419                       
     420                        /* If we went from POST to GET, truncate the request content. */
     421                        if( new_request[0] != req->request[0] && new_request[0] == 'G' &&
     422                            ( s = strstr( new_request, "\r\n\r\n" ) ) )
     423                                s[4] = '\0';
    392424                       
    393425                        g_free( url );
     
    402434                req->ssl = NULL;
    403435               
     436                if( getenv( "BITLBEE_DEBUG" ) )
     437                        printf( "New headers for redirected HTTP request:\n%s\n", new_request );
     438       
    404439                if( new_proto == PROTO_HTTPS )
    405440                {
     
    443478                closesocket( req->fd );
    444479       
     480        if( getenv( "BITLBEE_DEBUG" ) && req )
     481                printf( "Finishing HTTP request with status: %s\n",
     482                        req->status_string ? req->status_string : "NULL" );
     483       
    445484        req->func( req );
    446485        http_free( req );
  • lib/ssl_client.h

    r87dddee r6e9ae72  
    6363G_MODULE_EXPORT int ssl_write( void *conn, const char *buf, int len );
    6464
    65 /* See ssl_openssl.c for an explanation. */
     65/* Now needed by most SSL libs. See for more info:
     66   http://www.gnu.org/software/gnutls/manual/gnutls.html#index-gnutls_005frecord_005fcheck_005fpending-209
     67   http://www.openssl.org/docs/ssl/SSL_pending.html
     68   
     69   Required because OpenSSL empties the TCP buffer completely but doesn't
     70   necessarily give us all the unencrypted data. Or maybe you didn't ask
     71   for all of it because your buffer is too small.
     72   
     73   Returns 0 if there's nothing left, 1 if there's more data. */
    6674G_MODULE_EXPORT int ssl_pending( void *conn );
    6775
  • lib/ssl_gnutls.c

    r87dddee r6e9ae72  
    4545#endif
    4646
     47#define SSLDEBUG 0
     48
    4749struct scd
    4850{
     
    135137        gnutls_certificate_allocate_credentials( &conn->xcred );
    136138        gnutls_init( &conn->session, GNUTLS_CLIENT );
    137         gnutls_transport_set_lowat( conn->session, 1 );
     139#if GNUTLS_VERSION_NUMBER < 0x020c00
     140        gnutls_transport_set_lowat( conn->session, 0 );
     141#endif
    138142        gnutls_set_default_priority( conn->session );
    139143        gnutls_credentials_set( conn->session, GNUTLS_CRD_CERTIFICATE, conn->xcred );
     
    187191        {
    188192                ssl_errno = SSL_NOHANDSHAKE;
    189                 return( -1 );
     193                return -1;
    190194        }
    191195       
     
    196200                ssl_errno = SSL_AGAIN;
    197201       
    198         if( 0 && getenv( "BITLBEE_DEBUG" ) && st > 0 ) len = write( 1, buf, st );
     202        if( SSLDEBUG && getenv( "BITLBEE_DEBUG" ) && st > 0 ) len = write( 2, buf, st );
    199203       
    200204        return st;
     
    208212        {
    209213                ssl_errno = SSL_NOHANDSHAKE;
    210                 return( -1 );
     214                return -1;
    211215        }
    212216       
     
    217221                ssl_errno = SSL_AGAIN;
    218222       
    219         if( 0 && getenv( "BITLBEE_DEBUG" ) && st > 0 ) len = write( 1, buf, st );
     223        if( SSLDEBUG && getenv( "BITLBEE_DEBUG" ) && st > 0 ) len = write( 2, buf, st );
    220224       
    221225        return st;
    222226}
    223227
    224 /* See ssl_openssl.c for an explanation. */
    225228int ssl_pending( void *conn )
    226229{
    227         return 0;
     230        if( conn == NULL )
     231                return 0;
     232       
     233        if( !((struct scd*)conn)->established )
     234        {
     235                ssl_errno = SSL_NOHANDSHAKE;
     236                return 0;
     237        }
     238       
     239        return gnutls_record_check_pending( ((struct scd*)conn)->session ) != 0;
    228240}
    229241
  • lib/ssl_nss.c

    r87dddee r6e9ae72  
    207207}
    208208
    209 /* See ssl_openssl.c for an explanation. */
    210209int ssl_pending( void *conn )
    211210{
  • lib/ssl_openssl.c

    r87dddee r6e9ae72  
    241241}
    242242
    243 /* Only OpenSSL *really* needs this (and well, maybe NSS). See for more info:
    244    http://www.gnu.org/software/gnutls/manual/gnutls.html#index-gnutls_005frecord_005fcheck_005fpending-209
    245    http://www.openssl.org/docs/ssl/SSL_pending.html
    246    
    247    Required because OpenSSL empties the TCP buffer completely but doesn't
    248    necessarily give us all the unencrypted data.
    249    
    250    Returns 0 if there's nothing left or if we don't have to care (GnuTLS),
    251    1 if there's more data. */
    252243int ssl_pending( void *conn )
    253244{
  • lib/xmltree.c

    r87dddee r6e9ae72  
    323323}
    324324
    325 #ifdef DEBUG
    326325void xt_print( struct xt_node *node )
    327326{
     
    331330        /* Indentation */
    332331        for( c = node; c->parent; c = c->parent )
    333                 printf( "    " );
     332                fprintf( stderr, "    " );
    334333       
    335334        /* Start the tag */
    336         printf( "<%s", node->name );
     335        fprintf( stderr, "<%s", node->name );
    337336       
    338337        /* Print the attributes */
     
    340339        {
    341340                char *v = g_markup_escape_text( node->attr[i].value, -1 );
    342                 printf( " %s=\"%s\"", node->attr[i].key, v );
     341                fprintf( stderr, " %s=\"%s\"", node->attr[i].key, v );
    343342                g_free( v );
    344343        }
     
    349348        if( node->text == NULL && node->children == NULL )
    350349        {
    351                 printf( "/>\n" );
     350                fprintf( stderr, "/>\n" );
    352351                return;
    353352                /* Then we're finished! */
     
    355354       
    356355        /* Otherwise... */
    357         printf( ">" );
     356        fprintf( stderr, ">" );
    358357       
    359358        /* Only print the text if it contains more than whitespace (TEST). */
     
    364363                {
    365364                        char *v = g_markup_escape_text( node->text, -1 );
    366                         printf( "%s", v );
     365                        fprintf( stderr, "%s", v );
    367366                        g_free( v );
    368367                }
     
    370369       
    371370        if( node->children )
    372                 printf( "\n" );
     371                fprintf( stderr, "\n" );
    373372       
    374373        for( c = node->children; c; c = c->next )
     
    377376        if( node->children )
    378377                for( c = node; c->parent; c = c->parent )
    379                         printf( "    " );
     378                        fprintf( stderr, "    " );
    380379       
    381380        /* Non-empty tag is now finished. */
    382         printf( "</%s>\n", node->name );
    383 }
    384 #endif
     381        fprintf( stderr, "</%s>\n", node->name );
     382}
    385383
    386384struct xt_node *xt_dup( struct xt_node *node )
     
    557555}
    558556
     557/* Strip a few non-printable characters that aren't allowed in XML streams
     558   (and upset some XMPP servers for example). */
     559void xt_strip_text( char *in )
     560{
     561        char *out = in;
     562        static const char nonprint[32] = {
     563                0, 0, 0, 0, 0, 0, 0, 0, /* 0..7 */
     564                0, 1, 1, 0, 0, 1, 0, 0, /* 9 (tab), 10 (\n), 13 (\r) */
     565        };
     566       
     567        if( !in )
     568                return;
     569
     570        while( *in )
     571        {
     572                if( (unsigned int) *in >= ' ' || nonprint[(unsigned int) *in] )
     573                        *out ++ = *in;
     574                in ++;
     575        }
     576        *out = *in;
     577}
     578
    559579struct xt_node *xt_new_node( char *name, const char *text, struct xt_node *children )
    560580{
     
    568588        if( text )
    569589        {
    570                 node->text_len = strlen( text );
    571                 node->text = g_memdup( text, node->text_len + 1 );
     590                node->text = g_strdup( text );
     591                xt_strip_text( node->text );
     592                node->text_len = strlen( node->text );
    572593        }
    573594       
Note: See TracChangeset for help on using the changeset viewer.