From dff732d93799db858a5728abbf31d2e6274b8425 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sat, 12 Nov 2011 23:49:52 +0800 Subject: Undoing old workaround for MSN troubles and added more proper fix. The http_client module needs some refactoring though. Will do that later.. This should hopefully fix bug #850. --- lib/http_client.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'lib/http_client.c') diff --git a/lib/http_client.c b/lib/http_client.c index 8b045414..f535f13f 100644 --- a/lib/http_client.c +++ b/lib/http_client.c @@ -313,7 +313,7 @@ got_reply: req->status_code = -1; } - if( ( req->status_code == 301 || req->status_code == 302 ) && req->redir_ttl-- > 0 ) + if( ( req->status_code >= 301 && req->status_code <= 303 ) && req->redir_ttl-- > 0 ) { char *loc, *new_request, *new_host; int error = 0, new_port, new_proto; @@ -374,10 +374,13 @@ got_reply: /* So, now I just allocated enough memory, so I'm going to use strcat(), whether you like it or not. :-) */ - sprintf( new_request, "GET %s HTTP/1.0", url->file ); + *s = 0; + sprintf( new_request, "%s %s HTTP/1.0\r\nHost: %s", + req->status_code == 303 || req->request[0] == 'G' ? "GET" : "POST", url->file, url->host ); + *s = ' '; - s = strstr( req->request, "\r\n" ); - if( s == NULL ) + if( !( ( s = strstr( req->request, "\r\nHost: " ) ) && + ( s = strstr( s + strlen( "\r\nHost: " ), "\r\n" ) ) ) ) { req->status_string = g_strdup( "Error while rebuilding request string" ); g_free( new_request ); -- cgit v1.2.3 From 03a8f8ec82719512f059fdd2c0dca3bb919b059c Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 13 Nov 2011 09:41:42 +0800 Subject: Cleanup of http_client fix. Use g_strdup_printf and completely avoid strcat, truncate request if we switched from POST to GET. --- lib/http_client.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) (limited to 'lib/http_client.c') diff --git a/lib/http_client.c b/lib/http_client.c index f535f13f..84914388 100644 --- a/lib/http_client.c +++ b/lib/http_client.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2005 Wilmer van der Gaast and others * + * Copyright 2002-2011 Wilmer van der Gaast and others * \********************************************************************/ /* HTTP(S) module */ @@ -353,6 +353,7 @@ got_reply: /* A whole URL */ url_t *url; char *s; + const char *new_method; s = strstr( loc, "\r\n" ); if( s == NULL ) @@ -368,31 +369,37 @@ got_reply: goto cleanup; } - /* Okay, this isn't fun! We have to rebuild the request... :-( */ - new_request = g_malloc( req->request_length + strlen( url->file ) ); - - /* So, now I just allocated enough memory, so I'm - going to use strcat(), whether you like it or not. :-) */ - - *s = 0; - sprintf( new_request, "%s %s HTTP/1.0\r\nHost: %s", - req->status_code == 303 || req->request[0] == 'G' ? "GET" : "POST", url->file, url->host ); - *s = ' '; - + /* Find all headers and, if necessary, the POST request contents. + Skip the old Host: header though. This crappy code here means + anything using this http_client MUST put the Host: header at + the top. */ if( !( ( s = strstr( req->request, "\r\nHost: " ) ) && ( s = strstr( s + strlen( "\r\nHost: " ), "\r\n" ) ) ) ) { req->status_string = g_strdup( "Error while rebuilding request string" ); - g_free( new_request ); g_free( url ); goto cleanup; } - strcat( new_request, s ); + /* More or less HTTP/1.0 compliant, from my reading of RFC 2616. + Always perform a GET request unless we received a 301. 303 was + meant for this but it's HTTP/1.1-only and we're specifically + speaking HTTP/1.0. */ + new_method = req->status_code != 301 || req->request[0] == 'G' ? "GET" : "POST"; + + /* Okay, this isn't fun! We have to rebuild the request... :-( */ + new_request = g_strdup_printf( "%s %s HTTP/1.0\r\nHost: %s%s", + new_method, url->file, url->host, s ); + new_host = g_strdup( url->host ); new_port = url->port; new_proto = url->proto; + /* If we went from POST to GET, truncate the request content. */ + if( new_request[0] != req->request[0] && new_request[0] == 'G' && + ( s = strstr( new_request, "\r\n\r\n" ) ) ) + s[4] = '\0'; + g_free( url ); } -- cgit v1.2.3 From 80acb6db8133ebd16c3257d33721994ed164ba9f Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Mon, 14 Nov 2011 18:43:03 +0800 Subject: GnuTLS now also needs ssl_pending() implemented. Bug #860. --- lib/http_client.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib/http_client.c') diff --git a/lib/http_client.c b/lib/http_client.c index 84914388..8bd543af 100644 --- a/lib/http_client.c +++ b/lib/http_client.c @@ -239,7 +239,10 @@ static gboolean http_incoming_data( gpointer data, int source, b_input_condition req->ssl ? ssl_getdirection( req->ssl ) : B_EV_IO_READ, http_incoming_data, req ); - return FALSE; + if( ssl_pending( req->ssl ) ) + return http_incoming_data( data, source, cond ); + else + return FALSE; got_reply: /* Maybe if the webserver is overloaded, or when there's bad SSL -- cgit v1.2.3 From bd3166176fdb7ed96211eb539316f47843e0faa7 Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Fri, 2 Dec 2011 10:32:54 +0000 Subject: Somewhat improve debug logging of HTTP/SOAP stuff. --- lib/http_client.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'lib/http_client.c') diff --git a/lib/http_client.c b/lib/http_client.c index 8bd543af..56a6f376 100644 --- a/lib/http_client.c +++ b/lib/http_client.c @@ -278,6 +278,9 @@ got_reply: *end1 = 0; + if( getenv( "BITLBEE_DEBUG" ) ) + printf( "HTTP response headers:\n%s", req->reply_headers ); + if( evil_server ) req->reply_body = end1 + 1; else @@ -414,6 +417,9 @@ got_reply: req->fd = -1; req->ssl = NULL; + if( getenv( "BITLBEE_DEBUG" ) ) + printf( "New headers for redirected HTTP request:\n%s", new_request ); + if( new_proto == PROTO_HTTPS ) { req->ssl = ssl_connect( new_host, new_port, http_ssl_connected, req ); @@ -455,6 +461,10 @@ cleanup: else closesocket( req->fd ); + if( getenv( "BITLBEE_DEBUG" ) && req ) + printf( "Finishing HTTP request with status: %s", + req->status_string ? req->status_string : "NULL" ); + req->func( req ); http_free( req ); return FALSE; -- cgit v1.2.3 From 3f808ca58e45f2a305e01471cc514957039a865d Mon Sep 17 00:00:00 2001 From: Wilmer van der Gaast Date: Sun, 11 Dec 2011 16:38:02 +0000 Subject: Support HTTP/1.1 redirect status codes and use HTTPS for OAuth setup. This is required for identi.ca and really should be done for Twitter as well. Twitter OAuth is still broken though, it seems to disagree about signatures. --- lib/http_client.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'lib/http_client.c') diff --git a/lib/http_client.c b/lib/http_client.c index 56a6f376..9d986412 100644 --- a/lib/http_client.c +++ b/lib/http_client.c @@ -69,6 +69,9 @@ struct http_request *http_dorequest( char *host, int port, int ssl, char *reques req->request_length = strlen( request ); req->redir_ttl = 3; + if( getenv( "BITLBEE_DEBUG" ) ) + printf( "About to send HTTP request:\n%s\n", req->request ); + return( req ); } @@ -279,7 +282,7 @@ got_reply: *end1 = 0; if( getenv( "BITLBEE_DEBUG" ) ) - printf( "HTTP response headers:\n%s", req->reply_headers ); + printf( "HTTP response headers:\n%s\n", req->reply_headers ); if( evil_server ) req->reply_body = end1 + 1; @@ -319,7 +322,8 @@ got_reply: req->status_code = -1; } - if( ( req->status_code >= 301 && req->status_code <= 303 ) && req->redir_ttl-- > 0 ) + if( ( ( req->status_code >= 301 && req->status_code <= 303 ) || + req->status_code == 307 ) && req->redir_ttl-- > 0 ) { char *loc, *new_request, *new_host; int error = 0, new_port, new_proto; @@ -390,8 +394,20 @@ got_reply: /* More or less HTTP/1.0 compliant, from my reading of RFC 2616. Always perform a GET request unless we received a 301. 303 was meant for this but it's HTTP/1.1-only and we're specifically - speaking HTTP/1.0. */ - new_method = req->status_code != 301 || req->request[0] == 'G' ? "GET" : "POST"; + speaking HTTP/1.0. ... + + Well except someone at identi.ca's didn't bother reading any + RFCs and just return HTTP/1.1-specific status codes to HTTP/1.0 + requests. Fuckers. So here we are, handle 301..303,307. */ + if( strncmp( req->request, "GET", 3 ) == 0 ) + /* GETs never become POSTs. */ + new_method = "GET"; + else if( req->status_code == 302 || req->status_code == 303 ) + /* 302 de-facto becomes GET, 303 as specified by RFC 2616#10.3.3 */ + new_method = "GET"; + else + /* 301 de-facto should stay POST, 307 specifally RFC 2616#10.3.8 */ + new_method = "POST"; /* Okay, this isn't fun! We have to rebuild the request... :-( */ new_request = g_strdup_printf( "%s %s HTTP/1.0\r\nHost: %s%s", @@ -418,7 +434,7 @@ got_reply: req->ssl = NULL; if( getenv( "BITLBEE_DEBUG" ) ) - printf( "New headers for redirected HTTP request:\n%s", new_request ); + printf( "New headers for redirected HTTP request:\n%s\n", new_request ); if( new_proto == PROTO_HTTPS ) { @@ -462,7 +478,7 @@ cleanup: closesocket( req->fd ); if( getenv( "BITLBEE_DEBUG" ) && req ) - printf( "Finishing HTTP request with status: %s", + printf( "Finishing HTTP request with status: %s\n", req->status_string ? req->status_string : "NULL" ); req->func( req ); -- cgit v1.2.3