+ if (!err) err = map(exports, "protocol", 1, csp->http->ssl ? "https://" : "http://", 1);
+ if (!err) err = map(exports, "hostport", 1, html_encode(csp->http->hostport), 0);
+ if (!err) err = map(exports, "path", 1, html_encode(csp->http->path), 0);
+ if (!err) err = map(exports, "path-ue", 1, url_encode(csp->http->path), 0);
+ if (!err)
+ {
+ const char *block_reason;
+ if (csp->action->string[ACTION_STRING_BLOCK] != NULL)
+ {
+ block_reason = csp->action->string[ACTION_STRING_BLOCK];
+ }
+ else
+ {
+ assert(connect_port_is_forbidden(csp));
+ block_reason = "Forbidden CONNECT port.";
+ }
+ err = map(exports, "block-reason", 1, html_encode(block_reason), 0);
+ }
+ if (err)
+ {
+ free_map(exports);
+ free_http_response(rsp);
+ return cgi_error_memory();
+ }
+
+ err = template_fill_for_cgi(csp, "blocked", exports, rsp);
+ if (err)
+ {
+ free_http_response(rsp);
+ return cgi_error_memory();
+ }
+ }
+ rsp->crunch_reason = BLOCKED;
+
+ return finish_http_response(csp, rsp);
+
+}
+
+
+#ifdef FEATURE_TRUST
+/*********************************************************************
+ *
+ * Function : trust_url FIXME: I should be called distrust_url
+ *
+ * Description : Calls is_untrusted_url to determine if the URL is trusted
+ * and if not, returns a HTTP 403 response with a reject message.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : NULL => trusted, else http_response.
+ *
+ *********************************************************************/
+struct http_response *trust_url(struct client_state *csp)
+{
+ struct http_response *rsp;
+ struct map * exports;
+ char buf[BUFFER_SIZE];
+ char *p;
+ struct url_spec **tl;
+ struct url_spec *t;
+ jb_err err;
+
+ /*
+ * Don't bother to work on trusted URLs
+ */
+ if (!is_untrusted_url(csp))
+ {
+ return NULL;
+ }
+
+ /*
+ * Else, prepare a response:
+ */
+ if (NULL == (rsp = alloc_http_response()))
+ {
+ return cgi_error_memory();
+ }
+
+ rsp->status = strdup("403 Request blocked by Privoxy");
+ exports = default_exports(csp, NULL);
+ if (exports == NULL || rsp->status == NULL)
+ {
+ free_http_response(rsp);
+ return cgi_error_memory();
+ }
+
+ /*
+ * Export the protocol, host, port, and referrer information
+ */
+ err = map(exports, "hostport", 1, csp->http->hostport, 1);
+ if (!err) err = map(exports, "protocol", 1, csp->http->ssl ? "https://" : "http://", 1);
+ if (!err) err = map(exports, "path", 1, csp->http->path, 1);
+
+ if (NULL != (p = get_header_value(csp->headers, "Referer:")))
+ {
+ if (!err) err = map(exports, "referrer", 1, html_encode(p), 0);
+ }
+ else
+ {
+ if (!err) err = map(exports, "referrer", 1, "none set", 1);
+ }
+
+ if (err)
+ {
+ free_map(exports);
+ free_http_response(rsp);
+ return cgi_error_memory();
+ }
+
+ /*
+ * Export the trust list
+ */
+ p = strdup("");
+ for (tl = csp->config->trust_list; (t = *tl) != NULL ; tl++)
+ {
+ snprintf(buf, sizeof(buf), "<li>%s</li>\n", t->spec);
+ string_append(&p, buf);
+ }
+ err = map(exports, "trusted-referrers", 1, p, 0);
+
+ if (err)
+ {
+ free_map(exports);
+ free_http_response(rsp);
+ return cgi_error_memory();
+ }
+
+ /*
+ * Export the trust info, if available
+ */
+ if (csp->config->trust_info->first)
+ {
+ struct list_entry *l;
+
+ p = strdup("");
+ for (l = csp->config->trust_info->first; l ; l = l->next)
+ {
+ snprintf(buf, sizeof(buf), "<li> <a href=\"%s\">%s</a><br>\n", l->str, l->str);
+ string_append(&p, buf);
+ }
+ err = map(exports, "trust-info", 1, p, 0);
+ }
+ else
+ {
+ err = map_block_killer(exports, "have-trust-info");
+ }
+
+ if (err)
+ {
+ free_map(exports);
+ free_http_response(rsp);
+ return cgi_error_memory();
+ }
+
+ /*
+ * Export the force conditional block killer if
+ *
+ * - Privoxy was compiled without FEATURE_FORCE_LOAD, or
+ * - Privoxy is configured to enforce blocks, or
+ * - it's a CONNECT request and enforcing wouldn't work anyway.
+ */
+#ifdef FEATURE_FORCE_LOAD
+ if ((csp->config->feature_flags & RUNTIME_FEATURE_ENFORCE_BLOCKS)
+ || (0 == strcmpic(csp->http->gpc, "connect")))
+ {
+ err = map_block_killer(exports, "force-support");
+ }
+ else
+ {
+ err = map(exports, "force-prefix", 1, FORCE_PREFIX, 1);
+ }
+#else /* ifndef FEATURE_FORCE_LOAD */
+ err = map_block_killer(exports, "force-support");
+#endif /* ndef FEATURE_FORCE_LOAD */
+
+ if (err)
+ {
+ free_map(exports);
+ free_http_response(rsp);
+ return cgi_error_memory();
+ }
+
+ /*
+ * Build the response
+ */
+ err = template_fill_for_cgi(csp, "untrusted", exports, rsp);
+ if (err)
+ {
+ free_http_response(rsp);
+ return cgi_error_memory();
+ }
+ rsp->crunch_reason = UNTRUSTED;
+
+ return finish_http_response(csp, rsp);
+}
+#endif /* def FEATURE_TRUST */
+
+
+/*********************************************************************
+ *
+ * Function : compile_dynamic_pcrs_job_list
+ *
+ * Description : Compiles a dynamic pcrs job list (one with variables
+ * resolved at request time)
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ * 2 : b = The filter list to compile
+ *
+ * Returns : NULL in case of errors, otherwise the
+ * pcrs job list.
+ *
+ *********************************************************************/
+pcrs_job *compile_dynamic_pcrs_job_list(const struct client_state *csp, const struct re_filterfile_spec *b)
+{
+ struct list_entry *pattern;
+ pcrs_job *job_list = NULL;
+ pcrs_job *dummy = NULL;
+ pcrs_job *lastjob = NULL;
+ int error = 0;
+
+ const struct pcrs_variable variables[] =
+ {
+ {"url", csp->http->url, 1},
+ {"path", csp->http->path, 1},
+ {"host", csp->http->host, 1},
+ {"origin", csp->ip_addr_str, 1},
+ {NULL, NULL, 1}
+ };
+
+ for (pattern = b->patterns->first; pattern != NULL; pattern = pattern->next)
+ {
+ assert(pattern->str != NULL);