X-Git-Url: http://www.privoxy.org/gitweb/?a=blobdiff_plain;f=cgi.c;h=7816c37aea2bc07f9841f747e9425020dfc658b6;hb=048db68f0449f4b4a10eb56ad6e07e55fb475b2c;hp=dd3259551798d9932685495e6963d816ecdce449;hpb=6584be3d9bde7052e5288a6746ec11de94c501b9;p=privoxy.git
diff --git a/cgi.c b/cgi.c
index dd325955..7816c37a 100644
--- a/cgi.c
+++ b/cgi.c
@@ -1,4 +1,4 @@
-const char cgi_rcs[] = "$Id: cgi.c,v 1.77 2006/09/21 15:17:23 fabiankeil Exp $";
+const char cgi_rcs[] = "$Id: cgi.c,v 1.92 2007/01/28 13:41:17 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/cgi.c,v $
@@ -11,8 +11,8 @@ const char cgi_rcs[] = "$Id: cgi.c,v 1.77 2006/09/21 15:17:23 fabiankeil Exp $";
* Functions declared include:
*
*
- * Copyright : Written by and Copyright (C) 2001 the SourceForge
- * Privoxy team. http://www.privoxy.org/
+ * Copyright : Written by and Copyright (C) 2001-2004, 2006-2007
+ * the SourceForge Privoxy team. http://www.privoxy.org/
*
* Based on the Internet Junkbuster originally written
* by and Copyright (C) 1997 Anonymous Coders and
@@ -38,6 +38,77 @@ const char cgi_rcs[] = "$Id: cgi.c,v 1.77 2006/09/21 15:17:23 fabiankeil Exp $";
*
* Revisions :
* $Log: cgi.c,v $
+ * Revision 1.92 2007/01/28 13:41:17 fabiankeil
+ * - Add HEAD support to finish_http_response.
+ * - Add error favicon to internal HTML error messages.
+ *
+ * Revision 1.91 2007/01/27 13:09:16 fabiankeil
+ * Add new config option "templdir" to
+ * change the templates directory.
+ *
+ * Revision 1.90 2007/01/25 13:47:26 fabiankeil
+ * Added "forwarding-failed" template support for error_response().
+ *
+ * Revision 1.89 2007/01/23 15:51:16 fabiankeil
+ * Add favicon delivery functions.
+ *
+ * Revision 1.88 2007/01/23 13:14:32 fabiankeil
+ * - Map variables that aren't guaranteed to be
+ * pure ASCII html_encoded.
+ * - Use CGI_PREFIX to generate URL for user manual
+ * CGI page to make sure CGI_SITE_2_PATH is included.
+ *
+ * Revision 1.87 2007/01/22 15:34:13 fabiankeil
+ * - "Protect" against a rather lame JavaScript-based
+ * Privoxy detection "attack" and check the referrer
+ * before delivering the CGI style sheet.
+ * - Move referrer check for unsafe CGI pages into
+ * referrer_is_safe() and log the result.
+ * - Map @url@ in cgi-error-disabled page.
+ * It's required for the "go there anyway" link.
+ * - Mark *csp as immutable for grep_cgi_referrer().
+ *
+ * Revision 1.86 2007/01/09 11:54:26 fabiankeil
+ * Fix strdup() error handling in cgi_error_unknown()
+ * and cgi_error_no_template(). Reported by Markus Elfring.
+ *
+ * Revision 1.85 2007/01/05 14:19:02 fabiankeil
+ * Handle pcrs_execute() errors in template_fill() properly.
+ *
+ * Revision 1.84 2006/12/28 17:54:22 fabiankeil
+ * Fixed gcc43 conversion warnings and replaced sprintf
+ * calls with snprintf to give OpenBSD's gcc one less reason
+ * to complain.
+ *
+ * Revision 1.83 2006/12/17 19:35:19 fabiankeil
+ * Escape ampersand in Privoxy menu.
+ *
+ * Revision 1.82 2006/12/17 17:53:39 fabiankeil
+ * Suppress the toggle link if remote toggling is disabled.
+ *
+ * Revision 1.81 2006/12/09 13:49:16 fabiankeil
+ * Fix configure option --disable-toggle.
+ * Thanks to Peter Thoenen for reporting this.
+ *
+ * Revision 1.80 2006/12/08 14:45:32 fabiankeil
+ * Don't lose the FORCE_PREFIX in case of
+ * connection problems. Fixes #612235.
+ *
+ * Revision 1.79 2006/11/13 19:05:50 fabiankeil
+ * Make pthread mutex locking more generic. Instead of
+ * checking for OSX and OpenBSD, check for FEATURE_PTHREAD
+ * and use mutex locking unless there is an _r function
+ * available. Better safe than sorry.
+ *
+ * Fixes "./configure --disable-pthread" and should result
+ * in less threading-related problems on pthread-using platforms,
+ * but it still doesn't fix BR#1122404.
+ *
+ * Revision 1.78 2006/09/21 19:22:07 fabiankeil
+ * Use CGI_PREFIX to check the referrer.
+ * The check for "http://config.privoxy.org/" fails
+ * if the user modified CGI_SITE_2_HOST.
+ *
* Revision 1.77 2006/09/21 15:17:23 fabiankeil
* Adjusted headers for Privoxy's cgi responses:
* Don't set Last-Modified, Expires and Cache-Control
@@ -505,6 +576,7 @@ const char cgi_rcs[] = "$Id: cgi.c,v 1.77 2006/09/21 15:17:23 fabiankeil Exp $";
#include "encode.h"
#include "ssplit.h"
#include "errlog.h"
+#include "filters.h"
#include "miscutil.h"
#include "cgisimple.h"
#ifdef FEATURE_CGI_EDIT_ACTIONS
@@ -513,7 +585,6 @@ const char cgi_rcs[] = "$Id: cgi.c,v 1.77 2006/09/21 15:17:23 fabiankeil Exp $";
#include "loadcfg.h"
/* loadcfg.h is for global_toggle_state only */
#ifdef FEATURE_PTHREAD
-#include Privoxy ran out of memory while processing your request. Privoxy encountered an error while processing your request: Privoxy encountered an error while processing your request:500 Internal Privoxy Error
\r\n"
"500 Internal Privoxy Error
\r\n"
"500 Internal Privoxy Error
\r\n"
"
Please " - "" + "" "file a bug report.
\r\n" "\r\n" "\r\n"; @@ -1518,8 +1712,9 @@ jb_err cgi_error_unknown(struct client_state *csp, rsp->content_length = 0; rsp->head_length = 0; rsp->is_static = 0; + rsp->reason = RSP_REASON_INTERNAL_ERROR; - sprintf(errnumbuf, "%d", error_to_report); + snprintf(errnumbuf, sizeof(errnumbuf), "%d", error_to_report); rsp->body = malloc(strlen(body_prefix) + strlen(errnumbuf) + strlen(body_suffix) + 1); if (rsp->body == NULL) @@ -1531,7 +1726,7 @@ jb_err cgi_error_unknown(struct client_state *csp, strcat(rsp->body, body_suffix); rsp->status = strdup(status); - if (rsp->body == NULL) + if (rsp->status == NULL) { return JB_ERR_MEMORY; } @@ -1688,7 +1883,7 @@ void get_http_time(int time_offset, char *buf) struct tm *t; time_t current_time; -#if defined(HAVE_GMTIME_R) && !defined(OSX_DARWIN) +#if defined(HAVE_GMTIME_R) /* * Declare dummy up here (instead of inside get/set gmt block) so it * doesn't go out of scope before it's potentially used in snprintf later. @@ -1706,12 +1901,12 @@ void get_http_time(int time_offset, char *buf) /* get and save the gmt */ { -#ifdef OSX_DARWIN +#if HAVE_GMTIME_R + t = gmtime_r(¤t_time, &dummy); +#elif FEATURE_PTHREAD pthread_mutex_lock(&gmtime_mutex); t = gmtime(¤t_time); pthread_mutex_unlock(&gmtime_mutex); -#elif HAVE_GMTIME_R - t = gmtime_r(¤t_time, &dummy); #else t = gmtime(¤t_time); #endif @@ -1738,6 +1933,8 @@ void get_http_time(int time_offset, char *buf) * * Description : Fill in the missing headers in an http response, * and flatten the headers to an http head. + * For HEAD requests the body is freed once + * the Content-Length header is set. * * Parameters : * 1 : rsp = pointer to http_response to be processed @@ -1746,7 +1943,7 @@ void get_http_time(int time_offset, char *buf) * On error, free()s rsp and returns cgi_error_memory() * *********************************************************************/ -struct http_response *finish_http_response(struct http_response *rsp) +struct http_response *finish_http_response(const struct client_state *csp, struct http_response *rsp) { char buf[BUFFER_SIZE]; jb_err err; @@ -1762,7 +1959,7 @@ struct http_response *finish_http_response(struct http_response *rsp) /* * Fill in the HTTP Status */ - sprintf(buf, "HTTP/1.0 %s", rsp->status ? rsp->status : "200 OK"); + snprintf(buf, sizeof(buf), "HTTP/1.0 %s", rsp->status ? rsp->status : "200 OK"); err = enlist_first(rsp->headers, buf); /* @@ -1774,10 +1971,28 @@ struct http_response *finish_http_response(struct http_response *rsp) } if (!err) { - sprintf(buf, "Content-Length: %d", (int)rsp->content_length); + snprintf(buf, sizeof(buf), "Content-Length: %d", (int)rsp->content_length); err = enlist(rsp->headers, buf); } + if (0 == strcmpic(csp->http->gpc, "head")) + { + /* + * The client only asked for the head. Dispose + * the body and log an offensive message. + * + * While it may seem to be a bit inefficient to + * prepare the body if it isn't needed, it's the + * only way to get the Content-Length right for + * dynamic pages. We could have disposed the body + * earlier, but not without duplicating the + * Content-Length setting code above. + */ + log_error(LOG_LEVEL_CGI, "Preparing to give head to %s.", csp->ip_addr_str); + freez(rsp->body); + rsp->content_length = 0; + } + if (strncmpic(rsp->status, "302", 3)) { /* @@ -1839,7 +2054,7 @@ struct http_response *finish_http_response(struct http_response *rsp) * is older than Privoxy's error message, the server would send status code * 304 and the browser would display the outdated error message again and again. * - * For documents delivered with status code 404 or 503 we set "Last-Modified" + * For documents delivered with status code 403, 404 and 503 we set "Last-Modified" * to Tim Berners-Lee's birthday, which predates the age of any page on the web * and can be safely used to "revalidate" without getting a status code 304. * @@ -1850,7 +2065,9 @@ struct http_response *finish_http_response(struct http_response *rsp) get_http_time(0, buf); if (!err) err = enlist_unique_header(rsp->headers, "Date", buf); - if (!strncmpic(rsp->status, "404", 3) || !strncmpic(rsp->status, "503", 3)) + if (!strncmpic(rsp->status, "403", 3) + || !strncmpic(rsp->status, "404", 3) + || !strncmpic(rsp->status, "503", 3)) { if (!err) err = enlist_unique_header(rsp->headers, "Last-Modified", "Wed, 08 Jun 1955 12:00:00 GMT"); } @@ -1938,9 +2155,8 @@ void free_http_response(struct http_response *rsp) * Function : template_load * * Description : CGI support function that loads a given HTML - * template from the confdir, ignoring comment - * lines and following #include statements up to - * a depth of 1. + * template, ignoring comment lines and following + * #include statements up to a depth of 1. * * Parameters : * 1 : csp = Current client state (buffers, headers, etc...) @@ -1987,11 +2203,23 @@ jb_err template_load(struct client_state *csp, char **template_ptr, } } - /* Generate full path */ + /* + * Generate full path using either templdir + * or confdir/templates as base directory. + */ + if (NULL != csp->config->templdir) + { + templates_dir_path = strdup(csp->config->templdir); + } + else + { + templates_dir_path = make_path(csp->config->confdir, "templates"); + } - templates_dir_path = make_path(csp->config->confdir, "templates"); if (templates_dir_path == NULL) { + log_error(LOG_LEVEL_ERROR, "Out of memory while generating template path for %s.", + templatename); return JB_ERR_MEMORY; } @@ -1999,6 +2227,8 @@ jb_err template_load(struct client_state *csp, char **template_ptr, free(templates_dir_path); if (full_path == NULL) { + log_error(LOG_LEVEL_ERROR, "Out of memory while generating full template path for %s.", + templatename); return JB_ERR_MEMORY; } @@ -2007,6 +2237,7 @@ jb_err template_load(struct client_state *csp, char **template_ptr, file_buffer = strdup(""); if (file_buffer == NULL) { + log_error(LOG_LEVEL_ERROR, "Not enough free memory to buffer %s.", full_path); free(full_path); return JB_ERR_MEMORY; } @@ -2088,7 +2319,7 @@ jb_err template_load(struct client_state *csp, char **template_ptr, * Caller must free(). * 2 : exports = map with fill in symbol -> name pairs * - * Returns : JB_ERR_OK on success + * Returns : JB_ERR_OK on success (and for uncritical errors) * JB_ERR_MEMORY on out-of-memory error * *********************************************************************/ @@ -2159,15 +2390,35 @@ jb_err template_fill(char **template_ptr, const struct map *exports) } else { - pcrs_execute(job, file_buffer, size, &tmp_out_buffer, &size); - free(file_buffer); + error = pcrs_execute(job, file_buffer, size, &tmp_out_buffer, &size); + pcrs_free_job(job); if (NULL == tmp_out_buffer) { *template_ptr = NULL; return JB_ERR_MEMORY; } - file_buffer = tmp_out_buffer; + + 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. + */ + free(tmp_out_buffer); + log_error(LOG_LEVEL_ERROR, "Failed to execute s/%s/%s/%s. %s", + buf, m->value, flags, pcrs_strerror(error)); + } + else + { + /* Substitution succeeded, use modified buffer. */ + free(file_buffer); + file_buffer = tmp_out_buffer; + } } } @@ -2263,16 +2514,18 @@ struct map *default_exports(const struct client_state *csp, const char *caller) if (!err) err = map(exports, "my-hostname", 1, html_encode(csp->my_hostname ? csp->my_hostname : "unknown"), 0); if (!err) err = map(exports, "homepage", 1, html_encode(HOME_PAGE_URL), 0); if (!err) err = map(exports, "default-cgi", 1, html_encode(CGI_PREFIX), 0); - if (!err) err = map(exports, "menu", 1, make_menu(caller), 0); + if (!err) err = map(exports, "menu", 1, make_menu(caller, csp->config->feature_flags), 0); if (!err) err = map(exports, "code-status", 1, CODE_STATUS, 1); if (!strncmpic(csp->config->usermanual, "file://", 7) || !strncmpic(csp->config->usermanual, "http", 4)) { - if (!err) err = map(exports, "user-manual", 1, csp->config->usermanual ,1); + /* Manual is located somewhere else, just link to it. */ + if (!err) err = map(exports, "user-manual", 1, html_encode(csp->config->usermanual), 0); } else { - if (!err) err = map(exports, "user-manual", 1, "http://"CGI_SITE_2_HOST"/user-manual/" ,1); + /* Manual is delivered by Privoxy. */ + if (!err) err = map(exports, "user-manual", 1, html_encode(CGI_PREFIX"user-manual/"), 0); } if (!err) err = map(exports, "actions-help-prefix", 1, ACTIONS_HELP_PREFIX ,1); #ifdef FEATURE_TOGGLE @@ -2449,14 +2702,18 @@ jb_err map_conditional(struct map *exports, const char *name, int choose_first) * * Description : Returns an HTML-formatted menu of the available * unhidden CGIs, excluding the one given in