-const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.45 2006/12/28 18:16:41 fabiankeil Exp $";
+const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.55 2007/04/13 13:36:46 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/cgisimple.c,v $
* Functions declared include:
*
*
- * Copyright : Written by and Copyright (C) 2001-2006 the SourceForge
+ * Copyright : Written by and Copyright (C) 2001-2007 the SourceForge
* Privoxy team. http://www.privoxy.org/
*
* Based on the Internet Junkbuster originally written
*
* Revisions :
* $Log: cgisimple.c,v $
+ * Revision 1.55 2007/04/13 13:36:46 fabiankeil
+ * Reference action files in CGI URLs by id instead
+ * of using the first part of the file name.
+ * Fixes BR 1694250 and BR 1590556.
+ *
+ * Revision 1.54 2007/04/09 18:11:35 fabiankeil
+ * Don't mistake VC++'s _snprintf() for a snprintf() replacement.
+ *
+ * Revision 1.53 2007/04/08 13:21:04 fabiankeil
+ * Reference action files in CGI URLs by id instead
+ * of using the first part of the file name.
+ * Fixes BR 1694250 and BR 1590556.
+ *
+ * Revision 1.52 2007/02/13 15:10:26 fabiankeil
+ * Apparently fopen()ing in "binary" mode doesn't require
+ * #ifdefs, it's already done without them in cgiedit.c.
+ *
+ * Revision 1.51 2007/02/10 16:55:22 fabiankeil
+ * - Show forwarding settings on the show-url-info page
+ * - Fix some HTML syntax errors.
+ *
+ * Revision 1.50 2007/01/23 15:51:17 fabiankeil
+ * Add favicon delivery functions.
+ *
+ * Revision 1.49 2007/01/20 16:29:38 fabiankeil
+ * Suppress edit buttons for action files if Privoxy has
+ * no write access. Suggested by Roland in PR 1564026.
+ *
+ * Revision 1.48 2007/01/20 15:31:31 fabiankeil
+ * Display warning if show-url-info CGI page
+ * is used while Privoxy is toggled off.
+ *
+ * Revision 1.47 2007/01/12 15:07:10 fabiankeil
+ * Use zalloc in cgi_send_user_manual.
+ *
+ * Revision 1.46 2007/01/02 12:49:46 fabiankeil
+ * Add FEATURE_ZLIB to the list of conditional
+ * defines at the show-status page.
+ *
* Revision 1.45 2006/12/28 18:16:41 fabiankeil
* Fixed gcc43 compiler warnings, zero out cgi_send_user_manual's
* body memory before using it, replaced sprintf calls with snprintf.
#include <string.h>
#include <assert.h>
-#ifdef _WIN32
-#define snprintf _snprintf
-#endif /* def _WIN32 */
+#ifdef HAVE_ACCESS
+#include <unistd.h>
+#endif /* def HAVE_ACCESS */
#include "project.h"
#include "cgi.h"
static char *show_rcs(void);
static jb_err show_defines(struct map *exports);
+/*
+ * 16x16 ico blobs for favicon delivery functions.
+ */
+const char default_favicon_data[] =
+ "\000\000\001\000\001\000\020\020\002\000\000\000\000\000\260"
+ "\000\000\000\026\000\000\000\050\000\000\000\020\000\000\000"
+ "\040\000\000\000\001\000\001\000\000\000\000\000\100\000\000"
+ "\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000"
+ "\000\000\377\377\377\000\377\000\052\000\017\360\000\000\077"
+ "\374\000\000\161\376\000\000\161\376\000\000\361\377\000\000"
+ "\361\377\000\000\360\017\000\000\360\007\000\000\361\307\000"
+ "\000\361\307\000\000\361\307\000\000\360\007\000\000\160\036"
+ "\000\000\177\376\000\000\077\374\000\000\017\360\000\000\360"
+ "\017\000\000\300\003\000\000\200\001\000\000\200\001\000\000"
+ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
+ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
+ "\000\000\200\001\000\000\200\001\000\000\300\003\000\000\360"
+ "\017\000\000";
+const char error_favicon_data[] =
+ "\000\000\001\000\001\000\020\020\002\000\000\000\000\000\260"
+ "\000\000\000\026\000\000\000\050\000\000\000\020\000\000\000"
+ "\040\000\000\000\001\000\001\000\000\000\000\000\100\000\000"
+ "\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000"
+ "\000\000\377\377\377\000\000\000\377\000\017\360\000\000\077"
+ "\374\000\000\161\376\000\000\161\376\000\000\361\377\000\000"
+ "\361\377\000\000\360\017\000\000\360\007\000\000\361\307\000"
+ "\000\361\307\000\000\361\307\000\000\360\007\000\000\160\036"
+ "\000\000\177\376\000\000\077\374\000\000\017\360\000\000\360"
+ "\017\000\000\300\003\000\000\200\001\000\000\200\001\000\000"
+ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
+ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
+ "\000\000\200\001\000\000\200\001\000\000\300\003\000\000\360"
+ "\017\000\000";
+const size_t default_favicon_length = sizeof(default_favicon_data) - 1;
+const size_t error_favicon_length = sizeof(error_favicon_data) - 1;
/*********************************************************************
*
return JB_ERR_MEMORY;
}
- if (map(exports, "processed-request", 1, html_encode_and_free_original(
- sed(client_patterns, add_client_headers, csp)), 0))
+ if (map(exports, "processed-request", 1, html_encode(list_to_text(csp->headers)), 0))
{
free_map(exports);
return JB_ERR_MEMORY;
}
+/*********************************************************************
+ *
+ * Function : cgi_send_default_favicon
+ *
+ * Description : CGI function that sends the standard favicon.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ * 2 : rsp = http_response data structure for output
+ * 3 : parameters = map of cgi parameters
+ *
+ * CGI Parameters : None
+ *
+ * Returns : JB_ERR_OK on success
+ * JB_ERR_MEMORY on out-of-memory error.
+ *
+ *********************************************************************/
+jb_err cgi_send_default_favicon(struct client_state *csp,
+ struct http_response *rsp,
+ const struct map *parameters)
+{
+ rsp->body = bindup(default_favicon_data, default_favicon_length);
+ rsp->content_length = default_favicon_length;
+
+ if (rsp->body == NULL)
+ {
+ return JB_ERR_MEMORY;
+ }
+
+ if (enlist(rsp->headers, "Content-Type: image/x-icon"))
+ {
+ return JB_ERR_MEMORY;
+ }
+
+ rsp->is_static = 1;
+
+ return JB_ERR_OK;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : cgi_send_error_favicon
+ *
+ * Description : CGI function that sends the favicon for error pages.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ * 2 : rsp = http_response data structure for output
+ * 3 : parameters = map of cgi parameters
+ *
+ * CGI Parameters : None
+ *
+ * Returns : JB_ERR_OK on success
+ * JB_ERR_MEMORY on out-of-memory error.
+ *
+ *********************************************************************/
+jb_err cgi_send_error_favicon(struct client_state *csp,
+ struct http_response *rsp,
+ const struct map *parameters)
+{
+ rsp->body = bindup(error_favicon_data, error_favicon_length);
+ rsp->content_length = error_favicon_length;
+
+ if (rsp->body == NULL)
+ {
+ return JB_ERR_MEMORY;
+ }
+
+ if (enlist(rsp->headers, "Content-Type: image/x-icon"))
+ {
+ return JB_ERR_MEMORY;
+ }
+
+ rsp->is_static = 1;
+
+ return JB_ERR_OK;
+
+}
+
+
/*********************************************************************
*
* Function : cgi_send_stylesheet
}
/* Open user-manual file */
-#ifdef WIN32
- /*
- * XXX: Do we support other operating systems that
- * require special treatment to fopen in binary mode?
- */
if (NULL == (fp = fopen(full_path, "rb")))
-#else
- if (NULL == (fp = fopen(full_path, "r")))
-#endif /* def WIN32 */
{
log_error(LOG_LEVEL_ERROR, "Cannot open user-manual file %s: %E", full_path);
err = cgi_error_no_template(csp, rsp, full_path);
fseek(fp, 0, SEEK_SET);
/* Allocate memory and load the file directly into the body */
- rsp->body = (char *)malloc(length+1);
+ rsp->body = (char *)zalloc(length+1);
if (!rsp->body)
{
fclose(fp);
free(full_path);
return JB_ERR_MEMORY;
}
- memset(rsp->body, '\0', length+1);
if (!fread(rsp->body, length, 1, fp))
{
/*
- * This happens if we didn't fopen in binary mode.
+ * May happen if the file size changes between fseek() and fread().
* If it does, we just log it and serve what we got.
*/
log_error(LOG_LEVEL_ERROR, "Couldn't completely read user-manual file %s.", full_path);
{
if (!err) err = string_append(&s, "<tr><td>");
if (!err) err = string_join(&s, html_encode(csp->actions_list[i]->filename));
- snprintf(buf, 100, "</td><td class=\"buttons\"><a href=\"/show-status?file=actions&index=%d\">View</a>", i);
+ snprintf(buf, sizeof(buf),
+ "</td><td class=\"buttons\"><a href=\"/show-status?file=actions&index=%d\">View</a>", i);
if (!err) err = string_append(&s, buf);
#ifdef FEATURE_CGI_EDIT_ACTIONS
if (NULL == strstr(csp->actions_list[i]->filename, "standard.action") && NULL != csp->config->actions_file_short[i])
{
- snprintf(buf, 100, " <a href=\"/edit-actions-list?f=%s\">Edit</a>", csp->config->actions_file_short[i]);
- if (!err) err = string_append(&s, buf);
+#ifdef HAVE_ACCESS
+ if (access(csp->config->actions_file[i], W_OK) == 0)
+ {
+#endif /* def HAVE_ACCESS */
+ snprintf(buf, sizeof(buf), " <a href=\"/edit-actions-list?f=%d\">Edit</a>", i);
+ if (!err) err = string_append(&s, buf);
+#ifdef HAVE_ACCESS
+ }
+ else
+ {
+ if (!err) err = string_append(&s, " <strong>No write access.</strong>");
+ }
+#endif /* def HAVE_ACCESS */
}
#endif
/*
* Unknown prefix - assume http://
*/
- char * url_param_prefixed = malloc(7 + 1 + strlen(url_param));
+ const size_t url_param_prefixed_size = 7 + 1 + strlen(url_param);
+ char * url_param_prefixed = malloc(url_param_prefixed_size);
if (NULL == url_param_prefixed)
{
free(url_param);
free_map(exports);
return JB_ERR_MEMORY;
}
- strcpy(url_param_prefixed, "http://");
- strcpy(url_param_prefixed + 7, url_param);
+ strlcpy(url_param_prefixed, "http://", url_param_prefixed_size);
+ strlcat(url_param_prefixed, url_param, url_param_prefixed_size);
free(url_param);
url_param = url_param_prefixed;
}
+ /*
+ * Hide "toggle off" warning if Privoxy is toggled on.
+ */
+ if (
+#ifdef FEATURE_TOGGLE
+ (global_toggle_state == 1) &&
+#endif /* def FEATURE_TOGGLE */
+ map_block_killer(exports, "privoxy-is-toggled-off")
+ )
+ {
+ free_map(exports);
+ return JB_ERR_MEMORY;
+ }
if (url_param[0] == '\0')
{
}
}
- matches = strdup("<table class=\"transparent\">");
+ matches = strdup("<table summary=\"\" class=\"transparent\">");
for (i = 0; i < MAX_AF_FILES; i++)
{
if (NULL == csp->config->actions_file_short[i]
- || !strcmp(csp->config->actions_file_short[i], "standard")) continue;
+ || !strcmp(csp->config->actions_file_short[i], "standard.action")) continue;
b = NULL;
hits = 1;
/* FIXME: Hardcoded HTML! */
string_append(&matches, "<tr><th>In file: ");
string_join (&matches, html_encode(csp->config->actions_file_short[i]));
- snprintf(buf, 150, ".action <a class=\"cmd\" href=\"/show-status?file=actions&index=%d\">", i);
+ snprintf(buf, sizeof(buf), " <a class=\"cmd\" href=\"/show-status?file=actions&index=%d\">", i);
string_append(&matches, buf);
string_append(&matches, "View</a>");
#ifdef FEATURE_CGI_EDIT_ACTIONS
- string_append(&matches, " <a class=\"cmd\" href=\"/edit-actions-list?f=");
- string_join (&matches, html_encode(csp->config->actions_file_short[i]));
- string_append(&matches, "\">Edit</a>");
+ snprintf(buf, sizeof(buf), " <a class=\"cmd\" href=\"/edit-actions-list?f=%d\">", i);
+ string_append(&matches, buf);
+ string_append(&matches, "Edit</a>");
#endif
string_append(&matches, "</th></tr>\n");
{
string_append(&matches, "<tr><td>{");
string_join (&matches, actions_to_html(csp, b->action));
- string_append(&matches, " }</b><br>\n<code>");
+ string_append(&matches, " }<br>\n<code>");
string_join (&matches, html_encode(b->url->spec));
string_append(&matches, "</code></td></tr>\n");
}
string_append(&matches, "</table>\n");
+ /*
+ * Fill in forwarding settings.
+ *
+ * The possibilities are:
+ * - no forwarding
+ * - http forwarding only
+ * - socks4(a) forwarding only
+ * - socks4(a) and http forwarding.
+ *
+ * XXX: Parts of this code could be reused for the
+ * "forwarding-failed" template which currently doesn't
+ * display the proxy port and an eventuell second forwarder.
+ */
+ {
+ const struct forward_spec * fwd = forward_url(url_to_query, csp);
+
+ if ((fwd->gateway_host == NULL) && (fwd->forward_host == NULL))
+ {
+ if (!err) err = map_block_killer(exports, "socks-forwarder");
+ if (!err) err = map_block_killer(exports, "http-forwarder");
+ }
+ else
+ {
+ char port[10]; /* We save proxy ports as int but need a string here */
+
+ if (!err) err = map_block_killer(exports, "no-forwarder");
+
+ if (fwd->gateway_host != NULL)
+ {
+ if (!err) err = map(exports, "socks-type", 1, (fwd->type == SOCKS_4) ?
+ "socks4" : "socks4a", 1);
+ if (!err) err = map(exports, "gateway-host", 1, fwd->gateway_host, 1);
+ snprintf(port, sizeof(port), "%d", fwd->gateway_port);
+ if (!err) err = map(exports, "gateway-port", 1, port, 1);
+ }
+ else
+ {
+ if (!err) err = map_block_killer(exports, "socks-forwarder");
+ }
+
+ if (fwd->forward_host != NULL)
+ {
+ if (!err) err = map(exports, "forward-host", 1, fwd->forward_host, 1);
+ snprintf(port, sizeof(port), "%d", fwd->forward_port);
+ if (!err) err = map(exports, "forward-port", 1, port, 1);
+ }
+ else
+ {
+ if (!err) err = map_block_killer(exports, "http-forwarder");
+ }
+ }
+ }
+
free_http_request(url_to_query);
- if (matches == NULL)
+ if (err || matches == NULL)
{
free_current_action(action);
free_map(exports);