X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=cgi.c;h=0583f88a345c17daab459877f2e6f051d7f913fe;hp=9b0f4e3d007f839b0166093e093982b814790653;hb=2f946641e6706380d376f6946f30ebe239cc94bc;hpb=484c53d05cfe647a9a10981ba45e9579e33dcfe8 diff --git a/cgi.c b/cgi.c index 9b0f4e3d..0583f88a 100644 --- a/cgi.c +++ b/cgi.c @@ -1,4 +1,4 @@ -const char cgi_rcs[] = "$Id: cgi.c,v 1.118 2009/05/28 17:07:42 fabiankeil Exp $"; +const char cgi_rcs[] = "$Id: cgi.c,v 1.130 2011/04/19 13:00:47 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/cgi.c,v $ @@ -49,6 +49,10 @@ const char cgi_rcs[] = "$Id: cgi.c,v 1.118 2009/05/28 17:07:42 fabiankeil Exp $" #include #include +#ifdef FEATURE_COMPRESSION +#include +#endif + #include "project.h" #include "cgi.h" #include "list.h" @@ -553,7 +557,7 @@ static struct http_response *dispatch_known_cgi(struct client_state * csp, if (!err) { /* It worked */ - rsp->reason = RSP_REASON_CGI_CALL; + rsp->crunch_reason = CGI_CALL; return finish_http_response(csp, rsp); } else @@ -815,15 +819,13 @@ jb_err get_number_param(struct client_state *csp, * Parameters : * 1 : csp = Current client state (buffers, headers, etc...) * 2 : templatename = Which template should be used for the answer - * 3 : sys_err = system error number * * Returns : A http_response. If we run out of memory, this * will be cgi_error_memory(). * *********************************************************************/ struct http_response *error_response(struct client_state *csp, - const char *templatename, - int sys_err) + const char *templatename) { jb_err err; struct http_response *rsp; @@ -856,7 +858,6 @@ struct http_response *error_response(struct client_state *csp, if (!err) err = map(exports, "host", 1, html_encode(csp->http->host), 0); if (!err) err = map(exports, "hostport", 1, html_encode(csp->http->hostport), 0); if (!err) err = map(exports, "path", 1, html_encode_and_free_original(path), 0); - if (!err) err = map(exports, "error", 1, html_encode_and_free_original(safe_strerror(sys_err)), 0); if (!err) err = map(exports, "protocol", 1, csp->http->ssl ? "https://" : "http://", 1); if (!err) { @@ -879,13 +880,7 @@ struct http_response *error_response(struct client_state *csp, if (!strcmp(templatename, "no-such-domain")) { rsp->status = strdup("404 No such domain"); - if (rsp->status == NULL) - { - free_map(exports); - free_http_response(rsp); - return cgi_error_memory(); - } - rsp->reason = RSP_REASON_NO_SUCH_DOMAIN; + rsp->crunch_reason = NO_SUCH_DOMAIN; } else if (!strcmp(templatename, "forwarding-failed")) { @@ -939,26 +934,37 @@ struct http_response *error_response(struct client_state *csp, if (!err) err = map(exports, "forwarding-type", 1, socks_type, 1); if (!err) err = map(exports, "error-message", 1, html_encode(csp->error_message), 0); - - if (!err) rsp->status = strdup("503 Forwarding failure"); - if ((rsp->status == NULL) || (NULL == csp->error_message) || err) + if ((NULL == csp->error_message) || err) { free_map(exports); free_http_response(rsp); return cgi_error_memory(); } - rsp->reason = RSP_REASON_FORWARDING_FAILED; + + rsp->status = strdup("503 Forwarding failure"); + rsp->crunch_reason = FORWARDING_FAILED; } else if (!strcmp(templatename, "connect-failed")) { rsp->status = strdup("503 Connect failed"); - if (rsp->status == NULL) - { - free_map(exports); - free_http_response(rsp); - return cgi_error_memory(); - } - rsp->reason = RSP_REASON_CONNECT_FAILED; + rsp->crunch_reason = CONNECT_FAILED; + } + else if (!strcmp(templatename, "connection-timeout")) + { + rsp->status = strdup("504 Connection timeout"); + rsp->crunch_reason = CONNECTION_TIMEOUT; + } + else if (!strcmp(templatename, "no-server-data")) + { + rsp->status = strdup("502 No data received from server or forwarder"); + rsp->crunch_reason = NO_SERVER_DATA; + } + + if (rsp->status == NULL) + { + free_map(exports); + free_http_response(rsp); + return cgi_error_memory(); } err = template_fill_for_cgi(csp, templatename, exports, rsp); @@ -1051,7 +1057,7 @@ void cgi_init_error_messages(void) strlen(cgi_error_memory_response->head); cgi_error_memory_response->content_length = strlen(cgi_error_memory_response->body); - cgi_error_memory_response->reason = RSP_REASON_OUT_OF_MEMORY; + cgi_error_memory_response->crunch_reason = OUT_OF_MEMORY; } @@ -1222,7 +1228,7 @@ jb_err cgi_error_unknown(const struct client_state *csp, rsp->content_length = 0; rsp->head_length = 0; rsp->is_static = 0; - rsp->reason = RSP_REASON_INTERNAL_ERROR; + rsp->crunch_reason = INTERNAL_ERROR; snprintf(errnumbuf, sizeof(errnumbuf), "%d", error_to_report); @@ -1360,7 +1366,7 @@ char *add_help_link(const char *item, string_join (&result, string_toupper(item)); string_append(&result, "\">"); string_append(&result, item); - string_append(&result, " "); + string_append(&result, ""); return result; } @@ -1477,6 +1483,59 @@ static void get_locale_time(char *buf, size_t buffer_size) } + +#ifdef FEATURE_COMPRESSION +/********************************************************************* + * + * Function : compress_buffer + * + * Description : Compresses the content of a buffer with zlib's deflate + * Allocates a new buffer for the result, free'ing it is + * up to the caller. + * + * XXX: We should add a config option for the + * compression level. + * + * + * Parameters : + * 1 : buffer = buffer whose content should be compressed + * 2 : buffer_length = length of the buffer + * + * Returns : NULL on error, otherwise a pointer to the compressed + * content of the input buffer. + * + *********************************************************************/ +char *compress_buffer(char *buffer, size_t *buffer_length) +{ + char *compressed_buffer; + size_t new_length = *buffer_length; + + compressed_buffer = malloc(new_length); + if (NULL == compressed_buffer) + { + log_error(LOG_LEVEL_FATAL, + "Out of memory allocation compression buffer."); + } + + if (Z_OK != compress2((Bytef *)compressed_buffer, &new_length, + (Bytef *)buffer, *buffer_length, Z_DEFAULT_COMPRESSION)) + { + log_error(LOG_LEVEL_ERROR, "Error in compress2()"); + freez(compressed_buffer); + return NULL; + } + + log_error(LOG_LEVEL_RE_FILTER, + "Compressed content from %d to %d bytes.", *buffer_length, new_length); + + *buffer_length = new_length; + + return compressed_buffer; + +} +#endif + + /********************************************************************* * * Function : finish_http_response @@ -1522,6 +1581,23 @@ struct http_response *finish_http_response(const struct client_state *csp, struc { rsp->content_length = rsp->body ? strlen(rsp->body) : 0; } + +#ifdef FEATURE_COMPRESSION + if (!err && (csp->flags & CSP_FLAG_CLIENT_SUPPORTS_DEFLATE) + && (rsp->content_length > LOWER_LENGTH_LIMIT_FOR_COMRPESSION)) + { + char *compressed_content; + + compressed_content = compress_buffer(rsp->body, &rsp->content_length); + if (NULL != compressed_content) + { + freez(rsp->body); + rsp->body = compressed_content; + } + err = enlist_unique_header(rsp->headers, "Content-Encoding", "deflate"); + } +#endif + if (!err) { snprintf(buf, sizeof(buf), "Content-Length: %d", (int)rsp->content_length); @@ -1620,7 +1696,9 @@ struct http_response *finish_http_response(const struct client_state *csp, struc if (!err) err = enlist_unique_header(rsp->headers, "Date", buf); if (!strncmpic(rsp->status, "403", 3) || !strncmpic(rsp->status, "404", 3) - || !strncmpic(rsp->status, "503", 3)) + || !strncmpic(rsp->status, "502", 3) + || !strncmpic(rsp->status, "503", 3) + || !strncmpic(rsp->status, "504", 3)) { if (!err) err = enlist_unique_header(rsp->headers, "Last-Modified", "Wed, 08 Jun 1955 12:00:00 GMT"); } @@ -1632,13 +1710,10 @@ struct http_response *finish_http_response(const struct client_state *csp, struc if (!err) err = enlist_unique_header(rsp->headers, "Pragma", "no-cache"); } - /* - * Quoting RFC 2616: - * - * HTTP/1.1 applications that do not support persistent connections MUST - * include the "close" connection option in every message. - */ - if (!err) err = enlist_unique_header(rsp->headers, "Connection", "close"); + if (!err && !(csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE)) + { + err = enlist_unique_header(rsp->headers, "Connection", "close"); + } /* * Write the head @@ -1861,7 +1936,7 @@ jb_err template_load(const struct client_state *csp, char **template_ptr, * HTML template by replacing @name@ with value using * pcrs, for each item in the output map. * - * Note that a leading '$' charachter in the export map's + * Note that a leading '$' character in the export map's * values will be stripped and toggle on backreference * interpretation. *