X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=parsers.c;h=bb45a7b4ceaa1ffbce4164f3385748ebd62e8140;hp=2e7822dcc0f443d4e16019a3b8209835e8d7ada8;hb=4e1aa4a9c01464807e7033e9d47387f6d6bda7e7;hpb=fdf66c5b172bbca2eb4b4255dc4d3a8911cabffa diff --git a/parsers.c b/parsers.c index 2e7822dc..bb45a7b4 100644 --- a/parsers.c +++ b/parsers.c @@ -1,4 +1,4 @@ -const char parsers_rcs[] = "$Id: parsers.c,v 1.179 2009/06/16 15:42:28 fabiankeil Exp $"; +const char parsers_rcs[] = "$Id: parsers.c,v 1.189 2009/07/05 12:04:46 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/parsers.c,v $ @@ -156,6 +156,7 @@ static jb_err server_content_disposition(struct client_state *csp, char **header #ifdef FEATURE_CONNECTION_KEEP_ALIVE static jb_err server_save_content_length(struct client_state *csp, char **header); static jb_err server_keep_alive(struct client_state *csp, char **header); +static jb_err client_keep_alive(struct client_state *csp, char **header); #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ static jb_err client_host_adder (struct client_state *csp); @@ -201,7 +202,9 @@ static const struct parsers client_patterns[] = { { "TE:", 3, client_te }, { "Host:", 5, client_host }, { "if-modified-since:", 18, client_if_modified_since }, -#ifndef FEATURE_CONNECTION_KEEP_ALIVE +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + { "Keep-Alive:", 11, client_keep_alive }, +#else { "Keep-Alive:", 11, crumble }, #endif { "connection:", 11, client_connection }, @@ -1580,7 +1583,11 @@ static jb_err filter_header(struct client_state *csp, char **header) *********************************************************************/ static jb_err server_connection(struct client_state *csp, char **header) { - if (!strcmpic(*header, "Connection: keep-alive")) + if (!strcmpic(*header, "Connection: keep-alive") +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED) +#endif + ) { #ifdef FEATURE_CONNECTION_KEEP_ALIVE if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)) @@ -1620,7 +1627,7 @@ static jb_err server_connection(struct client_state *csp, char **header) * * Function : server_keep_alive * - * Description : Stores the servers keep alive timeout. + * Description : Stores the server's keep alive timeout. * * Parameters : * 1 : csp = Current client state (buffers, headers, etc...) @@ -1662,6 +1669,54 @@ static jb_err server_keep_alive(struct client_state *csp, char **header) return JB_ERR_OK; } + + +/********************************************************************* + * + * Function : client_keep_alive + * + * Description : Stores the client's keep alive timeout. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : header = On input, pointer to header to modify. + * On output, pointer to the modified header, or NULL + * to remove the header. This function frees the + * original string if necessary. + * + * Returns : JB_ERR_OK. + * + *********************************************************************/ +static jb_err client_keep_alive(struct client_state *csp, char **header) +{ + unsigned int keep_alive_timeout; + const char *timeout_position = strstr(*header, ": "); + + if ((NULL == timeout_position) + || (1 != sscanf(timeout_position, ": %u", &keep_alive_timeout))) + { + log_error(LOG_LEVEL_ERROR, "Couldn't parse: %s", *header); + } + else + { + if (keep_alive_timeout < csp->config->keep_alive_timeout) + { + log_error(LOG_LEVEL_HEADER, + "Reducing keep-alive timeout from %u to %u.", + csp->config->keep_alive_timeout, keep_alive_timeout); + csp->server_connection.keep_alive_timeout = keep_alive_timeout; + } + else + { + /* XXX: Is this log worthy? */ + log_error(LOG_LEVEL_HEADER, + "Client keep-alive timeout is %u. Sticking with %u.", + keep_alive_timeout, csp->server_connection.keep_alive_timeout); + } + } + + return JB_ERR_OK; +} #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ @@ -2108,7 +2163,11 @@ static jb_err server_save_content_length(struct client_state *csp, char **header assert(*(*header+14) == ':'); +#ifdef _WIN32 + if (1 != sscanf(*header+14, ": %I64u", &content_length)) +#else if (1 != sscanf(*header+14, ": %llu", &content_length)) +#endif { log_error(LOG_LEVEL_ERROR, "Crunching invalid header: %s", *header); freez(*header); @@ -2334,7 +2393,16 @@ static jb_err server_last_modified(struct client_state *csp, char **header) #else timeptr = gmtime(&last_modified); #endif - strftime(newheader, sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr); + if ((NULL == timeptr) || !strftime(newheader, + sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr)) + { + log_error(LOG_LEVEL_ERROR, + "Randomizing '%s' failed. Crunching the header without replacement.", + *header); + freez(*header); + return JB_ERR_OK; + } + freez(*header); *header = strdup("Last-Modified: "); string_append(header, newheader); @@ -3053,12 +3121,13 @@ static jb_err client_if_modified_since(struct client_state *csp, char **header) #else timeptr = gmtime(&tm); #endif - if (!strftime(newheader, sizeof(newheader), - "%a, %d %b %Y %H:%M:%S GMT", timeptr)) + if ((NULL == timeptr) || !strftime(newheader, + sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr)) { log_error(LOG_LEVEL_ERROR, - "Randomizing %s failed. Keeping the header unmodified.", + "Randomizing '%s' failed. Crunching the header without replacement.", *header); + freez(*header); return JB_ERR_OK; } @@ -3393,8 +3462,21 @@ static jb_err server_connection_adder(struct client_state *csp) if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE) && (NULL != response_status_line) - && !strncmpic(response_status_line, "HTTP/1.1", 8)) + && !strncmpic(response_status_line, "HTTP/1.1", 8) +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED) +#endif + && (csp->http->status == 200) + ) { + /* + * XXX: not doing this for status codes other than 200 works + * around problems with broken servers that will keep the + * connection open, but terminate the connection when the + * next request arrives. Once we are able to figure out which + * requests are safe to send again, this will probably no + * longer be necessary. + */ log_error(LOG_LEVEL_HEADER, "A HTTP/1.1 response " "without Connection header implies keep-alive."); csp->flags |= CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE; @@ -3427,7 +3509,8 @@ static jb_err server_proxy_connection_adder(struct client_state *csp) static const char proxy_connection_header[] = "Proxy-Connection: keep-alive"; jb_err err = JB_ERR_OK; - if ((csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE)) + if ((csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE) + && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED)) { log_error(LOG_LEVEL_HEADER, "Adding: %s", proxy_connection_header); err = enlist(csp->headers, proxy_connection_header); @@ -3464,7 +3547,8 @@ static jb_err client_connection_header_adder(struct client_state *csp) #ifdef FEATURE_CONNECTION_KEEP_ALIVE if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE) - && (csp->http->ssl == 0)) + && (csp->http->ssl == 0) + && !strcmpic(csp->http->ver, "HTTP/1.1")) { csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE; } @@ -4037,6 +4121,9 @@ static const char *get_appropiate_connection_header(const struct client_state *c static const char connection_close[] = "Connection: close"; if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE) +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED) +#endif && (csp->http->ssl == 0)) { return connection_keep_alive;