* File : $Source: /cvsroot/ijbswa/current/cgi.c,v $
*
* Purpose : Declares functions to intercept request, generate
- * html or gif answers, and to compose HTTP resonses.
+ * html or gif answers, and to compose HTTP responses.
* This only contains the framework functions, the
* actual handler functions are declared elsewhere.
*
- * Copyright : Written by and Copyright (C) 2001-2017
+ * Copyright : Written by and Copyright (C) 2001-2021
* members of the Privoxy team. https://www.privoxy.org/
*
* Based on the Internet Junkbuster originally written
#if defined(FEATURE_CGI_EDIT_ACTIONS) || defined(FEATURE_TOGGLE)
#include "cgiedit.h"
#endif /* defined(FEATURE_CGI_EDIT_ACTIONS) || defined (FEATURE_TOGGLE) */
+#ifdef FEATURE_HTTPS_INSPECTION
+#include "ssl.h"
+#endif
/* loadcfg.h is for global_toggle_state only */
#include "loadcfg.h"
/* jcc.h is for mutex semaphore globals only */
#include "jcc.h"
+static char *make_menu(const struct client_state *csp, const char *self);
+
/*
* List of CGI functions: name, handler, description
* Note: Do NOT use single quotes in the description;
*/
{ "client-tags",
cgi_show_client_tags,
- "View or toggle the tags that can be set based on the clients address",
+ "View or toggle the tags that can be set based on the client's address",
TRUE },
#endif
{ "show-request",
{ "user-manual",
cgi_send_user_manual,
NULL, TRUE /* Send user-manual */ },
+ { "wpad.dat",
+ cgi_send_wpad,
+ NULL, TRUE /* Send wpad.dat proxy autoconfiguration file */ },
{ NULL, /* NULL Indicates end of list and default page */
cgi_error_404,
NULL, TRUE /* Unknown CGI page */ }
"\000\000\000\000\111\105\116\104\256\102\140\202";
/*
- * 1x1 transparant PNG.
+ * 1x1 transparent PNG.
*/
const char image_blank_data[] =
"\211\120\116\107\015\012\032\012\000\000\000\015\111\110\104\122"
"\270\005\000\073";
/*
- * 1x1 transparant GIF.
+ * 1x1 transparent GIF.
*/
const char image_blank_data[] =
"GIF89a\001\000\001\000\200\000\000\377\377\377\000\000"
static char *grep_cgi_referrer(const struct client_state *csp)
{
struct list_entry *p;
+ struct list_entry *first_header =
+#ifdef FEATURE_HTTPS_INSPECTION
+ client_use_ssl(csp) ? csp->https_headers->first :
+#endif
+ csp->headers->first;
- for (p = csp->headers->first; p != NULL; p = p->next)
+ for (p = first_header; p != NULL; p = p->next)
{
if (p->str == NULL) continue;
if (strncmpic(p->str, "Referer: ", 9) == 0)
{
char *referrer;
static const char alternative_prefix[] = "http://" CGI_SITE_1_HOST "/";
+#ifdef FEATURE_HTTPS_INSPECTION
+ static const char alt_prefix_https[] = "https://" CGI_SITE_1_HOST "/";
+#endif
const char *trusted_cgi_referrer = csp->config->trusted_cgi_referrer;
referrer = grep_cgi_referrer(csp);
log_error(LOG_LEVEL_ERROR, "Denying access to %s. No referrer found.",
csp->http->url);
}
- else if ((0 == strncmp(referrer, CGI_PREFIX, sizeof(CGI_PREFIX)-1)
- || (0 == strncmp(referrer, alternative_prefix, strlen(alternative_prefix)))))
+ else if ((0 == strncmp(referrer, CGI_PREFIX_HTTP, sizeof(CGI_PREFIX_HTTP)-1))
+#ifdef FEATURE_HTTPS_INSPECTION
+ || (0 == strncmp(referrer, CGI_PREFIX_HTTPS, sizeof(CGI_PREFIX_HTTPS)-1))
+ || (0 == strncmp(referrer, alt_prefix_https, strlen(alt_prefix_https)))
+#endif
+ || (0 == strncmp(referrer, alternative_prefix, strlen(alternative_prefix))))
{
/* Trustworthy referrer */
log_error(LOG_LEVEL_CGI, "Granting access to %s, referrer %s is trustworthy.",
*query_args_start++ = '\0';
param_list = new_map();
err = map(param_list, "file", 1, url_decode(query_args_start), 0);
- if (JB_ERR_OK != err) {
+ if (JB_ERR_OK != err)
+ {
free(param_list);
free(path_copy);
return cgi_error_memory();
* The same hack is used in get_last_url() so it looks like
* a real solution is needed.
*/
- size_t max_segments = strlen(argstring) / 2;
- if (max_segments == 0)
- {
- /*
- * XXX: If the argstring is empty, there's really
- * no point in creating a param list, but currently
- * other parts of Privoxy depend on the list's existence.
- */
- max_segments = 1;
- }
+ size_t max_segments = strlen(argstring) / 2 + 1;
vector = malloc_or_die(max_segments * sizeof(char *));
cgi_params = new_map();
*
* Function : get_string_param
*
- * Description : Get a string paramater, to be used as an
- * ACTION_STRING or ACTION_MULTI paramater.
+ * Description : Get a string parameter, to be used as an
+ * ACTION_STRING or ACTION_MULTI parameter.
* Validates the input to prevent stupid/malicious
* users from corrupting their action file.
*
* Parameters :
* 1 : parameters = map of cgi parameters
* 2 : param_name = The name of the parameter to read
- * 3 : pparam = destination for paramater. Allocated as
+ * 3 : pparam = destination for parameter. Allocated as
* part of the map "parameters", so don't free it.
* Set to NULL if not specified.
*
- * Returns : JB_ERR_OK on success, or if the paramater
+ * Returns : JB_ERR_OK on success, or if the parameter
* was not specified.
* JB_ERR_MEMORY on out-of-memory.
- * JB_ERR_CGI_PARAMS if the paramater is not valid.
+ * JB_ERR_CGI_PARAMS if the parameter is not valid.
*
*********************************************************************/
jb_err get_string_param(const struct map *parameters,
").</p>\n"
"</body>\n"
"</html>\n";
- const size_t body_size = strlen(body_prefix) + strlen(template_name) + strlen(body_suffix) + 1;
+ size_t body_size = strlen(body_prefix) + strlen(body_suffix) + 1;
+ const char *encoded_template_name;
assert(csp);
assert(rsp);
rsp->head_length = 0;
rsp->is_static = 0;
+ encoded_template_name = html_encode(template_name);
+ if (encoded_template_name == NULL)
+ {
+ return JB_ERR_MEMORY;
+ }
+
+ body_size += strlen(encoded_template_name);
rsp->body = malloc_or_die(body_size);
strlcpy(rsp->body, body_prefix, body_size);
- strlcat(rsp->body, template_name, body_size);
+ strlcat(rsp->body, encoded_template_name, body_size);
+ freez(encoded_template_name);
strlcat(rsp->body, body_suffix, body_size);
rsp->status = strdup(status);
* In this context, "unexpected" means "anything other
* than JB_ERR_MEMORY or JB_ERR_CGI_PARAMS" - CGIs are
* expected to handle all other errors internally,
- * since they can give more relavent error messages
+ * since they can give more relevant error messages
* that way.
*
* Note this is not a true CGI, it takes an error
static const char body_suffix[] =
"</b></p>\n"
"<p>Please "
- "<a href=\"http://sourceforge.net/tracker/?group_id=11118&atid=111118\">"
+ "<a href=\"https://sourceforge.net/p/ijbswa/bugs/\">"
"file a bug report</a>.</p>\n"
"</body>\n"
"</html>\n";
#elif defined(MUTEX_LOCKS_AVAILABLE)
privoxy_mutex_lock(&localtime_mutex);
timeptr = localtime(¤t_time);
- privoxy_mutex_unlock(&localtime_mutex);
#else
timeptr = localtime(¤t_time);
#endif
strftime(buf, buffer_size, "%a %b %d %X %Z %Y", timeptr);
+#if !defined(HAVE_LOCALTIME_R) && defined(MUTEX_LOCKS_AVAILABLE)
+ privoxy_mutex_unlock(&localtime_mutex);
+#endif
}
(Bytef *)buffer, *buffer_length, compression_level))
{
log_error(LOG_LEVEL_ERROR,
- "compress2() failed. Buffer size: %d, compression level: %d.",
+ "compress2() failed. Buffer size: %lu, 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",
+ "Compressed content from %lu to %lu bytes. Compression level: %d",
*buffer_length, new_length, compression_level);
*buffer_length = (size_t)new_length;
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);
- if (!err) err = map(exports, "default-cgi", 1, html_encode(CGI_PREFIX), 0);
- if (!err) err = map(exports, "menu", 1, make_menu(caller, csp->config->feature_flags), 0);
+ if (!err)
+ {
+ err = map(exports, "default-cgi", 1, html_encode(CGI_PREFIX), 0);
+ }
+ if (!err) err = map(exports, "menu", 1, make_menu(csp, caller), 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))
else
{
/* 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, "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
* and the toggle CGI if toggling is disabled.
*
* Parameters :
- * 1 : self = name of CGI to leave out, can be NULL for
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ * 2 : self = name of CGI to leave out, can be NULL for
* complete listing.
- * 2 : feature_flags = feature bitmap from csp->config
- *
*
* Returns : menu string, or NULL on out-of-memory error.
*
*********************************************************************/
-char *make_menu(const char *self, const unsigned feature_flags)
+char *make_menu(const struct client_state *csp, const char *self)
{
const struct cgi_dispatcher *d;
char *result = strdup("");
{
#ifdef FEATURE_TOGGLE
- if (!(feature_flags & RUNTIME_FEATURE_CGI_TOGGLE) && !strcmp(d->name, "toggle"))
+ if (!(csp->config->feature_flags & RUNTIME_FEATURE_CGI_TOGGLE) && !strcmp(d->name, "toggle"))
{
/*
* Suppress the toggle link if remote toggling is disabled.