+#include "parsers.h"
+#include "urlmatch.h"
+#include "errlog.h"
+
+const char cgisimple_h_rcs[] = CGISIMPLE_H_VERSION;
+
+
+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;
+
+/*********************************************************************
+ *
+ * Function : cgi_default
+ *
+ * Description : CGI function that is called for the CGI_SITE_1_HOST
+ * and CGI_SITE_2_HOST/CGI_SITE_2_PATH base URLs.
+ * Boring - only exports the default exports.
+ *
+ * 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
+ *
+ *********************************************************************/
+jb_err cgi_default(struct client_state *csp,
+ struct http_response *rsp,
+ const struct map *parameters)
+{
+ struct map *exports;
+
+ assert(csp);
+ assert(rsp);
+
+ if (NULL == (exports = default_exports(csp, "")))
+ {
+ return JB_ERR_MEMORY;
+ }
+
+ return template_fill_for_cgi(csp, "default", exports, rsp);
+}
+
+
+/*********************************************************************
+ *
+ * Function : cgi_error_404
+ *
+ * Description : CGI function that is called if an unknown action was
+ * given.
+ *
+ * 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_error_404(struct client_state *csp,
+ struct http_response *rsp,
+ const struct map *parameters)
+{
+ struct map *exports;
+
+ assert(csp);
+ assert(rsp);
+ assert(parameters);
+
+ if (NULL == (exports = default_exports(csp, NULL)))
+ {
+ return JB_ERR_MEMORY;
+ }
+
+ rsp->status = strdup("404 Privoxy configuration page not found");
+ if (rsp->status == NULL)
+ {
+ free_map(exports);
+ return JB_ERR_MEMORY;
+ }
+
+ return template_fill_for_cgi(csp, "cgi-error-404", exports, rsp);
+}
+
+
+#ifdef FEATURE_GRACEFUL_TERMINATION
+/*********************************************************************
+ *
+ * Function : cgi_die
+ *
+ * Description : CGI function to shut down Privoxy.
+ * NOTE: Turning this on in a production build
+ * would be a BAD idea. An EXTREMELY BAD idea.
+ * In short, don't do it.
+ *
+ * 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_die (struct client_state *csp,
+ struct http_response *rsp,
+ const struct map *parameters)
+{
+ assert(csp);
+ assert(rsp);
+ assert(parameters);
+
+ /* quit */
+ g_terminate = 1;
+
+ /*
+ * I don't really care what gets sent back to the browser.
+ * Take the easy option - "out of memory" page.
+ */
+
+ return JB_ERR_MEMORY;
+}
+#endif /* def FEATURE_GRACEFUL_TERMINATION */
+
+
+/*********************************************************************
+ *
+ * Function : cgi_show_request
+ *
+ * Description : Show the client's request and what sed() would have
+ * made of it.
+ *
+ * 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_show_request(struct client_state *csp,
+ struct http_response *rsp,
+ const struct map *parameters)
+{
+ char *p;
+ struct map *exports;
+
+ assert(csp);
+ assert(rsp);
+ assert(parameters);
+
+ if (NULL == (exports = default_exports(csp, "show-request")))
+ {
+ return JB_ERR_MEMORY;
+ }
+
+ /*
+ * Repair the damage done to the IOB by get_header()
+ */
+ for (p = csp->iob->buf; p < csp->iob->eod; p++)
+ {
+ if (*p == '\0') *p = '\n';
+ }
+
+ /*
+ * Export the original client's request and the one we would
+ * be sending to the server if this wasn't a CGI call
+ */
+
+ if (map(exports, "client-request", 1, html_encode(csp->iob->buf), 0))
+ {
+ free_map(exports);
+ return JB_ERR_MEMORY;
+ }
+
+ if (map(exports, "processed-request", 1,
+ html_encode_and_free_original(list_to_text(csp->headers)), 0))
+ {
+ free_map(exports);
+ return JB_ERR_MEMORY;
+ }
+
+ return template_fill_for_cgi(csp, "show-request", exports, rsp);
+}
+
+
+/*********************************************************************
+ *
+ * Function : cgi_send_banner
+ *
+ * Description : CGI function that returns a banner.
+ *
+ * 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 :
+ * type : Selects the type of banner between "trans", "logo",
+ * and "auto". Defaults to "logo" if absent or invalid.
+ * "auto" means to select as if we were image-blocking.
+ * (Only the first character really counts; b and t are
+ * equivalent).
+ *
+ * Returns : JB_ERR_OK on success
+ * JB_ERR_MEMORY on out-of-memory error.
+ *
+ *********************************************************************/
+jb_err cgi_send_banner(struct client_state *csp,
+ struct http_response *rsp,
+ const struct map *parameters)
+{
+ char imagetype = lookup(parameters, "type")[0];
+
+ /*
+ * If type is auto, then determine the right thing
+ * to do from the set-image-blocker action
+ */
+ if (imagetype == 'a')
+ {
+ /*
+ * Default to pattern
+ */
+ imagetype = 'p';
+
+#ifdef FEATURE_IMAGE_BLOCKING
+ if ((csp->action->flags & ACTION_IMAGE_BLOCKER) != 0)
+ {
+ static const char prefix1[] = CGI_PREFIX "send-banner?type=";
+ static const char prefix2[] = "http://" CGI_SITE_1_HOST "/send-banner?type=";
+ const char *p = csp->action->string[ACTION_STRING_IMAGE_BLOCKER];
+
+ if (p == NULL)
+ {
+ /* Use default - nothing to do here. */
+ }
+ else if (0 == strcmpic(p, "blank"))
+ {
+ imagetype = 'b';
+ }
+ else if (0 == strcmpic(p, "pattern"))
+ {
+ imagetype = 'p';
+ }
+
+ /*
+ * If the action is to call this CGI, determine
+ * the argument:
+ */
+ else if (0 == strncmpic(p, prefix1, sizeof(prefix1) - 1))
+ {
+ imagetype = p[sizeof(prefix1) - 1];
+ }
+ else if (0 == strncmpic(p, prefix2, sizeof(prefix2) - 1))
+ {
+ imagetype = p[sizeof(prefix2) - 1];
+ }
+
+ /*
+ * Everything else must (should) be a URL to
+ * redirect to.
+ */
+ else
+ {
+ imagetype = 'r';
+ }
+ }
+#endif /* def FEATURE_IMAGE_BLOCKING */
+ }
+
+ /*
+ * Now imagetype is either the non-auto type we were called with,
+ * or it was auto and has since been determined. In any case, we
+ * can proceed to actually answering the request by sending a redirect
+ * or an image as appropriate:
+ */
+ if (imagetype == 'r')
+ {
+ rsp->status = strdup("302 Local Redirect from Privoxy");
+ if (rsp->status == NULL)
+ {
+ return JB_ERR_MEMORY;
+ }
+ if (enlist_unique_header(rsp->headers, "Location",
+ csp->action->string[ACTION_STRING_IMAGE_BLOCKER]))
+ {
+ return JB_ERR_MEMORY;
+ }
+ }
+ else
+ {
+ if ((imagetype == 'b') || (imagetype == 't'))
+ {
+ rsp->body = bindup(image_blank_data, image_blank_length);
+ rsp->content_length = image_blank_length;
+ }
+ else
+ {
+ rsp->body = bindup(image_pattern_data, image_pattern_length);
+ rsp->content_length = image_pattern_length;
+ }
+
+ if (rsp->body == NULL)
+ {
+ return JB_ERR_MEMORY;
+ }
+ if (enlist(rsp->headers, "Content-Type: " BUILTIN_IMAGE_MIMETYPE))
+ {
+ return JB_ERR_MEMORY;
+ }
+
+ rsp->is_static = 1;
+ }
+
+ return JB_ERR_OK;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : cgi_transparent_image
+ *
+ * Description : CGI function that sends a 1x1 transparent image.
+ *
+ * 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_transparent_image(struct client_state *csp,
+ struct http_response *rsp,
+ const struct map *parameters)
+{
+ rsp->body = bindup(image_blank_data, image_blank_length);
+ rsp->content_length = image_blank_length;
+
+ if (rsp->body == NULL)
+ {
+ return JB_ERR_MEMORY;
+ }
+
+ if (enlist(rsp->headers, "Content-Type: " BUILTIN_IMAGE_MIMETYPE))
+ {
+ return JB_ERR_MEMORY;
+ }
+
+ rsp->is_static = 1;
+
+ return JB_ERR_OK;
+
+}
+
+
+/*********************************************************************
+ *
+ * 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;