X-Git-Url: http://www.privoxy.org/gitweb/?a=blobdiff_plain;f=jcc.c;h=53d325e255ee7e7a6316361784bf99055bc8b7af;hb=e6b3ab33f6caca1a1f3554c4118978d6884b1812;hp=62f54ad912d2d0c26d0ac9be3df4ce08ae131f0f;hpb=2414895d4ca61d56c3b5d1a9dbaa442a5112a4c6;p=privoxy.git diff --git a/jcc.c b/jcc.c index 62f54ad9..53d325e2 100644 --- a/jcc.c +++ b/jcc.c @@ -1,4 +1,4 @@ -const char jcc_rcs[] = "$Id: jcc.c,v 1.134 2007/05/16 14:59:46 fabiankeil Exp $"; +const char jcc_rcs[] = "$Id: jcc.c,v 1.141 2007/08/04 09:56:23 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jcc.c,v $ @@ -33,6 +33,48 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.134 2007/05/16 14:59:46 fabiankeil Exp $" * * Revisions : * $Log: jcc.c,v $ + * Revision 1.141 2007/08/04 09:56:23 fabiankeil + * - Log rejected CONNECT requests with LOG_LEVEL_INFO + * and explain why they were rejected in the first place. + * - Fix the LOG_LEVEL_CLF message for crunches of unallowed + * CONNECT requests. The request line was missing. + * - Add two more XXX reminders as we don't have enough already. + * + * Revision 1.140 2007/07/21 11:51:36 fabiankeil + * As Hal noticed, checking dispatch_cgi() as the last cruncher + * looks like a bug if CGI requests are blocked unintentionally, + * so don't do it unless the user enabled the new config option + * "allow-cgi-request-crunching". + * + * Revision 1.139 2007/07/14 07:46:41 fabiankeil + * - Allow to rewrite the request destination behind the client's back. + * - Turn the weird-looking unconditional for loop that + * reads the client request into a conditional while loop. + * Move the stuff that only runs once out of the loop. + * - Move parts of chat(), server_content_type() and the + * necessary stuff to fix BR#1750917 into get_filter_function(). + * + * Revision 1.138 2007/06/03 18:45:18 fabiankeil + * Temporary workaround for BR#1730105. + * + * Revision 1.137 2007/06/01 18:16:36 fabiankeil + * Use the same mutex for gethostbyname() and gethostbyaddr() to prevent + * deadlocks and crashes on OpenBSD and possibly other OS with neither + * gethostbyname_r() nor gethostaddr_r(). Closes BR#1729174. + * Thanks to Ralf Horstmann for report and solution. + * + * Revision 1.136 2007/06/01 16:41:11 fabiankeil + * Add forward-override{} to change the forwarding settings through + * action sections. This is mainly interesting to forward different + * clients differently (for example based on User-Agent or request + * origin). + * + * Revision 1.135 2007/05/24 17:03:50 fabiankeil + * - Let usage() mention the --chroot parameter. + * - Use read_socket() consistently and always leave + * the last buffer byte alone, even in cases where + * null termination (currently) doesn't matter. + * * Revision 1.134 2007/05/16 14:59:46 fabiankeil * - Fix config file loading on Unix if no config file is specified. * Since r1.97 Privoxy would always interpret the last argument as @@ -939,6 +981,10 @@ static int32 server_thread(void *data); pthread_mutex_t log_mutex; pthread_mutex_t log_init_mutex; +#if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R) +pthread_mutex_t resolver_mutex; +#endif /* !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R) */ + #ifndef HAVE_GMTIME_R pthread_mutex_t gmtime_mutex; #endif /* ndef HAVE_GMTIME_R */ @@ -947,14 +993,6 @@ pthread_mutex_t gmtime_mutex; pthread_mutex_t localtime_mutex; #endif /* ndef HAVE_GMTIME_R */ -#ifndef HAVE_GETHOSTBYADDR_R -pthread_mutex_t gethostbyaddr_mutex; -#endif /* ndef HAVE_GETHOSTBYADDR_R */ - -#ifndef HAVE_GETHOSTBYNAME_R -pthread_mutex_t gethostbyname_mutex; -#endif /* ndef HAVE_GETHOSTBYNAME_R */ - #ifndef HAVE_RANDOM pthread_mutex_t rand_mutex; #endif /* ndef HAVE_RANDOM */ @@ -978,37 +1016,37 @@ static const char VANILLA_WAFER[] = "(copyright_or_otherwise)_applying_to_any_cookie._"; /* HTTP snipplets. */ -const static char CSUCCEED[] = +static const char CSUCCEED[] = "HTTP/1.0 200 Connection established\n" "Proxy-Agent: Privoxy/" VERSION "\r\n\r\n"; -const static char CHEADER[] = +static const char CHEADER[] = "HTTP/1.0 400 Invalid header received from browser\r\n" "Proxy-Agent: Privoxy " VERSION "\r\n" "Content-Type: text/plain\r\n" "Connection: close\r\n\r\n" "Invalid header received from browser.\r\n"; -const static char CFORBIDDEN[] = +static const char CFORBIDDEN[] = "HTTP/1.0 403 Connection not allowable\r\n" "Proxy-Agent: Privoxy " VERSION "\r\n" "X-Hint: If you read this message interactively, then you know why this happens ,-)\r\n" "Connection: close\r\n\r\n"; -const static char FTP_RESPONSE[] = +static const char FTP_RESPONSE[] = "HTTP/1.0 400 Invalid request received from browser\r\n" "Content-Type: text/plain\r\n" "Connection: close\r\n\r\n" "Invalid request. Privoxy doesn't support FTP.\r\n"; -const static char GOPHER_RESPONSE[] = +static const char GOPHER_RESPONSE[] = "HTTP/1.0 400 Invalid request received from browser\r\n" "Content-Type: text/plain\r\n" "Connection: close\r\n\r\n" "Invalid request. Privoxy doesn't support gopher.\r\n"; /* XXX: should be a template */ -const static char MISSING_DESTINATION_RESPONSE[] = +static const char MISSING_DESTINATION_RESPONSE[] = "HTTP/1.0 400 Bad request received from browser\r\n" "Proxy-Agent: Privoxy " VERSION "\r\n" "Content-Type: text/plain\r\n" @@ -1016,7 +1054,7 @@ const static char MISSING_DESTINATION_RESPONSE[] = "Bad request. Privoxy was unable to extract the destination.\r\n"; /* XXX: should be a template */ -const static char NO_SERVER_DATA_RESPONSE[] = +static const char NO_SERVER_DATA_RESPONSE[] = "HTTP/1.0 502 Server or forwarder response empty\r\n" "Proxy-Agent: Privoxy " VERSION "\r\n" "Content-Type: text/plain\r\n" @@ -1025,16 +1063,26 @@ const static char NO_SERVER_DATA_RESPONSE[] = "The connection was closed without sending any data.\r\n"; /* XXX: should be a template */ -const static char NULL_BYTE_RESPONSE[] = +static const char NULL_BYTE_RESPONSE[] = "HTTP/1.0 400 Bad request received from browser\r\n" "Proxy-Agent: Privoxy " VERSION "\r\n" "Content-Type: text/plain\r\n" "Connection: close\r\n\r\n" "Bad request. Null byte(s) before end of request.\r\n"; +/* XXX: should be a template */ +static const char MESSED_UP_REQUEST_RESPONSE[] = + "HTTP/1.0 400 Malformed request after rewriting\r\n" + "Proxy-Agent: Privoxy " VERSION "\r\n" + "Content-Type: text/plain\r\n" + "Connection: close\r\n\r\n" + "Bad request. Messed up with header filters.\r\n"; + /* A function to crunch a response */ typedef struct http_response *(*crunch_func_ptr)(struct client_state *); +typedef char *(*filter_function_ptr)(); + /* Crunch function flags */ #define CF_NO_FLAGS 0 /* Cruncher applies to forced requests as well */ @@ -1050,7 +1098,7 @@ struct cruncher }; /* Complete list of cruncher functions */ -const static struct cruncher crunchers_all[] = { +static const struct cruncher crunchers_all[] = { { direct_response, CF_COUNT_AS_REJECT|CF_IGNORE_FORCE}, { block_url, CF_COUNT_AS_REJECT }, #ifdef FEATURE_TRUST @@ -1062,7 +1110,7 @@ const static struct cruncher crunchers_all[] = { }; /* Light version, used after tags are applied */ -const static struct cruncher crunchers_light[] = { +static const struct cruncher crunchers_light[] = { { block_url, CF_COUNT_AS_REJECT }, { redirect_url, CF_NO_FLAGS }, { NULL, 0 } @@ -1134,7 +1182,7 @@ static void sig_handler(int the_signal) * FALSE if the request doesn't look invalid. * *********************************************************************/ -int client_protocol_is_unsupported(const struct client_state *csp, char *req) +static int client_protocol_is_unsupported(const struct client_state *csp, char *req) { char buf[BUFFER_SIZE]; @@ -1203,7 +1251,7 @@ int client_protocol_is_unsupported(const struct client_state *csp, char *req) * JB_ERR_PARSE if it isn't. * *********************************************************************/ -jb_err get_request_destination_elsewhere(struct client_state *csp, struct list *headers) +static jb_err get_request_destination_elsewhere(struct client_state *csp, struct list *headers) { char *req; @@ -1270,7 +1318,7 @@ jb_err get_request_destination_elsewhere(struct client_state *csp, struct list * * JB_ERR_PARSE if the headers were incomplete. * *********************************************************************/ -jb_err get_server_headers(struct client_state *csp) +static jb_err get_server_headers(struct client_state *csp) { int continue_hack_in_da_house = 0; char * header; @@ -1356,7 +1404,7 @@ jb_err get_server_headers(struct client_state *csp) * Returns : A string with the crunch reason or an error description. * *********************************************************************/ -const char *crunch_reason(const struct http_response *rsp) +static const char *crunch_reason(const struct http_response *rsp) { char * reason = NULL; @@ -1419,7 +1467,7 @@ const char *crunch_reason(const struct http_response *rsp) * Returns : Nothing. * *********************************************************************/ -void send_crunch_response(struct client_state *csp, struct http_response *rsp) +static void send_crunch_response(struct client_state *csp, struct http_response *rsp) { const struct http_request *http = csp->http; char status_code[4]; @@ -1498,7 +1546,7 @@ void send_crunch_response(struct client_state *csp, struct http_response *rsp) * FALSE otherwise. * *********************************************************************/ -int request_contains_null_bytes(const struct client_state *csp, char *buf, int len) +static int request_contains_null_bytes(const struct client_state *csp, char *buf, int len) { size_t c_len; /* Request lenght when treated as C string */ @@ -1555,11 +1603,24 @@ int request_contains_null_bytes(const struct client_state *csp, char *buf, int l * FALSE otherwise. * *********************************************************************/ -int crunch_response_triggered(struct client_state *csp, const struct cruncher crunchers[]) +static int crunch_response_triggered(struct client_state *csp, const struct cruncher crunchers[]) { struct http_response *rsp = NULL; const struct cruncher *c; + /* + * If CGI request crunching is disabled, + * check the CGI dispatcher out of order to + * prevent unintentional blocks or redirects. + */ + if (!(csp->config->feature_flags & RUNTIME_FEATURE_CGI_CRUNCHING) + && (NULL != (rsp = dispatch_cgi(csp)))) + { + /* Deliver, log and free the interception response. */ + send_crunch_response(csp, rsp); + return TRUE; + } + for (c = crunchers; c->cruncher != NULL; c++) { /* @@ -1604,11 +1665,13 @@ int crunch_response_triggered(struct client_state *csp, const struct cruncher cr * Parameters : * 1 : csp = Current client state (buffers, headers, etc...) * 2 : fwd = The forwarding spec used for the request + * XXX: Should use http->fwd instead. + * 3 : request_line = The old request line which will be replaced. * * Returns : Nothing. Terminates in case of memory problems. * *********************************************************************/ -void build_request_line(struct client_state *csp, const struct forward_spec *fwd) +static void build_request_line(struct client_state *csp, const struct forward_spec *fwd, char **request_line) { struct http_request *http = csp->http; @@ -1632,33 +1695,148 @@ void build_request_line(struct client_state *csp, const struct forward_spec *fwd /* * Rebuild the request line. - * XXX: If a http forwarder is used and the HTTP version - * wasn't downgraded, we don't have to rebuild anything. */ - freez(http->cmd); - - http->cmd = strdup(http->gpc); - string_append(&http->cmd, " "); + freez(*request_line); + *request_line = strdup(http->gpc); + string_append(request_line, " "); if (fwd->forward_host) { - string_append(&http->cmd, http->url); + string_append(request_line, http->url); } else { - string_append(&http->cmd, http->path); + string_append(request_line, http->path); } - string_append(&http->cmd, " "); - string_append(&http->cmd, http->ver); + string_append(request_line, " "); + string_append(request_line, http->ver); - if (http->cmd == NULL) + if (*request_line == NULL) { log_error(LOG_LEVEL_FATAL, "Out of memory writing HTTP command"); } - log_error(LOG_LEVEL_HEADER, "New HTTP Request-Line: %s", http->cmd); + log_error(LOG_LEVEL_HEADER, "New HTTP Request-Line: %s", *request_line); +} + + +/********************************************************************* + * + * Function : change_request_destination + * + * Description : Parse a (rewritten) request line and regenerate + * the http request data. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : Forwards the parse_http_request() return code. + * Terminates in case of memory problems. + * + *********************************************************************/ +static jb_err change_request_destination(struct client_state *csp) +{ + struct http_request *http = csp->http; + jb_err err; + + log_error(LOG_LEVEL_INFO, "Rewrite detected: %s", csp->headers->first->str); + free_http_request(http); + err = parse_http_request(csp->headers->first->str, http, csp); + if (JB_ERR_OK != err) + { + log_error(LOG_LEVEL_ERROR, "Couldn't parse rewritten request: %s.", + jb_err_to_string(err)); + } + http->ocmd = strdup(http->cmd); /* XXX: ocmd is a misleading name */ + if (http->ocmd == NULL) + { + log_error(LOG_LEVEL_FATAL, "Out of memory copying rewritten HTTP request line"); + } + + return err; } +/********************************************************************* + * + * Function : get_filter_function + * + * Description : Decides which content filter function has + * to be applied (if any). + * + * XXX: Doesn't handle filter_popups() + * because of the different prototype. Probably + * we should ditch filter_popups() anyway, it's + * even less reliable than popup blocking based + * on pcrs filters. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : The content filter function to run, or + * NULL if no content filter is active + * + *********************************************************************/ +static filter_function_ptr get_filter_function(struct client_state *csp) +{ + filter_function_ptr filter_function = NULL; + + /* + * Are we enabling text mode by force? + */ + if (csp->action->flags & ACTION_FORCE_TEXT_MODE) + { + /* + * Do we really have to? + */ + if (csp->content_type & CT_TEXT) + { + log_error(LOG_LEVEL_HEADER, "Text mode is already enabled."); + } + else + { + csp->content_type |= CT_TEXT; + log_error(LOG_LEVEL_HEADER, "Text mode enabled by force. Take cover!"); + } + } + + if (!(csp->content_type & CT_DECLARED)) + { + /* + * The server didn't bother to declare a MIME-Type. + * Assume it's text that can be filtered. + * + * This also regulary happens with 304 responses, + * therefore logging anything here would cause + * too much noise. + */ + csp->content_type |= CT_TEXT; + } + + + /* + * Choose the applying filter function based on + * the content type and action settings. + */ + if ((csp->content_type & CT_TEXT) && + (csp->rlist != NULL) && + (!list_is_empty(csp->action->multi[ACTION_MULTI_FILTER]))) + { + filter_function = pcrs_filter_response; + } + else if ((csp->content_type & CT_GIF) && + (csp->action->flags & ACTION_DEANIMATE)) + { + filter_function = gif_deanimate_response; + } + else if ((csp->content_type & CT_JPEG) && + (csp->action->flags & ACTION_JPEG_INSPECT)) + { + filter_function = jpeg_inspect_response; + } + + return filter_function; +} + /********************************************************************* * * Function : chat @@ -1695,17 +1873,13 @@ static void chat(struct client_state *csp) const struct forward_spec * fwd; struct http_request *http; int len; /* for buffer sizes (and negative error codes) */ + jb_err err; #ifdef FEATURE_KILL_POPUPS - int block_popups; /* bool, 1==will block popups */ int block_popups_now = 0; /* bool, 1==currently blocking popups */ #endif /* def FEATURE_KILL_POPUPS */ - int pcrs_filter; /* bool, 1==will filter through pcrs */ - int gif_deanimate; /* bool, 1==will deanimate gifs */ - int jpeg_inspect; /* bool, 1==will inspect jpegs */ - /* Function that does the content filtering for the current request */ - char *(*content_filter)() = NULL; + filter_function_ptr content_filter = NULL; /* Skeleton for HTTP response, if we should intercept the request */ struct http_response *rsp; @@ -1723,18 +1897,12 @@ static void chat(struct client_state *csp) * could get blocked here if a client connected, then didn't say anything! */ - for (;;) + do { len = read_socket(csp->cfd, buf, sizeof(buf) - 1); if (len <= 0) break; /* error! */ - if (request_contains_null_bytes(csp, buf, len)) - { - /* NULL bytes found and dealt with, just hang up. */ - return; - } - /* * If there is no memory left for buffering the * request, there is nothing we can do but hang up @@ -1746,15 +1914,35 @@ static void chat(struct client_state *csp) req = get_header(csp); - if (req == NULL) - { - break; /* no HTTP request! */ - } + } while ((NULL != req) && ('\0' == *req)); + + if (NULL != req) + { + /* Request received. Validate and parse it. */ - if (*req == '\0') +#if 0 + /* + * XXX: Temporary disabled to prevent problems + * with POST requests whose bodies are allowed to + * contain NULL bytes. BR#1730105. + * + * The main purpose of this check is to properly + * log stuff like BitTorrent traffic and other junk + * that hits public proxies. It's not required for + * Privoxy to functions as those requests are discarded + * later on anyway. + * + * It probably should be rewritten to only check + * the head of the request. Another option would + * be to let all POST requests pass, although that + * may not be good enough. + */ + if (request_contains_null_bytes(csp, buf, len)) { - continue; /* more to come! */ + /* NULL bytes found and dealt with, just hang up. */ + return; } +#endif /* Does the request line look invalid? */ if (client_protocol_is_unsupported(csp, req)) @@ -1788,19 +1976,13 @@ static void chat(struct client_state *csp) } #endif /* def FEATURE_FORCE_LOAD */ - - switch( parse_http_request(req, http, csp) ) + err = parse_http_request(req, http, csp); + if (JB_ERR_OK != err) { - case JB_ERR_MEMORY: - log_error(LOG_LEVEL_ERROR, "Out of memory while parsing request."); - break; - case JB_ERR_PARSE: - log_error(LOG_LEVEL_ERROR, "Couldn't parse request: %s.", req); - break; + log_error(LOG_LEVEL_ERROR, "Couldn't parse request: %s.", jb_err_to_string(err)); } freez(req); - break; } if (http->cmd == NULL) @@ -1866,9 +2048,75 @@ static void chat(struct client_state *csp) } } - /* decide how to route the HTTP request */ + /* + * Determine the actions for this URL + */ +#ifdef FEATURE_TOGGLE + if (!(csp->flags & CSP_FLAG_TOGGLED_ON)) + { + /* Most compatible set of actions (i.e. none) */ + init_current_action(csp->action); + } + else +#endif /* ndef FEATURE_TOGGLE */ + { + url_actions(http, csp); + } + + /* + * Save a copy of the original request for logging + */ + http->ocmd = strdup(http->cmd); - if ((fwd = forward_url(http, csp)) == NULL) + if (http->ocmd == NULL) + { + log_error(LOG_LEVEL_FATAL, "Out of memory copying HTTP request line"); + } + + enlist(csp->headers, http->cmd); + + /* Append the previously read headers */ + list_append_list_unique(csp->headers, headers); + destroy_list(headers); + + /* + * If the user has not supplied any wafers, and the user has not + * told us to suppress the vanilla wafer, then send the vanilla wafer. + */ + if (list_is_empty(csp->action->multi[ACTION_MULTI_WAFER]) + && ((csp->action->flags & ACTION_VANILLA_WAFER) != 0)) + { + enlist(csp->action->multi[ACTION_MULTI_WAFER], VANILLA_WAFER); + } + + err = sed(client_patterns, add_client_headers, csp); + if (JB_ERR_OK != err) + { + assert(err == JB_ERR_PARSE); + log_error(LOG_LEVEL_FATAL, "Failed to parse client headers"); + } + csp->flags |= CSP_FLAG_CLIENT_HEADER_PARSING_DONE; + + if (strcmp(http->cmd, csp->headers->first->str)) + { + /* + * A header filter rewrote the request line, + * modify the http request accordingly. + */ + if (JB_ERR_OK != change_request_destination(csp)) + { + write_socket(csp->cfd, MESSED_UP_REQUEST_RESPONSE, strlen(MESSED_UP_REQUEST_RESPONSE)); + /* XXX: Use correct size */ + log_error(LOG_LEVEL_CLF, "%s - - [%T] \"Invalid request generated\" 500 0", csp->ip_addr_str); + log_error(LOG_LEVEL_ERROR, "Invalid request line after applying header filters."); + + free_http_request(http); + return; + } + } + + /* decide how to route the HTTP request */ + if (NULL == (fwd = forward_url(http, csp))) { log_error(LOG_LEVEL_FATAL, "gateway spec is NULL!?!? This can't happen!"); /* Never get here - LOG_LEVEL_FATAL causes program exit */ @@ -1910,22 +2158,6 @@ static void chat(struct client_state *csp) * */ - /* - * Determine the actions for this URL - */ -#ifdef FEATURE_TOGGLE - if (!(csp->flags & CSP_FLAG_TOGGLED_ON)) - { - /* Most compatible set of actions (i.e. none) */ - init_current_action(csp->action); - } - else -#endif /* ndef FEATURE_TOGGLE */ - { - url_actions(http, csp); - } - - /* * Check if a CONNECT request is allowable: * In the absence of a +limit-connect action, allow only port 443. @@ -1942,74 +2174,48 @@ static void chat(struct client_state *csp) /* * The response may confuse some clients, * but makes unblocking easier. + * + * XXX: It seems to work with all major browsers, + * so we should consider returning a body by default someday ... */ - log_error(LOG_LEVEL_ERROR, "Marking suspicious CONNECT request from %s for blocking.", - csp->ip_addr_str); + log_error(LOG_LEVEL_INFO, "Request from %s marked for blocking. " + "limit-connect{%s} doesn't allow CONNECT requests to port %d.", + csp->ip_addr_str, csp->action->string[ACTION_STRING_LIMIT_CONNECT], + csp->http->port); csp->action->flags |= ACTION_BLOCK; http->ssl = 0; } else { write_socket(csp->cfd, CFORBIDDEN, strlen(CFORBIDDEN)); - log_error(LOG_LEVEL_CONNECT, "Denying suspicious CONNECT request from %s", csp->ip_addr_str); - log_error(LOG_LEVEL_CLF, "%s - - [%T] \" \" 403 0", csp->ip_addr_str); + log_error(LOG_LEVEL_INFO, "Request from %s denied. " + "limit-connect{%s} doesn't allow CONNECT requests to port %d.", + csp->ip_addr_str, csp->action->string[ACTION_STRING_LIMIT_CONNECT], + csp->http->port); + assert(NULL != csp->http->ocmd); + log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 403 0", csp->ip_addr_str, csp->http->ocmd); + + list_remove_all(csp->headers); + /* + * XXX: For consistency we might want to log a crunch message here. + */ return; } } } - - /* - * Save a copy of the original request for logging - */ - http->ocmd = strdup(http->cmd); - - if (http->ocmd == NULL) - { - log_error(LOG_LEVEL_FATAL, "Out of memory copying HTTP request line"); - } - - /* - * (Re)build the HTTP request for non-SSL requests. - */ if (http->ssl == 0) { - build_request_line(csp, fwd); + freez(csp->headers->first->str); + build_request_line(csp, fwd, &csp->headers->first->str); } - enlist(csp->headers, http->cmd); - - /* Append the previously read headers */ - list_append_list_unique(csp->headers, headers); - destroy_list(headers); - /* - * If the user has not supplied any wafers, and the user has not - * told us to suppress the vanilla wafer, then send the vanilla wafer. - */ - if (list_is_empty(csp->action->multi[ACTION_MULTI_WAFER]) - && ((csp->action->flags & ACTION_VANILLA_WAFER) != 0)) - { - enlist(csp->action->multi[ACTION_MULTI_WAFER], VANILLA_WAFER); - } - - hdr = sed(client_patterns, add_client_headers, csp); + hdr = list_to_text(csp->headers); if (hdr == NULL) { /* FIXME Should handle error properly */ log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header"); } - csp->flags |= CSP_FLAG_CLIENT_HEADER_PARSING_DONE; - -#ifdef FEATURE_KILL_POPUPS - block_popups = ((csp->action->flags & ACTION_NO_POPUPS) != 0); -#endif /* def FEATURE_KILL_POPUPS */ - - pcrs_filter = (csp->rlist != NULL) && /* There are expressions to be used */ - (!list_is_empty(csp->action->multi[ACTION_MULTI_FILTER])); - - gif_deanimate = ((csp->action->flags & ACTION_DEANIMATE) != 0); - - jpeg_inspect = ((csp->action->flags & ACTION_JPEG_INSPECT) != 0); /* * We have a request. Check if one of the crunchers wants it. @@ -2271,8 +2477,12 @@ static void chat(struct client_state *csp) csp->content_length = (size_t)(csp->iob->eod - csp->iob->cur); } - hdr = sed(server_patterns_light, NULL, csp); + if (JB_ERR_OK != sed(server_patterns_light, NULL, csp)) + { + log_error(LOG_LEVEL_FATAL, "Failed to parse server headers."); + } + hdr = list_to_text(csp->headers); if (hdr == NULL) { /* FIXME Should handle error properly */ @@ -2337,8 +2547,11 @@ static void chat(struct client_state *csp) int flushed; log_error(LOG_LEVEL_ERROR, "Flushing header and buffers. Stepping back from filtering."); - - hdr = sed(server_patterns, add_server_headers, csp); + if (JB_ERR_OK != sed(server_patterns, add_server_headers, csp)) + { + log_error(LOG_LEVEL_FATAL, "Failed to parse server headers."); + } + hdr = list_to_text(csp->headers); if (hdr == NULL) { /* @@ -2452,8 +2665,11 @@ static void chat(struct client_state *csp) /* we have now received the entire header. * filter it and send the result to the client */ - - hdr = sed(server_patterns, add_server_headers, csp); + if (JB_ERR_OK != sed(server_patterns, add_server_headers, csp)) + { + log_error(LOG_LEVEL_FATAL, "Failed to parse server headers."); + } + hdr = list_to_text(csp->headers); if (hdr == NULL) { /* FIXME Should handle error properly */ @@ -2471,50 +2687,26 @@ static void chat(struct client_state *csp) freez(hdr); return; } -#ifdef FEATURE_KILL_POPUPS - /* Start blocking popups if appropriate. */ - - if ((csp->content_type & CT_TEXT) && /* It's a text / * MIME-Type */ - !http->ssl && /* We talk plaintext */ - block_popups) /* Policy allows */ - { - block_popups_now = 1; - /* - * Filter the part of the body that came in the same read - * as the last headers: - */ - filter_popups(csp->iob->cur, csp); - } - -#endif /* def FEATURE_KILL_POPUPS */ - /* Buffer and pcrs filter this if appropriate. */ - if ((csp->content_type & CT_TEXT) && /* It's a text / * MIME-Type */ - !http->ssl && /* We talk plaintext */ - pcrs_filter) /* Policy allows */ - { - content_filter = pcrs_filter_response; - } - - /* Buffer and gif_deanimate this if appropriate. */ - - if ((csp->content_type & CT_GIF) && /* It's an image/gif MIME-Type */ - !http->ssl && /* We talk plaintext */ - gif_deanimate) /* Policy allows */ + if (!http->ssl) /* We talk plaintext */ { - content_filter = gif_deanimate_response; - } - /* Buffer and jpg_inspect this if appropriate. */ - - if ((csp->content_type & CT_JPEG) && /* It's an image/jpeg MIME-Type */ - !http->ssl && /* We talk plaintext */ - jpeg_inspect) /* Policy allows */ - { - content_filter = jpeg_inspect_response; +#ifdef FEATURE_KILL_POPUPS + /* Start blocking popups if appropriate. */ + if ((csp->content_type & CT_TEXT) && /* It's a text / * MIME-Type */ + (csp->action->flags & ACTION_NO_POPUPS) != 0) /* Policy allows */ + { + block_popups_now = 1; + /* + * Filter the part of the body that came in the same read + * as the last headers: + */ + filter_popups(csp->iob->cur, csp); + } +#endif /* def FEATURE_KILL_POPUPS */ + content_filter = get_filter_function(csp); } - /* * Only write if we're not buffering for content modification */ @@ -2642,7 +2834,7 @@ static int32 server_thread(void *data) * Returns : No. ,-) * *********************************************************************/ -void usage(const char *myname) +static void usage(const char *myname) { printf("Privoxy version " VERSION " (" HOME_PAGE_URL ")\n" "Usage: %s " @@ -2672,7 +2864,7 @@ void usage(const char *myname) * Returns : Void, exits in case of errors. * *********************************************************************/ -void initialize_mutexes() +static void initialize_mutexes(void) { int err = 0; @@ -2690,7 +2882,14 @@ void initialize_mutexes() * * For example older FreeBSD versions (< 6.x?) * have no gethostbyname_r, but gethostbyname is - * thead safe. + * thread safe. + */ +#if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R) + if (!err) err = pthread_mutex_init(&resolver_mutex, 0); +#endif /* !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R) */ + /* + * XXX: should we use a single mutex for + * localtime() and gmtime() as well? */ #ifndef HAVE_GMTIME_R if (!err) err = pthread_mutex_init(&gmtime_mutex, 0); @@ -2700,14 +2899,6 @@ void initialize_mutexes() if (!err) err = pthread_mutex_init(&localtime_mutex, 0); #endif /* ndef HAVE_GMTIME_R */ -#ifndef HAVE_GETHOSTBYADDR_R - if (!err) err = pthread_mutex_init(&gethostbyaddr_mutex, 0); -#endif /* ndef HAVE_GETHOSTBYADDR_R */ - -#ifndef HAVE_GETHOSTBYNAME_R - if (!err) err = pthread_mutex_init(&gethostbyname_mutex, 0); -#endif /* ndef HAVE_GETHOSTBYNAME_R */ - #ifndef HAVE_RANDOM if (!err) err = pthread_mutex_init(&rand_mutex, 0); #endif /* ndef HAVE_RANDOM */