X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=parsers.c;h=5ff9eea9503b58880b00cdbb9587a2b610f6738b;hp=2bd062ba0f66db467ef27872da558b05845c1015;hb=058777fc9062317845554178fc6a40ac255d934c;hpb=7d25d05eea40bd05d56b38dce51fac4ee5c53cb5 diff --git a/parsers.c b/parsers.c index 2bd062ba..5ff9eea9 100644 --- a/parsers.c +++ b/parsers.c @@ -1,4 +1,4 @@ -const char parsers_rcs[] = "$Id: parsers.c,v 1.108 2007/08/28 18:21:03 fabiankeil Exp $"; +const char parsers_rcs[] = "$Id: parsers.c,v 1.122 2008/03/28 15:13:39 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/parsers.c,v $ @@ -44,6 +44,64 @@ const char parsers_rcs[] = "$Id: parsers.c,v 1.108 2007/08/28 18:21:03 fabiankei * * Revisions : * $Log: parsers.c,v $ + * Revision 1.122 2008/03/28 15:13:39 fabiankeil + * Remove inspect-jpegs action. + * + * Revision 1.121 2008/01/05 21:37:03 fabiankeil + * Let client_range() also handle Request-Range headers + * which apparently are still supported by many servers. + * + * Revision 1.120 2008/01/04 17:43:45 fabiankeil + * Improve the warning messages that get logged if the action files + * "enable" filters but no filters of that type have been loaded. + * + * Revision 1.119 2007/12/28 18:32:51 fabiankeil + * In server_content_type(): + * - Don't require leading white space when detecting image content types. + * - Change '... not replaced ...' message to sound less crazy if the text + * type actually is 'text/plain'. + * - Mark the 'text/plain == binary data' assumption for removal. + * - Remove a bunch of trailing white space. + * + * Revision 1.118 2007/12/28 16:56:35 fabiankeil + * Minor server_content_disposition() changes: + * - Don't regenerate the header name all lower-case. + * - Some white space fixes. + * - Remove useless log message in case of ENOMEM. + * + * Revision 1.117 2007/12/06 18:11:50 fabiankeil + * Garbage-collect the code to add a X-Forwarded-For + * header as it seems to be mostly used by accident. + * + * Revision 1.116 2007/12/01 13:04:22 fabiankeil + * Fix a crash on mingw32 with some Last Modified times in the future. + * + * Revision 1.115 2007/11/02 16:52:50 fabiankeil + * Remove a "can't happen" error block which, over + * time, mutated into a "guaranteed to happen" block. + * + * Revision 1.114 2007/10/19 16:56:26 fabiankeil + * - Downgrade "Buffer limit reached" message to LOG_LEVEL_INFO. + * - Use shiny new content_filters_enabled() in client_range(). + * + * Revision 1.113 2007/10/10 17:29:57 fabiankeil + * I forgot about Poland. + * + * Revision 1.112 2007/10/09 16:38:40 fabiankeil + * Remove Range and If-Range headers if content filtering is enabled. + * + * Revision 1.111 2007/10/04 18:07:00 fabiankeil + * Move ACTION_VANILLA_WAFER handling from jcc's chat() into + * client_cookie_adder() to make sure send-vanilla-wafer can be + * controlled through tags (and thus regression-tested). + * + * Revision 1.110 2007/09/29 10:42:37 fabiankeil + * - Remove "scanning headers for" log message again. + * - Some more whitespace fixes. + * + * Revision 1.109 2007/09/08 14:25:48 fabiankeil + * Refactor client_referrer() and add conditional-forge parameter. + * * Revision 1.108 2007/08/28 18:21:03 fabiankeil * A bunch of whitespace fixes, pointy hat to me. * @@ -785,6 +843,7 @@ static jb_err client_accept_language (struct client_state *csp, char **header static jb_err client_if_none_match (struct client_state *csp, char **header); static jb_err crunch_client_header (struct client_state *csp, char **header); static jb_err client_x_filter (struct client_state *csp, char **header); +static jb_err client_range (struct client_state *csp, char **header); static jb_err server_set_cookie (struct client_state *csp, char **header); static jb_err server_content_type (struct client_state *csp, char **header); static jb_err server_content_length (struct client_state *csp, char **header); @@ -797,9 +856,7 @@ static jb_err server_last_modified (struct client_state *csp, char **header static jb_err server_content_disposition(struct client_state *csp, char **header); static jb_err client_host_adder (struct client_state *csp); -static jb_err client_cookie_adder (struct client_state *csp); static jb_err client_xtra_adder (struct client_state *csp); -static jb_err client_x_forwarded_adder(struct client_state *csp); static jb_err connection_close_adder (struct client_state *csp); static jb_err create_forged_referrer(char **header, const char *hostport); @@ -824,6 +881,9 @@ const struct parsers client_patterns[] = { { "max-forwards:", 13, client_max_forwards }, { "Accept-Language:", 16, client_accept_language }, { "if-none-match:", 14, client_if_none_match }, + { "Range:", 6, client_range }, + { "Request-Range:", 14, client_range }, + { "If-Range:", 9, client_range }, { "X-Filter:", 9, client_x_filter }, { "*", 0, crunch_client_header }, { "*", 0, filter_header }, @@ -857,15 +917,12 @@ const struct parsers server_patterns_light[] = { const add_header_func_ptr add_client_headers[] = { client_host_adder, - client_cookie_adder, - client_x_forwarded_adder, client_xtra_adder, /* Temporarily disabled: client_accept_encoding_adder, */ connection_close_adder, NULL }; - const add_header_func_ptr add_server_headers[] = { connection_close_adder, NULL @@ -943,7 +1000,7 @@ jb_err add_to_iob(struct client_state *csp, char *buf, int n) */ if (need > csp->config->buffer_limit) { - log_error(LOG_LEVEL_ERROR, "Buffer limit reached while extending the buffer (iob)"); + log_error(LOG_LEVEL_INFO, "Buffer limit reached while extending the buffer (iob)"); return JB_ERR_MEMORY; } @@ -1104,7 +1161,7 @@ jb_err decompress_iob(struct client_state *csp) * The number of bytes to skip should be positive * and we'd like to stay in the buffer. */ - if((skip_bytes < 0) || (skip_bytes >= (csp->iob->eod - cur))) + if ((skip_bytes < 0) || (skip_bytes >= (csp->iob->eod - cur))) { log_error(LOG_LEVEL_ERROR, "Unreasonable amount of bytes to skip (%d). Stopping decompression", @@ -1481,8 +1538,6 @@ static jb_err scan_headers(struct client_state *csp) struct list_entry *h; /* Header */ jb_err err = JB_ERR_OK; - log_error(LOG_LEVEL_HEADER, "scanning headers for: %s", csp->http->url); - for (h = csp->headers->first; (err == JB_ERR_OK) && (h != NULL) ; h = h->next) { /* Header crunch()ed in previous run? -> ignore */ @@ -1507,6 +1562,8 @@ static jb_err scan_headers(struct client_state *csp) * As a side effect it frees the space used by the original * header lines. * + * XXX: should be split to remove the first_run hack. + * * Parameters : * 1 : pats = list of patterns to match against headers * 2 : more_headers = list of functions to add more @@ -1646,7 +1703,8 @@ static jb_err header_tagger(struct client_state *csp, char *header) if (0 == found_filters) { - log_error(LOG_LEVEL_ERROR, "Unable to get current state of regex tagging."); + log_error(LOG_LEVEL_ERROR, "Inconsistent configuration: " + "tagging enabled, but no taggers available."); return(JB_ERR_OK); } @@ -1863,7 +1921,8 @@ static jb_err filter_header(struct client_state *csp, char **header) if (0 == found_filters) { - log_error(LOG_LEVEL_ERROR, "Unable to get current state of regexp filtering."); + log_error(LOG_LEVEL_ERROR, "Inconsistent configuration: " + "header filtering enabled, but no matching filters available."); return(JB_ERR_OK); } @@ -1936,7 +1995,7 @@ static jb_err filter_header(struct client_state *csp, char **header) /* RegEx failure */ log_error(LOG_LEVEL_ERROR, "Filtering \'%s\' with \'%s\' didn't work out: %s", *header, b->name, pcrs_strerror(matches)); - if( newheader != NULL) + if (newheader != NULL) { log_error(LOG_LEVEL_ERROR, "Freeing what's left: %s", newheader); freez(newheader); @@ -2042,6 +2101,7 @@ static jb_err crumble(struct client_state *csp, char **header) return JB_ERR_OK; } + /********************************************************************* * * Function : crunch_server_header @@ -2128,39 +2188,40 @@ static jb_err server_content_type(struct client_state *csp, char **header) if (!(csp->content_type & CT_TABOO)) { - if ((strstr(*header, " text/") && !strstr(*header, "plain")) + /* + * XXX: The assumption that text/plain is a sign of + * binary data seems to be somewhat unreasonable nowadays + * and should be dropped after 3.0.8 is out. + */ + if ((strstr(*header, "text/") && !strstr(*header, "plain")) || strstr(*header, "xml") || strstr(*header, "application/x-javascript")) { csp->content_type |= CT_TEXT; } - else if (strstr(*header, " image/gif")) + else if (strstr(*header, "image/gif")) { csp->content_type |= CT_GIF; } - else if (strstr(*header, " image/jpeg")) - { - csp->content_type |= CT_JPEG; - } } /* * Are we messing with the content type? - */ + */ if (csp->action->flags & ACTION_CONTENT_TYPE_OVERWRITE) - { + { /* * Make sure the user doesn't accidently * change the content type of binary documents. - */ + */ if ((csp->content_type & CT_TEXT) || (csp->action->flags & ACTION_FORCE_TEXT_MODE)) - { + { freez(*header); *header = strdup("Content-Type: "); string_append(header, csp->action->string[ACTION_STRING_CONTENT_TYPE]); if (header == NULL) - { + { log_error(LOG_LEVEL_HEADER, "Insufficient memory to replace Content-Type!"); return JB_ERR_MEMORY; } @@ -2168,10 +2229,11 @@ static jb_err server_content_type(struct client_state *csp, char **header) } else { - log_error(LOG_LEVEL_HEADER, "%s not replaced. It doesn't look like text. " - "Enable force-text-mode if you know what you're doing.", *header); + log_error(LOG_LEVEL_HEADER, "%s not replaced. " + "It doesn't look like a content type that should be filtered. " + "Enable force-text-mode if you know what you're doing.", *header); } - } + } return JB_ERR_OK; } @@ -2398,11 +2460,12 @@ static jb_err server_content_md5(struct client_state *csp, char **header) return JB_ERR_OK; } + /********************************************************************* * * Function : server_content_disposition * - * Description : If enabled, blocks or modifies the "content-disposition" header. + * Description : If enabled, blocks or modifies the "Content-Disposition" header. * Called from `sed'. * * Parameters : @@ -2421,17 +2484,17 @@ static jb_err server_content_disposition(struct client_state *csp, char **header const char *newval; /* - * Are we messing with the content-disposition header? + * Are we messing with the Content-Disposition header? */ if ((csp->action->flags & ACTION_HIDE_CONTENT_DISPOSITION) == 0) { - /*Me tinks not*/ + /* Me tinks not */ return JB_ERR_OK; } newval = csp->action->string[ACTION_STRING_CONTENT_DISPOSITION]; - if ((newval == NULL) || (0 == strcmpic(newval, "block")) ) + if ((newval == NULL) || (0 == strcmpic(newval, "block"))) { /* * Blocking content-disposition header @@ -2443,24 +2506,22 @@ static jb_err server_content_disposition(struct client_state *csp, char **header else { /* - * Replacing content-disposition header + * Replacing Content-Disposition header */ freez(*header); - *header = strdup("content-disposition: "); - string_append(header, newval); + *header = strdup("Content-Disposition: "); + string_append(header, newval); - if (*header == NULL) + if (*header != NULL) { - log_error(LOG_LEVEL_HEADER, "Insufficent memory. content-disposition header not fully replaced."); - } - else - { - log_error(LOG_LEVEL_HEADER, "content-disposition header crunched and replaced with: %s", *header); + log_error(LOG_LEVEL_HEADER, + "Content-Disposition header crunched and replaced with: %s", *header); } } return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK; } + /********************************************************************* * * Function : server_last_modified @@ -2558,7 +2619,16 @@ static jb_err server_last_modified(struct client_state *csp, char **header) rtime = (long int)difftime(now, last_modified); if (rtime) { + int negative = 0; + + if (rtime < 0) + { + rtime *= -1; + negative = 1; + log_error(LOG_LEVEL_HEADER, "Server time in the future."); + } rtime = pick_from_range(rtime); + if (negative) rtime *= -1; last_modified += rtime; #ifdef HAVE_GMTIME_R timeptr = gmtime_r(&last_modified, &gmt); @@ -2580,7 +2650,7 @@ static jb_err server_last_modified(struct client_state *csp, char **header) return JB_ERR_MEMORY; } - if(LOG_LEVEL_HEADER & debug) /* Save cycles if the user isn't interested. */ + if (LOG_LEVEL_HEADER & debug) /* Save cycles if the user isn't interested. */ { days = rtime / (3600 * 24); hours = rtime / 3600 % 24; @@ -2904,6 +2974,7 @@ static jb_err client_uagent(struct client_state *csp, char **header) return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK; } + /********************************************************************* * * Function : client_ua @@ -3034,19 +3105,7 @@ static jb_err client_send_cookie(struct client_state *csp, char **header) *********************************************************************/ jb_err client_x_forwarded(struct client_state *csp, char **header) { - if ((csp->action->flags & ACTION_HIDE_FORWARDED) == 0) - { - /* Save it so we can re-add it later */ - freez(csp->x_forwarded); - csp->x_forwarded = *header; - - /* - * Always set *header = NULL, since this information - * will be sent at the end of the header. - */ - *header = NULL; - } - else + if ((csp->action->flags & ACTION_HIDE_FORWARDED) != 0) { freez(*header); log_error(LOG_LEVEL_HEADER, "crunched x-forwarded-for!"); @@ -3095,17 +3154,6 @@ static jb_err client_max_forwards(struct client_state *csp, char **header) log_error(LOG_LEVEL_ERROR, "Crunching invalid header: %s", *header); freez(*header); } - else - { - /* - * Not supposed to be reached. direct_response() which - * was already called earlier in chat() should have - * intercepted the request. - */ - log_error(LOG_LEVEL_ERROR, - "Non-intercepted %s request with Max-Forwards zero!", csp->http->gpc); - assert(max_forwards != 0); - } } else { @@ -3197,6 +3245,7 @@ static jb_err client_host(struct client_state *csp, char **header) return JB_ERR_OK; } + /********************************************************************* * * Function : client_if_modified_since @@ -3261,11 +3310,11 @@ static jb_err client_if_modified_since(struct client_state *csp, char **header) else { rtime = strtol(newval, &endptr, 0); - if(rtime) + if (rtime) { log_error(LOG_LEVEL_HEADER, "Randomizing: %s (random range: %d minut%s)", *header, rtime, (rtime == 1 || rtime == -1) ? "e": "es"); - if(rtime < 0) + if (rtime < 0) { rtime *= -1; negative = 1; @@ -3300,7 +3349,7 @@ static jb_err client_if_modified_since(struct client_state *csp, char **header) return JB_ERR_MEMORY; } - if(LOG_LEVEL_HEADER & debug) /* Save cycles if the user isn't interested. */ + if (LOG_LEVEL_HEADER & debug) /* Save cycles if the user isn't interested. */ { hours = rtime / 3600; minutes = rtime / 60 % 60; @@ -3317,6 +3366,7 @@ static jb_err client_if_modified_since(struct client_state *csp, char **header) return JB_ERR_OK; } + /********************************************************************* * * Function : client_if_none_match @@ -3345,6 +3395,7 @@ static jb_err client_if_none_match(struct client_state *csp, char **header) return JB_ERR_OK; } + /********************************************************************* * * Function : client_x_filter @@ -3390,6 +3441,40 @@ jb_err client_x_filter(struct client_state *csp, char **header) return JB_ERR_OK; } + +/********************************************************************* + * + * Function : client_range + * + * Description : Removes Range, Request-Range and If-Range headers if + * content filtering is enabled. If the client's version + * of the document has been altered by Privoxy, the server + * could interpret the range differently than the client + * intended in which case the user could end up with + * corrupted content. + * + * 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_range(struct client_state *csp, char **header) +{ + if (content_filters_enabled(csp)) + { + log_error(LOG_LEVEL_HEADER, "Content filtering is enabled." + " Crunching: \'%s\' to prevent range-mismatch problems.", *header); + freez(*header); + } + + return JB_ERR_OK; +} + /* the following functions add headers directly to the header list */ /********************************************************************* @@ -3444,57 +3529,6 @@ static jb_err client_host_adder(struct client_state *csp) } -/********************************************************************* - * - * Function : client_cookie_adder - * - * Description : Used in the add_client_headers list to add "wafers". - * Called from `sed'. - * - * Parameters : - * 1 : csp = Current client state (buffers, headers, etc...) - * - * Returns : JB_ERR_OK on success, or - * JB_ERR_MEMORY on out-of-memory error. - * - *********************************************************************/ -jb_err client_cookie_adder(struct client_state *csp) -{ - char *tmp; - struct list_entry *wafer; - struct list_entry *wafer_list = csp->action->multi[ACTION_MULTI_WAFER]->first; - jb_err err; - - if (NULL == wafer_list) - { - /* Nothing to do */ - return JB_ERR_OK; - } - - tmp = strdup("Cookie: "); - - for (wafer = wafer_list; (NULL != tmp) && (NULL != wafer); wafer = wafer->next) - { - if (wafer != wafer_list) - { - /* As this isn't the first wafer, we need a delimiter. */ - string_append(&tmp, "; "); - } - string_join(&tmp, cookie_encode(wafer->str)); - } - - if (tmp == NULL) - { - return JB_ERR_MEMORY; - } - - log_error(LOG_LEVEL_HEADER, "addh: %s", tmp); - err = enlist(csp->headers, tmp); - free(tmp); - return err; -} - - #if 0 /********************************************************************* * @@ -3559,53 +3593,6 @@ static jb_err client_xtra_adder(struct client_state *csp) } -/********************************************************************* - * - * Function : client_x_forwarded_adder - * - * Description : Used in the add_client_headers list. Called from `sed'. - * - * Parameters : - * 1 : csp = Current client state (buffers, headers, etc...) - * - * Returns : JB_ERR_OK on success, or - * JB_ERR_MEMORY on out-of-memory error. - * - *********************************************************************/ -static jb_err client_x_forwarded_adder(struct client_state *csp) -{ - char *p = NULL; - jb_err err; - - if ((csp->action->flags & ACTION_HIDE_FORWARDED) != 0) - { - return JB_ERR_OK; - } - - if (csp->x_forwarded) - { - p = strdup(csp->x_forwarded); - string_append(&p, ", "); - } - else - { - p = strdup("X-Forwarded-For: "); - } - string_append(&p, csp->ip_addr_str); - - if (p == NULL) - { - return JB_ERR_MEMORY; - } - - log_error(LOG_LEVEL_HEADER, "addh: %s", p); - err = enlist(csp->headers, p); - free(p); - - return err; -} - - /********************************************************************* * * Function : connection_close_adder @@ -3950,6 +3937,7 @@ int strclean(const char *string, const char *substring) } #endif /* def FEATURE_FORCE_LOAD */ + /********************************************************************* * * Function : parse_header_time @@ -3999,6 +3987,7 @@ static jb_err parse_header_time(const char *header_time, time_t *result) } + /********************************************************************* * * Function : get_destination_from_headers