diff options
| author | Indent <please@skip.me> | 2015-02-19 02:47:20 -0300 | 
|---|---|---|
| committer | dequis <dx@dxzone.com.ar> | 2015-02-20 19:50:54 -0300 | 
| commit | 5ebff60479fc7a9f7f50ac03b124c91d4e6ebe11 (patch) | |
| tree | 9fc0d50cb1f4bc9768d9f00de94eafd876bb55b0 /lib/http_client.c | |
| parent | af359b4316f9d392c6b752495a1b2ed631576ed8 (diff) | |
Reindent everything to K&R style with tabs
Used uncrustify, with the configuration file in ./doc/uncrustify.cfg
Commit author set to "Indent <please@skip.me>" so that it's easier to
skip while doing git blame.
Diffstat (limited to 'lib/http_client.c')
| -rw-r--r-- | lib/http_client.c | 839 | 
1 files changed, 411 insertions, 428 deletions
diff --git a/lib/http_client.c b/lib/http_client.c index 2481997a..1dc5947a 100644 --- a/lib/http_client.c +++ b/lib/http_client.c @@ -1,4 +1,4 @@ -  /********************************************************************\ +/********************************************************************\    * BitlBee -- An IRC to other IM-networks gateway                     *    *                                                                    *    * Copyright 2002-2013 Wilmer van der Gaast and others                * @@ -31,165 +31,159 @@  #include "sock.h" -static gboolean http_connected( gpointer data, int source, b_input_condition cond ); -static gboolean http_ssl_connected( gpointer data, int returncode, void *source, b_input_condition cond ); -static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond ); -static void http_free( struct http_request *req ); +static gboolean http_connected(gpointer data, int source, b_input_condition cond); +static gboolean http_ssl_connected(gpointer data, int returncode, void *source, b_input_condition cond); +static gboolean http_incoming_data(gpointer data, int source, b_input_condition cond); +static void http_free(struct http_request *req); -struct http_request *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data ) +struct http_request *http_dorequest(char *host, int port, int ssl, char *request, http_input_function func, +                                    gpointer data)  {  	struct http_request *req;  	int error = 0; -	 -	req = g_new0( struct http_request, 1 ); -	 -	if( ssl ) -	{ -		req->ssl = ssl_connect( host, port, TRUE, http_ssl_connected, req ); -		if( req->ssl == NULL ) + +	req = g_new0(struct http_request, 1); + +	if (ssl) { +		req->ssl = ssl_connect(host, port, TRUE, http_ssl_connected, req); +		if (req->ssl == NULL) {  			error = 1; -	} -	else -	{ -		req->fd = proxy_connect( host, port, http_connected, req ); -		if( req->fd < 0 ) +		} +	} else { +		req->fd = proxy_connect(host, port, http_connected, req); +		if (req->fd < 0) {  			error = 1; +		}  	} -	 -	if( error ) -	{ -		http_free( req ); + +	if (error) { +		http_free(req);  		return NULL;  	} -	 +  	req->func = func;  	req->data = data; -	req->request = g_strdup( request ); -	req->request_length = strlen( request ); +	req->request = g_strdup(request); +	req->request_length = strlen(request);  	req->redir_ttl = 3;  	req->content_length = -1; -	 -	if( getenv( "BITLBEE_DEBUG" ) ) -		printf( "About to send HTTP request:\n%s\n", req->request ); -	 + +	if (getenv("BITLBEE_DEBUG")) { +		printf("About to send HTTP request:\n%s\n", req->request); +	} +  	return req;  } -struct http_request *http_dorequest_url( char *url_string, http_input_function func, gpointer data ) +struct http_request *http_dorequest_url(char *url_string, http_input_function func, gpointer data)  { -	url_t *url = g_new0( url_t, 1 ); +	url_t *url = g_new0(url_t, 1);  	char *request;  	void *ret; -	 -	if( !url_set( url, url_string ) ) -	{ -		g_free( url ); + +	if (!url_set(url, url_string)) { +		g_free(url);  		return NULL;  	} -	 -	if( url->proto != PROTO_HTTP && url->proto != PROTO_HTTPS ) -	{ -		g_free( url ); + +	if (url->proto != PROTO_HTTP && url->proto != PROTO_HTTPS) { +		g_free(url);  		return NULL;  	} -	 -	request = g_strdup_printf( "GET %s HTTP/1.0\r\n" -	                           "Host: %s\r\n" -	                           "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n" -	                           "\r\n", url->file, url->host ); -	 -	ret = http_dorequest( url->host, url->port, -	                      url->proto == PROTO_HTTPS, request, func, data ); -	 -	g_free( url ); -	g_free( request ); + +	request = g_strdup_printf("GET %s HTTP/1.0\r\n" +	                          "Host: %s\r\n" +	                          "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n" +	                          "\r\n", url->file, url->host); + +	ret = http_dorequest(url->host, url->port, +	                     url->proto == PROTO_HTTPS, request, func, data); + +	g_free(url); +	g_free(request);  	return ret;  } -/* This one is actually pretty simple... Might get more calls if we can't write  +/* This one is actually pretty simple... Might get more calls if we can't write     the whole request at once. */ -static gboolean http_connected( gpointer data, int source, b_input_condition cond ) +static gboolean http_connected(gpointer data, int source, b_input_condition cond)  {  	struct http_request *req = data;  	int st; -	 -	if( source < 0 ) + +	if (source < 0) {  		goto error; -	 -	if( req->inpa > 0 ) -		b_event_remove( req->inpa ); -	 -	sock_make_nonblocking( req->fd ); -	 -	if( req->ssl ) -	{ -		st = ssl_write( req->ssl, req->request + req->bytes_written, -		                req->request_length - req->bytes_written ); -		if( st < 0 ) -		{ -			if( ssl_errno != SSL_AGAIN ) -			{ -				ssl_disconnect( req->ssl ); +	} + +	if (req->inpa > 0) { +		b_event_remove(req->inpa); +	} + +	sock_make_nonblocking(req->fd); + +	if (req->ssl) { +		st = ssl_write(req->ssl, req->request + req->bytes_written, +		               req->request_length - req->bytes_written); +		if (st < 0) { +			if (ssl_errno != SSL_AGAIN) { +				ssl_disconnect(req->ssl);  				goto error;  			}  		} -	} -	else -	{ -		st = write( source, req->request + req->bytes_written, -		                    req->request_length - req->bytes_written ); -		if( st < 0 ) -		{ -			if( !sockerr_again() ) -			{ -				closesocket( req->fd ); +	} else { +		st = write(source, req->request + req->bytes_written, +		           req->request_length - req->bytes_written); +		if (st < 0) { +			if (!sockerr_again()) { +				closesocket(req->fd);  				goto error;  			}  		}  	} -	 -	if( st > 0 ) + +	if (st > 0) {  		req->bytes_written += st; -	 -	if( req->bytes_written < req->request_length ) -		req->inpa = b_input_add( source, -		                         req->ssl ? ssl_getdirection( req->ssl ) : B_EV_IO_WRITE, -	        	                 http_connected, req ); -	else -		req->inpa = b_input_add( source, B_EV_IO_READ, http_incoming_data, req ); -	 +	} + +	if (req->bytes_written < req->request_length) { +		req->inpa = b_input_add(source, +		                        req->ssl ? ssl_getdirection(req->ssl) : B_EV_IO_WRITE, +		                        http_connected, req); +	} else { +		req->inpa = b_input_add(source, B_EV_IO_READ, http_incoming_data, req); +	} +  	return FALSE; -	 +  error: -	if( req->status_string == NULL ) -		req->status_string = g_strdup( "Error while writing HTTP request" ); -	 -	req->func( req ); -	http_free( req ); +	if (req->status_string == NULL) { +		req->status_string = g_strdup("Error while writing HTTP request"); +	} + +	req->func(req); +	http_free(req);  	return FALSE;  } -static gboolean http_ssl_connected( gpointer data, int returncode, void *source, b_input_condition cond ) +static gboolean http_ssl_connected(gpointer data, int returncode, void *source, b_input_condition cond)  {  	struct http_request *req = data; -	 -	if( source == NULL ) -	{ -		if( returncode != 0 ) -		{ -			char *err = ssl_verify_strerror( returncode ); + +	if (source == NULL) { +		if (returncode != 0) { +			char *err = ssl_verify_strerror(returncode);  			req->status_string = g_strdup_printf( -				"Certificate verification problem 0x%x: %s", -				returncode, err ? err : "Unknown" ); -			g_free( err ); +			        "Certificate verification problem 0x%x: %s", +			        returncode, err ? err : "Unknown"); +			g_free(err);  		} -		return http_connected( data, -1, cond ); +		return http_connected(data, -1, cond);  	} -	 -	req->fd = ssl_getfd( source ); -	 -	return http_connected( data, req->fd, cond ); + +	req->fd = ssl_getfd(source); + +	return http_connected(data, req->fd, cond);  }  typedef enum { @@ -199,97 +193,87 @@ typedef enum {  	CR_ABORT,  } http_ret_t; -static gboolean http_handle_headers( struct http_request *req ); -static http_ret_t http_process_chunked_data( struct http_request *req, const char *buffer, int len ); -static http_ret_t http_process_data( struct http_request *req, const char *buffer, int len ); +static gboolean http_handle_headers(struct http_request *req); +static http_ret_t http_process_chunked_data(struct http_request *req, const char *buffer, int len); +static http_ret_t http_process_data(struct http_request *req, const char *buffer, int len); -static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond ) +static gboolean http_incoming_data(gpointer data, int source, b_input_condition cond)  {  	struct http_request *req = data;  	char buffer[4096];  	int st; -	 -	if( req->inpa > 0 ) -	{ -		b_event_remove( req->inpa ); + +	if (req->inpa > 0) { +		b_event_remove(req->inpa);  		req->inpa = 0;  	} -	 -	if( req->ssl ) -	{ -		st = ssl_read( req->ssl, buffer, sizeof( buffer ) ); -		if( st < 0 ) -		{ -			if( ssl_errno != SSL_AGAIN ) -			{ + +	if (req->ssl) { +		st = ssl_read(req->ssl, buffer, sizeof(buffer)); +		if (st < 0) { +			if (ssl_errno != SSL_AGAIN) {  				/* goto cleanup; */ -				 +  				/* YAY! We have to deal with crappy Microsoft  				   servers that LOVE to send invalid TLS  				   packets that abort connections! \o/ */ -				 +  				goto eof;  			} -		} -		else if( st == 0 ) -		{ +		} else if (st == 0) {  			goto eof;  		} -	} -	else -	{ -		st = read( req->fd, buffer, sizeof( buffer ) ); -		if( st < 0 ) -		{ -			if( !sockerr_again() ) -			{ -				req->status_string = g_strdup( strerror( errno ) ); +	} else { +		st = read(req->fd, buffer, sizeof(buffer)); +		if (st < 0) { +			if (!sockerr_again()) { +				req->status_string = g_strdup(strerror(errno));  				goto cleanup;  			} -		} -		else if( st == 0 ) -		{ +		} else if (st == 0) {  			goto eof;  		}  	} -	 -	if( st > 0 ) -	{ + +	if (st > 0) {  		http_ret_t c; -		 -		if( req->flags & HTTPC_CHUNKED ) -			c = http_process_chunked_data( req, buffer, st ); -		else -			c = http_process_data( req, buffer, st ); -		 -		if( c == CR_EOF ) + +		if (req->flags & HTTPC_CHUNKED) { +			c = http_process_chunked_data(req, buffer, st); +		} else { +			c = http_process_data(req, buffer, st); +		} + +		if (c == CR_EOF) {  			goto eof; -		else if( c == CR_ERROR || c == CR_ABORT ) +		} else if (c == CR_ERROR || c == CR_ABORT) {  			return FALSE; +		}  	} -	 -	if( req->content_length != -1 && -	    req->body_size >= req->content_length ) + +	if (req->content_length != -1 && +	    req->body_size >= req->content_length) {  		goto eof; -	 -	if( ssl_pending( req->ssl ) ) -		return http_incoming_data( data, source, cond ); -	 +	} + +	if (ssl_pending(req->ssl)) { +		return http_incoming_data(data, source, cond); +	} +  	/* There will be more! */ -	req->inpa = b_input_add( req->fd, -	                         req->ssl ? ssl_getdirection( req->ssl ) : B_EV_IO_READ, -	                         http_incoming_data, req ); -	 +	req->inpa = b_input_add(req->fd, +	                        req->ssl ? ssl_getdirection(req->ssl) : B_EV_IO_READ, +	                        http_incoming_data, req); +  	return FALSE;  eof:  	req->flags |= HTTPC_EOF; -	 +  	/* Maybe if the webserver is overloaded, or when there's bad SSL  	   support... */ -	if( req->bytes_read == 0 ) -	{ -		req->status_string = g_strdup( "Empty HTTP reply" ); +	if (req->bytes_read == 0) { +		req->status_string = g_strdup("Empty HTTP reply");  		goto cleanup;  	} @@ -297,433 +281,432 @@ cleanup:  	/* Avoid g_source_remove warnings */  	req->inpa = 0; -	if( req->ssl ) -		ssl_disconnect( req->ssl ); -	else -		closesocket( req->fd ); -	 -	if( req->body_size < req->content_length ) -	{ +	if (req->ssl) { +		ssl_disconnect(req->ssl); +	} else { +		closesocket(req->fd); +	} + +	if (req->body_size < req->content_length) {  		req->status_code = -1; -		g_free( req->status_string ); -		req->status_string = g_strdup( "Response truncated" ); -	} -	 -	if( getenv( "BITLBEE_DEBUG" ) && req ) -		printf( "Finishing HTTP request with status: %s\n", -		        req->status_string ? req->status_string : "NULL" ); -	 -	req->func( req ); -	http_free( req ); +		g_free(req->status_string); +		req->status_string = g_strdup("Response truncated"); +	} + +	if (getenv("BITLBEE_DEBUG") && req) { +		printf("Finishing HTTP request with status: %s\n", +		       req->status_string ? req->status_string : "NULL"); +	} + +	req->func(req); +	http_free(req);  	return FALSE;  } -static http_ret_t http_process_chunked_data( struct http_request *req, const char *buffer, int len ) +static http_ret_t http_process_chunked_data(struct http_request *req, const char *buffer, int len)  {  	char *chunk, *eos, *s; -	 -	if( len < 0 ) + +	if (len < 0) {  		return TRUE; -	 -	if( len > 0 ) -	{ -		req->cbuf = g_realloc( req->cbuf, req->cblen + len + 1 ); -		memcpy( req->cbuf + req->cblen, buffer, len ); +	} + +	if (len > 0) { +		req->cbuf = g_realloc(req->cbuf, req->cblen + len + 1); +		memcpy(req->cbuf + req->cblen, buffer, len);  		req->cblen += len;  		req->cbuf[req->cblen] = '\0';  	} -	 +  	/* Turns out writing a proper chunked-encoding state machine is not  	   that simple. :-( I've tested this one feeding it byte by byte so  	   I hope it's solid now. */  	chunk = req->cbuf;  	eos = req->cbuf + req->cblen; -	while( TRUE ) -	{ +	while (TRUE) {  		int clen = 0; -		 +  		/* Might be a \r\n from the last chunk. */  		s = chunk; -		while( g_ascii_isspace( *s ) ) -			s ++; +		while (g_ascii_isspace(*s)) { +			s++; +		}  		/* Chunk length. Might be incomplete. */ -		if( s < eos && sscanf( s, "%x", &clen ) != 1 ) +		if (s < eos && sscanf(s, "%x", &clen) != 1) {  			return CR_ERROR; -		while( g_ascii_isxdigit( *s ) ) -			s ++; -		 +		} +		while (g_ascii_isxdigit(*s)) { +			s++; +		} +  		/* If we read anything here, it *must* be \r\n. */ -		if( strncmp( s, "\r\n", MIN( 2, eos - s ) ) != 0 ) +		if (strncmp(s, "\r\n", MIN(2, eos - s)) != 0) {  			return CR_ERROR; +		}  		s += 2; -		 -		if( s >= eos ) + +		if (s >= eos) {  			break; -		 -		/* 0-length chunk means end of response. */	 -		if( clen == 0 ) +		} + +		/* 0-length chunk means end of response. */ +		if (clen == 0) {  			return CR_EOF; -		 +		} +  		/* Wait for the whole chunk to arrive. */ -		if( s + clen > eos ) +		if (s + clen > eos) {  			break; -		if( http_process_data( req, s, clen ) != CR_OK ) +		} +		if (http_process_data(req, s, clen) != CR_OK) {  			return CR_ABORT; -		 +		} +  		chunk = s + clen;  	} -	 -	if( chunk != req->cbuf ) -	{ + +	if (chunk != req->cbuf) {  		req->cblen = eos - chunk; -		s = g_memdup( chunk, req->cblen + 1 ); -		g_free( req->cbuf ); +		s = g_memdup(chunk, req->cblen + 1); +		g_free(req->cbuf);  		req->cbuf = s;  	} -	 +  	return CR_OK;  } -static http_ret_t http_process_data( struct http_request *req, const char *buffer, int len ) +static http_ret_t http_process_data(struct http_request *req, const char *buffer, int len)  { -	if( len <= 0 ) +	if (len <= 0) {  		return CR_OK; -	 -	if( !req->reply_body ) -	{ -		req->reply_headers = g_realloc( req->reply_headers, req->bytes_read + len + 1 ); -		memcpy( req->reply_headers + req->bytes_read, buffer, len ); +	} + +	if (!req->reply_body) { +		req->reply_headers = g_realloc(req->reply_headers, req->bytes_read + len + 1); +		memcpy(req->reply_headers + req->bytes_read, buffer, len);  		req->bytes_read += len;  		req->reply_headers[req->bytes_read] = '\0'; -		 -		if( strstr( req->reply_headers, "\r\n\r\n" ) || -		    strstr( req->reply_headers, "\n\n" ) ) -		{ + +		if (strstr(req->reply_headers, "\r\n\r\n") || +		    strstr(req->reply_headers, "\n\n")) {  			/* We've now received all headers. Look for something  			   interesting. */ -			if( !http_handle_headers( req ) ) +			if (!http_handle_headers(req)) {  				return CR_ABORT; -			 +			} +  			/* Start parsing the body as chunked if required. */ -			if( req->flags & HTTPC_CHUNKED ) -				return http_process_chunked_data( req, NULL, 0 ); +			if (req->flags & HTTPC_CHUNKED) { +				return http_process_chunked_data(req, NULL, 0); +			}  		} -	} -	else -	{ +	} else {  		int pos = req->reply_body - req->sbuf; -		req->sbuf = g_realloc( req->sbuf, req->sblen + len + 1 ); -		memcpy( req->sbuf + req->sblen, buffer, len ); +		req->sbuf = g_realloc(req->sbuf, req->sblen + len + 1); +		memcpy(req->sbuf + req->sblen, buffer, len);  		req->bytes_read += len;  		req->sblen += len;  		req->sbuf[req->sblen] = '\0';  		req->reply_body = req->sbuf + pos;  		req->body_size = req->sblen - pos;  	} -	 -	if( ( req->flags & HTTPC_STREAMING ) && req->reply_body ) -		req->func( req ); -	 + +	if ((req->flags & HTTPC_STREAMING) && req->reply_body) { +		req->func(req); +	} +  	return CR_OK;  }  /* Splits headers and body. Checks result code, in case of 300s it'll handle     redirects. If this returns FALSE, don't call any callbacks! */ -static gboolean http_handle_headers( struct http_request *req ) +static gboolean http_handle_headers(struct http_request *req)  {  	char *end1, *end2, *s;  	int evil_server = 0; -	 +  	/* Zero termination is very convenient. */  	req->reply_headers[req->bytes_read] = '\0'; -	 +  	/* Find the separation between headers and body, and keep stupid  	   webservers in mind. */ -	end1 = strstr( req->reply_headers, "\r\n\r\n" ); -	end2 = strstr( req->reply_headers, "\n\n" ); -	 -	if( end2 && end2 < end1 ) -	{ +	end1 = strstr(req->reply_headers, "\r\n\r\n"); +	end2 = strstr(req->reply_headers, "\n\n"); + +	if (end2 && end2 < end1) {  		end1 = end2 + 1;  		evil_server = 1; -	} -	else if( end1 ) -	{ +	} else if (end1) {  		end1 += 2; -	} -	else -	{ -		req->status_string = g_strdup( "Malformed HTTP reply" ); +	} else { +		req->status_string = g_strdup("Malformed HTTP reply");  		return TRUE;  	} -	 +  	*end1 = '\0'; -	 -	if( getenv( "BITLBEE_DEBUG" ) ) -		printf( "HTTP response headers:\n%s\n", req->reply_headers ); -	 -	if( evil_server ) + +	if (getenv("BITLBEE_DEBUG")) { +		printf("HTTP response headers:\n%s\n", req->reply_headers); +	} + +	if (evil_server) {  		req->reply_body = end1 + 1; -	else +	} else {  		req->reply_body = end1 + 2; -	 +	} +  	/* Separately allocated space for headers and body. */  	req->sblen = req->body_size = req->reply_headers + req->bytes_read - req->reply_body; -	req->sbuf = req->reply_body = g_memdup( req->reply_body, req->body_size + 1 ); -	req->reply_headers = g_realloc( req->reply_headers, end1 - req->reply_headers + 1 ); -	 -	if( ( end1 = strchr( req->reply_headers, ' ' ) ) != NULL ) -	{ -		if( sscanf( end1 + 1, "%hd", &req->status_code ) != 1 ) -		{ -			req->status_string = g_strdup( "Can't parse status code" ); +	req->sbuf = req->reply_body = g_memdup(req->reply_body, req->body_size + 1); +	req->reply_headers = g_realloc(req->reply_headers, end1 - req->reply_headers + 1); + +	if ((end1 = strchr(req->reply_headers, ' ')) != NULL) { +		if (sscanf(end1 + 1, "%hd", &req->status_code) != 1) { +			req->status_string = g_strdup("Can't parse status code");  			req->status_code = -1; -		} -		else -		{ +		} else {  			char *eol; -			 -			if( evil_server ) -				eol = strchr( end1, '\n' ); -			else -				eol = strchr( end1, '\r' ); -			 -			req->status_string = g_strndup( end1 + 1, eol - end1 - 1 ); -			 + +			if (evil_server) { +				eol = strchr(end1, '\n'); +			} else { +				eol = strchr(end1, '\r'); +			} + +			req->status_string = g_strndup(end1 + 1, eol - end1 - 1); +  			/* Just to be sure... */ -			if( ( eol = strchr( req->status_string, '\r' ) ) ) +			if ((eol = strchr(req->status_string, '\r'))) {  				*eol = 0; -			if( ( eol = strchr( req->status_string, '\n' ) ) ) +			} +			if ((eol = strchr(req->status_string, '\n'))) {  				*eol = 0; +			}  		} -	} -	else -	{ -		req->status_string = g_strdup( "Can't locate status code" ); +	} else { +		req->status_string = g_strdup("Can't locate status code");  		req->status_code = -1;  	} -	 -	if( ( ( req->status_code >= 301 && req->status_code <= 303 ) || -	      req->status_code == 307 ) && 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; -		 +  		/* We might fill it again, so let's not leak any memory. */ -		g_free( req->status_string ); +		g_free(req->status_string);  		req->status_string = NULL; -		 -		loc = strstr( req->reply_headers, "\nLocation: " ); -		if( loc == NULL ) /* We can't handle this redirect... */ -		{ -			req->status_string = g_strdup( "Can't locate Location: header" ); + +		loc = strstr(req->reply_headers, "\nLocation: "); +		if (loc == NULL) { /* We can't handle this redirect... */ +			req->status_string = g_strdup("Can't locate Location: header");  			return TRUE;  		} -		 +  		loc += 11; -		while( *loc == ' ' ) -			loc ++; -		 +		while (*loc == ' ') { +			loc++; +		} +  		/* TODO/FIXME: Possibly have to handle relative redirections,  		   and rewrite Host: headers. Not necessary for now, it's  		   enough for passport authentication like this. */ -		 -		if( *loc == '/' ) -		{ + +		if (*loc == '/') {  			/* Just a different pathname... */ -			 +  			/* Since we don't cache the servername, and since we  			   don't need this yet anyway, I won't implement it. */ -			 -			req->status_string = g_strdup( "Can't handle relative redirects" ); -			 + +			req->status_string = g_strdup("Can't handle relative redirects"); +  			return TRUE; -		} -		else -		{ +		} else {  			/* A whole URL */  			url_t *url;  			char *s, *version, *headers;  			const char *new_method; -			 -			s = strstr( loc, "\r\n" ); -			if( s == NULL ) + +			s = strstr(loc, "\r\n"); +			if (s == NULL) {  				return TRUE; -			 -			url = g_new0( url_t, 1 ); +			} + +			url = g_new0(url_t, 1);  			*s = 0; -			 -			if( !url_set( url, loc ) ) -			{ -				req->status_string = g_strdup( "Malformed redirect URL" ); -				g_free( url ); + +			if (!url_set(url, loc)) { +				req->status_string = g_strdup("Malformed redirect URL"); +				g_free(url);  				return TRUE;  			} -			 +  			/* 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( url ); +			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(url);  				return TRUE;  			}  			headers = 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. ... -			    +  			   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 ) +			if (strncmp(req->request, "GET", 3) == 0) {  				/* GETs never become POSTs. */  				new_method = "GET"; -			else if( req->status_code == 302 || req->status_code == 303 ) +			} 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 +			} else {  				/* 301 de-facto should stay POST, 307 specifally RFC 2616#10.3.8 */  				new_method = "POST"; -			 -			if( ( version = strstr( req->request, " HTTP/" ) ) && -			    ( s = strstr( version, "\r\n" ) ) ) -			{ -				version ++; -				version = g_strndup( version, s - version );  			} -			else -				version = g_strdup( "HTTP/1.0" ); -			 + +			if ((version = strstr(req->request, " HTTP/")) && +			    (s = strstr(version, "\r\n"))) { +				version++; +				version = g_strndup(version, s - version); +			} else { +				version = g_strdup("HTTP/1.0"); +			} +  			/* Okay, this isn't fun! We have to rebuild the request... :-( */ -			new_request = g_strdup_printf( "%s %s %s\r\nHost: %s%s", -			                               new_method, url->file, version, -			                               url->host, headers ); -			 -			new_host = g_strdup( url->host ); +			new_request = g_strdup_printf("%s %s %s\r\nHost: %s%s", +			                              new_method, url->file, version, +			                              url->host, headers); + +			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" ) ) ) +			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 ); -			g_free( version ); +			} + +			g_free(url); +			g_free(version); +		} + +		if (req->ssl) { +			ssl_disconnect(req->ssl); +		} else { +			closesocket(req->fd);  		} -		 -		if( req->ssl ) -			ssl_disconnect( req->ssl ); -		else -			closesocket( req->fd ); -		 +  		req->fd = -1;  		req->ssl = NULL; -		 -		if( getenv( "BITLBEE_DEBUG" ) ) -			printf( "New headers for redirected HTTP request:\n%s\n", new_request ); -	 -		if( new_proto == PROTO_HTTPS ) -		{ -			req->ssl = ssl_connect( new_host, new_port, TRUE, http_ssl_connected, req ); -			if( req->ssl == NULL ) -				error = 1; + +		if (getenv("BITLBEE_DEBUG")) { +			printf("New headers for redirected HTTP request:\n%s\n", new_request);  		} -		else -		{ -			req->fd = proxy_connect( new_host, new_port, http_connected, req ); -			if( req->fd < 0 ) + +		if (new_proto == PROTO_HTTPS) { +			req->ssl = ssl_connect(new_host, new_port, TRUE, http_ssl_connected, req); +			if (req->ssl == NULL) {  				error = 1; +			} +		} else { +			req->fd = proxy_connect(new_host, new_port, http_connected, req); +			if (req->fd < 0) { +				error = 1; +			}  		} -		g_free( new_host ); -		 -		if( error ) -		{ -			req->status_string = g_strdup( "Connection problem during redirect" ); -			g_free( new_request ); +		g_free(new_host); + +		if (error) { +			req->status_string = g_strdup("Connection problem during redirect"); +			g_free(new_request);  			return TRUE;  		} -		 -		g_free( req->request ); -		g_free( req->reply_headers ); -		g_free( req->sbuf ); + +		g_free(req->request); +		g_free(req->reply_headers); +		g_free(req->sbuf);  		req->request = new_request; -		req->request_length = strlen( new_request ); +		req->request_length = strlen(new_request);  		req->bytes_read = req->bytes_written = req->inpa = 0;  		req->reply_headers = req->reply_body = NULL;  		req->sbuf = req->cbuf = NULL;  		req->sblen = req->cblen = 0; -		 +  		return FALSE;  	} -	if( ( s = get_rfc822_header( req->reply_headers, "Content-Length", 0 ) ) && -	    sscanf( s, "%d", &req->content_length ) != 1 ) +	if ((s = get_rfc822_header(req->reply_headers, "Content-Length", 0)) && +	    sscanf(s, "%d", &req->content_length) != 1) {  		req->content_length = -1; -	g_free( s ); -	 -	if( ( s = get_rfc822_header( req->reply_headers, "Transfer-Encoding", 0 ) ) ) -	{ -		if( strcasestr( s, "chunked" ) ) -		{ +	} +	g_free(s); + +	if ((s = get_rfc822_header(req->reply_headers, "Transfer-Encoding", 0))) { +		if (strcasestr(s, "chunked")) {  			req->flags |= HTTPC_CHUNKED;  			req->cbuf = req->sbuf;  			req->cblen = req->sblen; -			 -			req->reply_body = req->sbuf = g_strdup( "" ); + +			req->reply_body = req->sbuf = g_strdup("");  			req->body_size = req->sblen = 0;  		} -		g_free( s ); +		g_free(s);  	} -	 +  	return TRUE;  } -void http_flush_bytes( struct http_request *req, size_t len ) +void http_flush_bytes(struct http_request *req, size_t len)  { -	if( len <= 0 || len > req->body_size || !( req->flags & HTTPC_STREAMING ) ) +	if (len <= 0 || len > req->body_size || !(req->flags & HTTPC_STREAMING)) {  		return; -	 +	} +  	req->reply_body += len;  	req->body_size -= len; -	 -	if( req->reply_body - req->sbuf >= 512 ) -	{ -		char *new = g_memdup( req->reply_body, req->body_size + 1 ); -		g_free( req->sbuf ); + +	if (req->reply_body - req->sbuf >= 512) { +		char *new = g_memdup(req->reply_body, req->body_size + 1); +		g_free(req->sbuf);  		req->reply_body = req->sbuf = new;  		req->sblen = req->body_size;  	}  } -void http_close( struct http_request *req ) +void http_close(struct http_request *req)  { -	if( !req ) +	if (!req) {  		return; -	 -	if( req->inpa > 0 ) -		b_event_remove( req->inpa ); -	 -	if( req->ssl ) -		ssl_disconnect( req->ssl ); -	else -		closesocket( req->fd ); -	 -	http_free( req ); +	} + +	if (req->inpa > 0) { +		b_event_remove(req->inpa); +	} + +	if (req->ssl) { +		ssl_disconnect(req->ssl); +	} else { +		closesocket(req->fd); +	} + +	http_free(req);  } -static void http_free( struct http_request *req ) +static void http_free(struct http_request *req)  { -	g_free( req->request ); -	g_free( req->reply_headers ); -	g_free( req->status_string ); -	g_free( req->sbuf ); -	g_free( req->cbuf ); -	g_free( req ); +	g_free(req->request); +	g_free(req->reply_headers); +	g_free(req->status_string); +	g_free(req->sbuf); +	g_free(req->cbuf); +	g_free(req);  }  | 
