X-Git-Url: http://www.privoxy.org/gitweb/?a=blobdiff_plain;f=cgi.c;h=d28b92044bcd6f7d3615cbdc16ab4b9b114e3a1c;hb=c46413a31172a46ad4b522a614b130a202cc6b2a;hp=a470c2bf8a3329ef702b3fd22487ecf14a003fe8;hpb=9c8724b5e111018b50b869f16d531d810ae6d2d5;p=privoxy.git
diff --git a/cgi.c b/cgi.c
index a470c2bf..d28b9204 100644
--- a/cgi.c
+++ b/cgi.c
@@ -1,4 +1,4 @@
-const char cgi_rcs[] = "$Id: cgi.c,v 1.119 2009/05/28 21:13:34 fabiankeil Exp $";
+const char cgi_rcs[] = "$Id: cgi.c,v 1.146 2011/12/31 14:47:44 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/cgi.c,v $
@@ -7,18 +7,15 @@ const char cgi_rcs[] = "$Id: cgi.c,v 1.119 2009/05/28 21:13:34 fabiankeil Exp $"
* html or gif answers, and to compose HTTP resonses.
* This only contains the framework functions, the
* actual handler functions are declared elsewhere.
- *
- * Functions declared include:
- *
*
* Copyright : Written by and Copyright (C) 2001-2004, 2006-2008
* the SourceForge Privoxy team. http://www.privoxy.org/
*
* Based on the Internet Junkbuster originally written
- * by and Copyright (C) 1997 Anonymous Coders and
+ * by and Copyright (C) 1997 Anonymous Coders and
* Junkbusters Corporation. http://www.junkbusters.com
*
- * This program is free software; you can redistribute it
+ * This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at
@@ -49,6 +46,10 @@ const char cgi_rcs[] = "$Id: cgi.c,v 1.119 2009/05/28 21:13:34 fabiankeil Exp $"
#include Privoxy ran out of memory while processing your request. Please contact your proxy administrator, or try again later Privoxy ran out of memory while processing your request. Please contact your proxy administrator, or try again later Privoxy encountered an error while processing your request: Privoxy encountered an error while processing your request: Could not load template file Please contact your proxy administrator.500 Internal Privoxy Error
\r\n"
- "500 Internal Privoxy Error
\n"
+ "500 Internal Privoxy Error
\r\n"
- "500 Internal Privoxy Error
\n"
+ "";
static const char body_suffix[] =
- "
or one of its included components.
Please contact your proxy administrator.
\n" "If you are the proxy administrator, please put the required file(s)"
"in the (confdir)/templates
directory. The "
"location of the (confdir)
directory "
@@ -1120,9 +1135,9 @@ jb_err cgi_error_no_template(const struct client_state *csp,
#ifndef _WIN32
", or /etc/privoxy/
"
#endif /* ndef _WIN32 */
- ").
Privoxy encountered an error while processing your request:
\r\n" + "\n" + "\n" + "Privoxy encountered an error while processing your request:
\n" "Unexpected internal error: "; static const char body_suffix[] = - "
\r\n" + "\n" "Please " "" - "file a bug report.
\r\n" - "\r\n" - "\r\n"; - char errnumbuf[30]; - /* - * Due to sizeof(errnumbuf), body_size will be slightly - * bigger than necessary but it doesn't really matter. - */ - const size_t body_size = strlen(body_prefix) + sizeof(errnumbuf) + strlen(body_suffix) + 1; + "file a bug report.\n" + "\n" + "\n"; + /* Includes room for larger error numbers in the future. */ + const size_t body_size = sizeof(body_prefix) + sizeof(body_suffix) + 5; assert(csp); assert(rsp); @@ -1219,18 +1230,15 @@ 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; - - snprintf(errnumbuf, sizeof(errnumbuf), "%d", error_to_report); + rsp->crunch_reason = INTERNAL_ERROR; rsp->body = malloc(body_size); if (rsp->body == NULL) { return JB_ERR_MEMORY; } - strlcpy(rsp->body, body_prefix, body_size); - strlcat(rsp->body, errnumbuf, body_size); - strlcat(rsp->body, body_suffix, body_size); + + snprintf(rsp->body, body_size, "%s%d%s", body_prefix, error_to_report, body_suffix); rsp->status = strdup(status); if (rsp->status == NULL) @@ -1248,7 +1256,7 @@ jb_err cgi_error_unknown(const struct client_state *csp, * * Description : CGI function that is called if the parameters * (query string) for a CGI were wrong. - * + * * Parameters : * 1 : csp = Current client state (buffers, headers, etc...) * 2 : rsp = http_response data structure for output @@ -1256,7 +1264,7 @@ jb_err cgi_error_unknown(const struct client_state *csp, * CGI Parameters : none * * Returns : JB_ERR_OK on success - * JB_ERR_MEMORY on out-of-memory error. + * JB_ERR_MEMORY on out-of-memory error. * *********************************************************************/ jb_err cgi_error_bad_param(const struct client_state *csp, @@ -1278,7 +1286,7 @@ jb_err cgi_error_bad_param(const struct client_state *csp, /********************************************************************* * - * Function : cgi_redirect + * Function : cgi_redirect * * Description : CGI support function to generate a HTTP redirect * message @@ -1290,7 +1298,7 @@ jb_err cgi_error_bad_param(const struct client_state *csp, * CGI Parameters : None * * Returns : JB_ERR_OK on success - * JB_ERR_MEMORY on out-of-memory error. + * JB_ERR_MEMORY on out-of-memory error. * *********************************************************************/ jb_err cgi_redirect (struct http_response * rsp, const char *target) @@ -1325,8 +1333,8 @@ jb_err cgi_redirect (struct http_response * rsp, const char *target) * FIXME: I currently only work for actions, and would * like to be generalized for other topics. * - * Parameters : - * 1 : item = item (will NOT be free()d.) + * Parameters : + * 1 : item = item (will NOT be free()d.) * It is assumed to be HTML-safe. * 2 : config = The current configuration. * @@ -1357,7 +1365,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; } @@ -1371,7 +1379,7 @@ char *add_help_link(const char *item, * HTTP header - e.g.: * "Sun, 06 Nov 1994 08:49:37 GMT" * - * Parameters : + * Parameters : * 1 : time_offset = Time returned will be current time * plus this number of seconds. * 2 : buf = Destination for result. @@ -1384,12 +1392,6 @@ char *add_help_link(const char *item, *********************************************************************/ void get_http_time(int time_offset, char *buf, size_t buffer_size) { - static const char day_names[7][4] = - { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; - static const char month_names[12][4] = - { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - struct tm *t; time_t current_time; #if defined(HAVE_GMTIME_R) @@ -1414,17 +1416,7 @@ void get_http_time(int time_offset, char *buf, size_t buffer_size) t = gmtime(¤t_time); #endif - /* Format: "Sun, 06 Nov 1994 08:49:37 GMT" */ - snprintf(buf, buffer_size, - "%s, %02d %s %4d %02d:%02d:%02d GMT", - day_names[t->tm_wday], - t->tm_mday, - month_names[t->tm_mon], - t->tm_year + 1900, - t->tm_hour, - t->tm_min, - t->tm_sec - ); + strftime(buf, buffer_size, "%a, %d %b %Y %H:%M:%S GMT", t); } @@ -1474,6 +1466,63 @@ 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. + * + * Parameters : + * 1 : buffer = buffer whose content should be compressed + * 2 : buffer_length = length of the buffer + * 3 : compression_level = compression level for compress2() + * + * Returns : NULL on error, otherwise a pointer to the compressed + * content of the input buffer. + * + *********************************************************************/ +char *compress_buffer(char *buffer, size_t *buffer_length, int compression_level) +{ + char *compressed_buffer; + uLongf new_length; + assert(-1 <= compression_level && compression_level <= 9); + + /* Let zlib figure out the maximum length of the compressed data */ + new_length = compressBound((uLongf)*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, compression_level)) + { + log_error(LOG_LEVEL_ERROR, + "compress2() failed. Buffer size: %d, compression level: %d.", + new_length, compression_level); + freez(compressed_buffer); + return NULL; + } + + log_error(LOG_LEVEL_RE_FILTER, + "Compressed content from %d to %d bytes. Compression level: %d", + *buffer_length, new_length, compression_level); + + *buffer_length = (size_t)new_length; + + return compressed_buffer; + +} +#endif + + /********************************************************************* * * Function : finish_http_response @@ -1503,7 +1552,7 @@ struct http_response *finish_http_response(const struct client_state *csp, struc return rsp; } - /* + /* * Fill in the HTTP Status, using HTTP/1.1 * unless the client asked for HTTP/1.0. */ @@ -1512,13 +1561,31 @@ struct http_response *finish_http_response(const struct client_state *csp, struc rsp->status ? rsp->status : "200 OK"); err = enlist_first(rsp->headers, buf); - /* + /* * Set the Content-Length */ if (rsp->content_length == 0) { 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_COMPRESSION)) + { + char *compressed_content; + + compressed_content = compress_buffer(rsp->body, &rsp->content_length, + csp->config->compression_level); + 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); @@ -1560,7 +1627,7 @@ struct http_response *finish_http_response(const struct client_state *csp, struc * Last-Modified: set to date/time the page was last changed. * Expires: set to date/time page next needs reloading. * Cache-Control: set to "no-cache" if applicable. - * + * * See http://www.w3.org/Protocols/rfc2068/rfc2068 */ if (rsp->is_static) @@ -1617,7 +1684,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"); } @@ -1629,15 +1698,12 @@ 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 */ if (err || (NULL == (rsp->head = list_to_text(rsp->headers)))) @@ -1717,11 +1783,11 @@ void free_http_response(struct http_response *rsp) * following an #include statament * * Returns : JB_ERR_OK on success - * JB_ERR_MEMORY on out-of-memory error. + * JB_ERR_MEMORY on out-of-memory error. * JB_ERR_FILE if the template file cannot be read * *********************************************************************/ -jb_err template_load(const struct client_state *csp, char **template_ptr, +jb_err template_load(const struct client_state *csp, char **template_ptr, const char *templatename, int recursive) { jb_err err; @@ -1803,7 +1869,7 @@ jb_err template_load(const struct client_state *csp, char **template_ptr, } free(full_path); - /* + /* * Read the file, ignoring comments, and honoring #include * statements, unless we're already called recursively. * @@ -1858,7 +1924,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. * @@ -1891,7 +1957,7 @@ jb_err template_fill(char **template_ptr, const struct map *exports) file_buffer = *template_ptr; size = strlen(file_buffer) + 1; - /* + /* * Assemble pcrs joblist from exports map */ for (m = exports->first; m != NULL; m = m->next) @@ -1909,7 +1975,7 @@ jb_err template_fill(char **template_ptr, const struct map *exports) else { /* - * Treat the "replace with" text as a literal string - + * Treat the "replace with" text as a literal string - * no quoting needed, no backreferences allowed. * ("Trivial" ['T'] flag). */ @@ -1923,7 +1989,7 @@ jb_err template_fill(char **template_ptr, const struct map *exports) /* Make and run job. */ job = pcrs_compile(buf, m->value, flags, &error); - if (job == NULL) + if (job == NULL) { if (error == PCRS_ERR_NOMEM) { @@ -1950,10 +2016,10 @@ jb_err template_fill(char **template_ptr, const struct map *exports) if (error < 0) { - /* + /* * Substitution failed, keep the original buffer, * log the problem and ignore it. - * + * * The user might see some unresolved @CGI_VARIABLES@, * but returning a special CGI error page seems unreasonable * and could mask more important error messages. @@ -2005,7 +2071,7 @@ jb_err template_fill_for_cgi(const struct client_state *csp, struct http_response *rsp) { jb_err err; - + assert(csp); assert(templatename); assert(exports); @@ -2050,6 +2116,7 @@ struct map *default_exports(const struct client_state *csp, const char *caller) struct map * exports; int local_help_exists = 0; char *ip_address = NULL; + char *port = NULL; char *hostname = NULL; assert(csp); @@ -2062,12 +2129,12 @@ struct map *default_exports(const struct client_state *csp, const char *caller) if (csp->config->hostname) { - get_host_information(csp->cfd, &ip_address, NULL); + get_host_information(csp->cfd, &ip_address, &port, NULL); hostname = strdup(csp->config->hostname); } else { - get_host_information(csp->cfd, &ip_address, &hostname); + get_host_information(csp->cfd, &ip_address, &port, &hostname); } err = map(exports, "version", 1, html_encode(VERSION), 0); @@ -2075,6 +2142,8 @@ struct map *default_exports(const struct client_state *csp, const char *caller) if (!err) err = map(exports, "time", 1, html_encode(buf), 0); if (!err) err = map(exports, "my-ip-address", 1, html_encode(ip_address ? ip_address : "unknown"), 0); freez(ip_address); + if (!err) err = map(exports, "my-port", 1, html_encode(port ? port : "unknown"), 0); + freez(port); if (!err) err = map(exports, "my-hostname", 1, html_encode(hostname ? hostname : "unknown"), 0); freez(hostname); if (!err) err = map(exports, "homepage", 1, html_encode(HOME_PAGE_URL), 0); @@ -2099,9 +2168,6 @@ struct map *default_exports(const struct client_state *csp, const char *caller) if (!err) err = map_block_killer(exports, "can-toggle"); #endif - snprintf(buf, sizeof(buf), "%d", csp->config->hport); - if (!err) err = map(exports, "my-port", 1, buf, 1); - if(!strcmp(CODE_STATUS, "stable")) { if (!err) err = map_block_killer(exports, "unstable"); @@ -2152,12 +2218,12 @@ struct map *default_exports(const struct client_state *csp, const char *caller) * "if-