X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=parsers.c;h=d63647d8c03b8d179a0a4fcf076ebe335da226f2;hp=9b4a1298cfc80b1616e0880be55051201b032251;hb=4398286ec2297fdbb7e1faab3e37d2c3ea43e8c8;hpb=565187f94976db71fc5be074862af1ebb5afd77c diff --git a/parsers.c b/parsers.c index 9b4a1298..d63647d8 100644 --- a/parsers.c +++ b/parsers.c @@ -4,7 +4,7 @@ * * Purpose : Declares functions to parse/crunch headers and pages. * - * Copyright : Written by and Copyright (C) 2001-2020 the + * Copyright : Written by and Copyright (C) 2001-2021 the * Privoxy team. https://www.privoxy.org/ * * Based on the Internet Junkbuster originally written @@ -68,7 +68,7 @@ #include #endif -#if !defined(_WIN32) && !defined(__OS2__) +#if !defined(_WIN32) #include #endif @@ -291,6 +291,27 @@ long flush_iob(jb_socket fd, struct iob *iob, unsigned int delay) } +/********************************************************************* + * + * Function : can_add_to_iob + * + * Description : Checks if the given number of bytes can be added to the given iob + * without exceeding the given buffer limit. + * + * Parameters : + * 1 : iob = Destination buffer. + * 2 : buffer_limit = Limit to which the destination may grow + * 3 : n = number of bytes to be added + * + * Returns : TRUE if the given iob can handle given number of bytes + * FALSE buffer limit will be exceeded + * + *********************************************************************/ +int can_add_to_iob(const struct iob *iob, const size_t buffer_limit, size_t n) +{ + return ((size_t)(iob->eod - iob->buf) + n + 1) > buffer_limit ? FALSE : TRUE; +} + /********************************************************************* * * Function : add_to_iob @@ -308,7 +329,7 @@ long flush_iob(jb_socket fd, struct iob *iob, unsigned int delay) * or buffer limit reached. * *********************************************************************/ -jb_err add_to_iob(struct iob *iob, const size_t buffer_limit, char *src, long n) +jb_err add_to_iob(struct iob *iob, const size_t buffer_limit, const char *src, long n) { size_t used, offset, need; char *p; @@ -326,7 +347,7 @@ jb_err add_to_iob(struct iob *iob, const size_t buffer_limit, char *src, long n) if (need > buffer_limit) { log_error(LOG_LEVEL_INFO, - "Buffer limit reached while extending the buffer (iob). Needed: %d. Limit: %d", + "Buffer limit reached while extending the buffer (iob). Needed: %lu. Limit: %lu", need, buffer_limit); return JB_ERR_MEMORY; } @@ -440,7 +461,7 @@ static jb_err decompress_iob_with_brotli(struct client_state *csp) if (decoded_buffer == NULL) { log_error(LOG_LEVEL_ERROR, - "Failed to allocate %d bytes for Brotli decompression", + "Failed to allocate %lu bytes for Brotli decompression", decoded_buffer_size); return JB_ERR_MEMORY; } @@ -461,7 +482,7 @@ static jb_err decompress_iob_with_brotli(struct client_state *csp) csp->iob->size = decoded_buffer_size; log_error(LOG_LEVEL_RE_FILTER, - "Decompression successful. Old size: %d, new size: %d.", + "Decompression successful. Old size: %lu, new size: %lu.", encoded_size, decoded_size); return JB_ERR_OK; @@ -526,7 +547,7 @@ jb_err decompress_iob(struct client_state *csp) * but it should(?) be valid for deflated data also. */ log_error(LOG_LEVEL_ERROR, - "Insufficient data to start decompression. Bytes in buffer: %d", + "Insufficient data to start decompression. Bytes in buffer: %ld", csp->iob->eod - csp->iob->cur); return JB_ERR_COMPRESS; } @@ -727,6 +748,7 @@ jb_err decompress_iob(struct client_state *csp) { log_error(LOG_LEVEL_ERROR, "Buffer limit reached while decompressing iob"); freez(buf); + inflateEnd(&zstr); return JB_ERR_MEMORY; } @@ -745,6 +767,7 @@ jb_err decompress_iob(struct client_state *csp) { log_error(LOG_LEVEL_ERROR, "Out of memory decompressing iob"); freez(buf); + inflateEnd(&zstr); return JB_ERR_MEMORY; } else @@ -815,7 +838,7 @@ jb_err decompress_iob(struct client_state *csp) * Make sure the new uncompressed iob obeys some minimal * consistency conditions. */ - if ((csp->iob->buf <= csp->iob->cur) + if ((csp->iob->buf <= csp->iob->cur) && (csp->iob->cur <= csp->iob->eod) && (csp->iob->eod <= csp->iob->buf + csp->iob->size)) { @@ -823,7 +846,7 @@ jb_err decompress_iob(struct client_state *csp) if (new_size > (size_t)0) { log_error(LOG_LEVEL_RE_FILTER, - "Decompression successful. Old size: %d, new size: %d.", + "Decompression successful. Old size: %lu, new size: %lu.", old_size, new_size); } else @@ -836,10 +859,7 @@ jb_err decompress_iob(struct client_state *csp) else { /* It seems that zlib did something weird. */ - log_error(LOG_LEVEL_ERROR, - "Unexpected error decompressing the buffer (iob): %d==%d, %d>%d, %d<%d", - csp->iob->cur, csp->iob->buf + skip_size, csp->iob->eod, csp->iob->buf, - csp->iob->eod, csp->iob->buf + csp->iob->size); + log_error(LOG_LEVEL_ERROR, "Inconsistent buffer after decompression"); return JB_ERR_COMPRESS; } @@ -1326,9 +1346,11 @@ jb_err sed_https(struct client_state *csp) csp->flags |= CSP_FLAG_CLIENT_HEADER_PARSING_DONE; /* - * Update the last header which may have changed - * due to header additions, + * Update the https headers list which may have + * been modified due to header additions or header + * reordering. */ + csp->https_headers->first = csp->headers->first; csp->https_headers->last = csp->headers->last; csp->headers->first = headers.first; @@ -1489,7 +1511,7 @@ static jb_err header_tagger(struct client_state *csp, char *header) if (NULL == joblist) { - log_error(LOG_LEVEL_RE_FILTER, + log_error(LOG_LEVEL_TAGGING, "Tagger %s has empty joblist. Nothing to do.", b->name); continue; } @@ -1517,7 +1539,7 @@ static jb_err header_tagger(struct client_state *csp, char *header) assert(NULL != header); log_error(LOG_LEVEL_ERROR, "Problems with tagger \'%s\' and header \'%s\': %s", - b->name, *header, pcrs_strerror(hits)); + b->name, header, pcrs_strerror(hits)); } freez(modified_tag); } @@ -1536,11 +1558,20 @@ static jb_err header_tagger(struct client_state *csp, char *header) * no one would do it intentionally. */ freez(tag); - log_error(LOG_LEVEL_INFO, + log_error(LOG_LEVEL_TAGGING, "Tagger \'%s\' created an empty tag. Ignored.", b->name); continue; } + if (list_contains_item(csp->action->multi[ACTION_MULTI_SUPPRESS_TAG], tag)) + { + log_error(LOG_LEVEL_TAGGING, + "Tagger \'%s\' didn't add tag \'%s\': suppressed", + b->name, tag); + freez(tag); + continue; + } + if (!list_contains_item(csp->tags, tag)) { if (JB_ERR_OK != enlist(csp->tags, tag)) @@ -1548,7 +1579,7 @@ static jb_err header_tagger(struct client_state *csp, char *header) log_error(LOG_LEVEL_ERROR, "Insufficient memory to add tag \'%s\', " "based on tagger \'%s\' and header \'%s\'", - tag, b->name, *header); + tag, b->name, header); } else { @@ -1567,7 +1598,7 @@ static jb_err header_tagger(struct client_state *csp, char *header) action_message = "No action bits update necessary."; } - log_error(LOG_LEVEL_HEADER, + log_error(LOG_LEVEL_TAGGING, "Tagger \'%s\' added tag \'%s\'. %s", b->name, tag, action_message); } @@ -1575,7 +1606,7 @@ static jb_err header_tagger(struct client_state *csp, char *header) else { /* XXX: Is this log-worthy? */ - log_error(LOG_LEVEL_HEADER, + log_error(LOG_LEVEL_TAGGING, "Tagger \'%s\' didn't add tag \'%s\'. Tag already present", b->name, tag); } @@ -1668,7 +1699,7 @@ static jb_err filter_header(struct client_state *csp, char **header) continue; } - log_error(LOG_LEVEL_RE_FILTER, "filtering \'%s\' (size %d) with \'%s\' ...", + log_error(LOG_LEVEL_RE_FILTER, "filtering \'%s\' (size %lu) with \'%s\' ...", *header, size, b->name); /* Apply all jobs from the joblist */ @@ -1702,7 +1733,8 @@ static jb_err filter_header(struct client_state *csp, char **header) if (b->dynamic) pcrs_free_joblist(joblist); - log_error(LOG_LEVEL_RE_FILTER, "... produced %d hits (new size %d).", current_hits, size); + log_error(LOG_LEVEL_RE_FILTER, + "... produced %d hits (new size %lu).", current_hits, size); hits += current_hits; } @@ -1994,10 +2026,7 @@ static jb_err get_content_length(const char *header_value, unsigned long long *l * * 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. + * 2 : header = pointer to the Content-Length header * * Returns : JB_ERR_OK on success, or * JB_ERR_MEMORY on out-of-memory error. @@ -2608,6 +2637,37 @@ static jb_err server_adjust_content_encoding(struct client_state *csp, char **he #endif /* defined(FEATURE_ZLIB) */ +/********************************************************************* + * + * Function : header_adjust_content_length + * + * Description : Replace given header with new Content-Length header. + * + * Parameters : + * 1 : 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. + * 2 : content_length = content length value to set + * + * Returns : JB_ERR_OK on success, or + * JB_ERR_MEMORY on out-of-memory error. + * + *********************************************************************/ +jb_err header_adjust_content_length(char **header, size_t content_length) +{ + const size_t header_length = 50; + freez(*header); + *header = malloc(header_length); + if (*header == NULL) + { + return JB_ERR_MEMORY; + } + create_content_length_header(content_length, *header, header_length); + return JB_ERR_OK; +} + + /********************************************************************* * * Function : server_adjust_content_length @@ -2631,14 +2691,10 @@ static jb_err server_adjust_content_length(struct client_state *csp, char **head /* Regenerate header if the content was modified. */ if (csp->flags & CSP_FLAG_MODIFIED) { - const size_t header_length = 50; - freez(*header); - *header = malloc(header_length); - if (*header == NULL) + if (JB_ERR_OK != header_adjust_content_length(header, csp->content_length)) { return JB_ERR_MEMORY; } - create_content_length_header(csp->content_length, *header, header_length); log_error(LOG_LEVEL_HEADER, "Adjusted Content-Length to %llu", csp->content_length); } @@ -2907,7 +2963,7 @@ static jb_err server_last_modified(struct client_state *csp, char **header) seconds = rtime % 60; log_error(LOG_LEVEL_HEADER, - "Randomized: %s (added %d da%s %d hou%s %d minut%s %d second%s", + "Randomized: %s (added %ld da%s %ld hou%s %ld minut%s %ld second%s", *header, days, (days == 1) ? "y" : "ys", hours, (hours == 1) ? "r" : "rs", minutes, (minutes == 1) ? "e" : "es", seconds, (seconds == 1) ? ")" : "s)"); } @@ -3559,7 +3615,7 @@ static jb_err client_if_modified_since(struct client_state *csp, char **header) if (rtime) { - log_error(LOG_LEVEL_HEADER, "Randomizing: %s (random range: %d minut%s)", + log_error(LOG_LEVEL_HEADER, "Randomizing: %s (random range: %ld minut%s)", *header, rtime, (rtime == 1 || rtime == -1) ? "e": "es"); if (negative_range) { @@ -3570,8 +3626,8 @@ static jb_err client_if_modified_since(struct client_state *csp, char **header) } else { - log_error(LOG_LEVEL_ERROR, "Random range is 0. Assuming time transformation test.", - *header); + log_error(LOG_LEVEL_ERROR, + "Random range is 0. Assuming time transformation test."); } tm += rtime * (negative_range ? -1 : 1); timeptr = privoxy_gmtime_r(&tm, &gmt); @@ -3599,7 +3655,7 @@ static jb_err client_if_modified_since(struct client_state *csp, char **header) seconds = rtime % 60; log_error(LOG_LEVEL_HEADER, - "Randomized: %s (%s %d hou%s %d minut%s %d second%s", + "Randomized: %s (%s %ld hou%s %ld minut%s %ld second%s", *header, (negative_range) ? "subtracted" : "added", hours, (hours == 1) ? "r" : "rs", minutes, (minutes == 1) ? "e" : "es", seconds, (seconds == 1) ? ")" : "s)"); @@ -4067,7 +4123,8 @@ static jb_err server_http(struct client_state *csp, char **header) return JB_ERR_PARSE; } - if (csp->http->status == 206) + if (csp->http->status == 101 || + csp->http->status == 206) { csp->content_type = CT_TABOO; } @@ -4497,7 +4554,7 @@ static jb_err parse_header_time(const char *header_time, time_t *result) if (*result != result2) { log_error(LOG_LEVEL_ERROR, "strftime() and strptime() disagree. " - "Format: '%s'. In: '%s', out: '%s'. %d != %d. Rejecting.", + "Format: '%s'. In: '%s', out: '%s'. %ld != %ld. Rejecting.", time_formats[i], header_time, recreated_date, *result, result2); continue; } @@ -4586,7 +4643,11 @@ jb_err get_destination_from_headers(const struct list *headers, struct http_requ return JB_ERR_PARSE; } - p = strdup_or_die(host); + p = string_tolower(host); + if (p == NULL) + { + return JB_ERR_MEMORY; + } chomp(p); q = strdup_or_die(p); @@ -4673,7 +4734,11 @@ jb_err get_destination_from_https_headers(const struct list *headers, struct htt return JB_ERR_PARSE; } - p = strdup_or_die(host); + p = string_tolower(host); + if (p == NULL) + { + return JB_ERR_MEMORY; + } chomp(p); q = strdup_or_die(p); @@ -4834,6 +4899,10 @@ static jb_err handle_conditional_hide_referrer_parameter(char **header, referer[hostlength+17] = '\0'; } referer_url = strstr(referer, "http://"); + if (NULL == referer_url) + { + referer_url = strstr(referer, "https://"); + } if ((NULL == referer_url) || (NULL == strstr(referer_url, host))) { /* Host has changed, Referer is invalid or a https URL. */