X-Git-Url: http://www.privoxy.org/gitweb/?a=blobdiff_plain;f=cgisimple.c;h=562eeb63bb91e8ab4bdb0f5c083811f26582afb6;hb=0eb832922b1d6453f8fc4d0445369d9d7e5babde;hp=6d75da606cdf80c93fc7927ee894e1cc54576b9a;hpb=9b18513b5159156a8f29376aca23d711df43370f;p=privoxy.git
diff --git a/cgisimple.c b/cgisimple.c
index 6d75da60..562eeb63 100644
--- a/cgisimple.c
+++ b/cgisimple.c
@@ -1,4 +1,4 @@
-const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.123 2014/05/20 11:55:09 fabiankeil Exp $";
+const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.149 2017/05/04 14:33:17 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/cgisimple.c,v $
@@ -6,7 +6,7 @@ const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.123 2014/05/20 11:55:09 fabia
* Purpose : Simple CGIs to get information about Privoxy's
* status.
*
- * Copyright : Written by and Copyright (C) 2001-2014 the
+ * Copyright : Written by and Copyright (C) 2001-2017 the
* Privoxy team. http://www.privoxy.org/
*
* Based on the Internet Junkbuster originally written
@@ -60,6 +60,9 @@ const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.123 2014/05/20 11:55:09 fabia
#include "parsers.h"
#include "urlmatch.h"
#include "errlog.h"
+#ifdef FEATURE_CLIENT_TAGS
+#include "client-tags.h"
+#endif
const char cgisimple_h_rcs[] = CGISIMPLE_H_VERSION;
@@ -142,12 +145,7 @@ jb_err cgi_error_404(struct client_state *csp,
return JB_ERR_MEMORY;
}
- rsp->status = strdup("404 Privoxy configuration page not found");
- if (rsp->status == NULL)
- {
- free_map(exports);
- return JB_ERR_MEMORY;
- }
+ rsp->status = strdup_or_die("404 Privoxy configuration page not found");
return template_fill_for_cgi(csp, "cgi-error-404", exports, rsp);
}
@@ -171,7 +169,6 @@ jb_err cgi_error_404(struct client_state *csp,
* 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,
@@ -184,7 +181,7 @@ jb_err cgi_die (struct client_state *csp,
"
\n"
" Privoxy shutdown request received\n"
" \n"
- " \n"
+ " \n"
"\n"
"\n"
"Privoxy shutdown request received
\n"
@@ -205,13 +202,8 @@ jb_err cgi_die (struct client_state *csp,
rsp->head_length = 0;
rsp->is_static = 0;
- rsp->body = strdup(body);
- rsp->status = strdup(status);
-
- if ((rsp->body == NULL) || (rsp->status == NULL))
- {
- return JB_ERR_MEMORY;
- }
+ rsp->body = strdup_or_die(body);
+ rsp->status = strdup_or_die(status);
return JB_ERR_OK;
}
@@ -282,6 +274,242 @@ jb_err cgi_show_request(struct client_state *csp,
}
+#ifdef FEATURE_CLIENT_TAGS
+/*********************************************************************
+ *
+ * Function : cgi_create_client_tag_form
+ *
+ * Description : Creates a HTML form to enable or disable a given
+ * client tag.
+ * XXX: Could use a template.
+ *
+ * Parameters :
+ * 1 : form = Buffer to fill with the generated form
+ * 2 : size = Size of the form buffer
+ * 3 : tag = Name of the tag this form should affect
+ * 4 : toggle_state = Desired state after the button pressed 0
+ * 5 : expires = Whether or not the tag should be enabled.
+ * Only checked if toggle_state is 1.
+ *
+ * Returns : void
+ *
+ *********************************************************************/
+static void cgi_create_client_tag_form(char *form, size_t size,
+ const char *tag, int toggle_state, int expires)
+{
+ char *button_name;
+
+ if (toggle_state == 1)
+ {
+ button_name = (expires == 1) ? "Enable" : "Enable temporarily";
+ }
+ else
+ {
+ assert(toggle_state == 0);
+ button_name = "Disable";
+ }
+
+ snprintf(form, size,
+ "", tag, toggle_state, !expires, button_name);
+}
+
+/*********************************************************************
+ *
+ * Function : cgi_show_client_tags
+ *
+ * Description : Shows the tags that can be set based on the client
+ * address (opt-in).
+ *
+ * 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_client_tags(struct client_state *csp,
+ struct http_response *rsp,
+ const struct map *parameters)
+{
+ struct map *exports;
+ struct client_tag_spec *this_tag;
+ jb_err err = JB_ERR_OK;
+ char *client_tag_status;
+ char buf[1000];
+ time_t refresh_delay;
+
+ assert(csp);
+ assert(rsp);
+ assert(parameters);
+
+ if (NULL == (exports = default_exports(csp, "client-tags")))
+ {
+ return JB_ERR_MEMORY;
+ }
+ assert(csp->client_address != NULL);
+
+ this_tag = csp->config->client_tags;
+ if (this_tag->name == NULL)
+ {
+ client_tag_status = strdup_or_die("No tags available.
\n");
+ }
+ else
+ {
+ client_tag_status = strdup_or_die("\n"
+ "Tag name | \n"
+ "Current state | Change state | Description |
\n");
+ while ((this_tag != NULL) && (this_tag->name != NULL))
+ {
+ int tag_state;
+
+ privoxy_mutex_lock(&client_tags_mutex);
+ tag_state = client_has_requested_tag(csp->client_address, this_tag->name);
+ privoxy_mutex_unlock(&client_tags_mutex);
+ if (!err) err = string_append(&client_tag_status, "");
+ if (!err) err = string_append(&client_tag_status, this_tag->name);
+ if (!err) err = string_append(&client_tag_status, " | ");
+ if (!err) err = string_append(&client_tag_status, tag_state == 1 ? "Enabled" : "Disabled");
+ if (!err) err = string_append(&client_tag_status, " | ");
+ cgi_create_client_tag_form(buf, sizeof(buf), this_tag->name, !tag_state, 1);
+ if (!err) err = string_append(&client_tag_status, buf);
+ if (tag_state == 0)
+ {
+ cgi_create_client_tag_form(buf, sizeof(buf), this_tag->name, !tag_state, 0);
+ if (!err) err = string_append(&client_tag_status, buf);
+ }
+ if (!err) err = string_append(&client_tag_status, " | ");
+ if (!err) err = string_append(&client_tag_status, this_tag->description);
+ if (!err) err = string_append(&client_tag_status, " |
\n");
+ if (err)
+ {
+ break;
+ }
+ this_tag = this_tag->next;
+ }
+ if (!err) err = string_append(&client_tag_status, "
\n");
+ if (err)
+ {
+ free_map(exports);
+ return JB_ERR_MEMORY;
+ }
+ }
+ refresh_delay = get_next_tag_timeout_for_client(csp->client_address);
+ if (refresh_delay != 0)
+ {
+ snprintf(buf, sizeof(buf), "%d", csp->config->client_tag_lifetime);
+ if (map(exports, "refresh-delay", 1, buf, 1))
+ {
+ free_map(exports);
+ return JB_ERR_MEMORY;
+ }
+ }
+ else
+ {
+ err = map_block_killer(exports, "tags-expire");
+ if (err != JB_ERR_OK)
+ {
+ return err;
+ }
+ }
+
+ if (map(exports, "client-tags", 1, client_tag_status, 0))
+ {
+ free_map(exports);
+ return JB_ERR_MEMORY;
+ }
+
+ if (map(exports, "client-ip-addr", 1, csp->client_address, 1))
+ {
+ free_map(exports);
+ return JB_ERR_MEMORY;
+ }
+
+ return template_fill_for_cgi(csp, "client-tags", exports, rsp);
+}
+
+
+/*********************************************************************
+ *
+ * Function : cgi_toggle_client_tag
+ *
+ * Description : Toggles a client tag and redirects to the show-tags
+ * page
+ *
+ * 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
+ * 1 : tag = Name of the tag to enable or disable
+ * 2 : toggle-state = How to toggle the tag (0/1)
+ * 3 : expires = Set to 1 if the tag should be enabled
+ * temporarily, otherwise set to 0
+ *
+ * Returns : JB_ERR_OK on success
+ * JB_ERR_MEMORY on out-of-memory error.
+ *
+ *********************************************************************/
+jb_err cgi_toggle_client_tag(struct client_state *csp,
+ struct http_response *rsp,
+ const struct map *parameters)
+{
+ const char *toggled_tag;
+ const char *toggle_state;
+ const char *tag_expires;
+ time_t time_to_live;
+
+ assert(csp);
+ assert(rsp);
+ assert(parameters);
+
+ toggled_tag = lookup(parameters, "tag");
+ if (*toggled_tag == '\0')
+ {
+ log_error(LOG_LEVEL_ERROR, "Received tag toggle request without tag");
+ }
+ else
+ {
+ tag_expires = lookup(parameters, "expires");
+ if (*tag_expires == '0')
+ {
+ time_to_live = 0;
+ }
+ else
+ {
+ time_to_live = csp->config->client_tag_lifetime;
+ }
+ toggle_state = lookup(parameters, "toggle-state");
+ if (*toggle_state == '1')
+ {
+ enable_client_specific_tag(csp, toggled_tag, time_to_live);
+ }
+ else
+ {
+ disable_client_specific_tag(csp, toggled_tag);
+ }
+ }
+ rsp->status = strdup_or_die("302 Done dealing with toggle request");
+ if (enlist_unique_header(rsp->headers,
+ "Location", CGI_PREFIX "client-tags"))
+ {
+ return JB_ERR_MEMORY;
+ }
+ return JB_ERR_OK;
+
+}
+#endif /* def FEATURE_CLIENT_TAGS */
+
+
/*********************************************************************
*
* Function : cgi_send_banner
@@ -374,11 +602,7 @@ jb_err cgi_send_banner(struct client_state *csp,
*/
if (imagetype == 'r')
{
- rsp->status = strdup("302 Local Redirect from Privoxy");
- if (rsp->status == NULL)
- {
- return JB_ERR_MEMORY;
- }
+ rsp->status = strdup_or_die("302 Local Redirect from Privoxy");
if (enlist_unique_header(rsp->headers, "Location",
csp->action->string[ACTION_STRING_IMAGE_BLOCKER]))
{
@@ -697,8 +921,8 @@ static const char *get_content_type(const char *filename)
int i;
struct content_type
{
- const char *extension;
- const char *content_type;
+ const char extension[6];
+ const char content_type[11];
};
static const struct content_type content_types[] =
{
@@ -963,7 +1187,7 @@ jb_err cgi_show_status(struct client_state *csp,
}
#else /* ndef FEATURE_STATISTICS */
- err = err || map_block_killer(exports, "statistics");
+ if (!err) err = map_block_killer(exports, "statistics");
#endif /* ndef FEATURE_STATISTICS */
/*
@@ -985,7 +1209,6 @@ jb_err cgi_show_status(struct client_state *csp,
#ifdef FEATURE_CGI_EDIT_ACTIONS
if ((csp->config->feature_flags & RUNTIME_FEATURE_CGI_EDIT_ACTIONS)
- && (NULL == strstr(csp->actions_list[i]->filename, "standard.action"))
&& (NULL != csp->config->actions_file_short[i]))
{
#ifdef HAVE_ACCESS
@@ -1064,6 +1287,8 @@ jb_err cgi_show_status(struct client_state *csp,
}
#endif /* ndef CGI_EDIT_ACTIONS */
+ if (!err) err = map(exports, "force-prefix", 1, FORCE_PREFIX, 1);
+
if (err)
{
free_map(exports);
@@ -1117,12 +1342,7 @@ jb_err cgi_show_url_info(struct client_state *csp,
/*
* Get the url= parameter (if present) and remove any leading/trailing spaces.
*/
- url_param = strdup(lookup(parameters, "url"));
- if (url_param == NULL)
- {
- free_map(exports);
- return JB_ERR_MEMORY;
- }
+ url_param = strdup_or_die(lookup(parameters, "url"));
chomp(url_param);
/*
@@ -1165,7 +1385,7 @@ jb_err cgi_show_url_info(struct client_state *csp,
* No prefix or at least no prefix before
* the first slash - assume http://
*/
- char *url_param_prefixed = strdup("http://");
+ char *url_param_prefixed = strdup_or_die("http://");
if (JB_ERR_OK != string_join(&url_param_prefixed, url_param))
{
@@ -1185,6 +1405,7 @@ jb_err cgi_show_url_info(struct client_state *csp,
map_block_killer(exports, "privoxy-is-toggled-off")
)
{
+ freez(url_param);
free_map(exports);
return JB_ERR_MEMORY;
}
@@ -1277,7 +1498,7 @@ jb_err cgi_show_url_info(struct client_state *csp,
}
}
- matches = strdup("");
+ matches = strdup_or_die("");
for (i = 0; i < MAX_AF_FILES; i++)
{
@@ -1516,7 +1737,7 @@ jb_err cgi_robots_txt(struct client_state *csp,
(void)csp;
(void)parameters;
- rsp->body = strdup(
+ rsp->body = strdup_or_die(
"# This is the Privoxy control interface.\n"
"# It isn't very useful to index it, and you're likely to break stuff.\n"
"# So go away!\n"
@@ -1524,10 +1745,6 @@ jb_err cgi_robots_txt(struct client_state *csp,
"User-agent: *\n"
"Disallow: /\n"
"\n");
- if (rsp->body == NULL)
- {
- return JB_ERR_MEMORY;
- }
err = enlist_unique(rsp->headers, "Content-Type: text/plain", 13);
@@ -1564,6 +1781,14 @@ static jb_err show_defines(struct map *exports)
};
static const struct feature features[] = {
+ {
+ "FEATURE_64_BIT_TIME_T",
+#if (SIZEOF_TIME_T == 8)
+ 1,
+#else
+ 0,
+#endif
+ },
{
"FEATURE_ACCEPT_FILTER",
#ifdef FEATURE_ACCEPT_FILTER
@@ -1586,6 +1811,14 @@ static jb_err show_defines(struct map *exports)
1,
#else
0,
+#endif
+ },
+ {
+ "FEATURE_CLIENT_TAGS",
+#ifdef FEATURE_CLIENT_TAGS
+ 1,
+#else
+ 0,
#endif
},
{
@@ -1610,6 +1843,14 @@ static jb_err show_defines(struct map *exports)
1,
#else
0,
+#endif
+ },
+ {
+ "FEATURE_EXTERNAL_FILTERS",
+#ifdef FEATURE_EXTERNAL_FILTERS
+ 1,
+#else
+ 0,
#endif
},
{
@@ -1642,14 +1883,6 @@ static jb_err show_defines(struct map *exports)
1,
#else
0,
-#endif
- },
- {
- "FEATURE_IMAGE_DETECT_MSIE",
-#ifdef FEATURE_IMAGE_DETECT_MSIE
- 1,
-#else
- 0,
#endif
},
{
@@ -1753,7 +1986,7 @@ static jb_err show_defines(struct map *exports)
*********************************************************************/
static char *show_rcs(void)
{
- char *result = strdup("");
+ char *result = strdup_or_die("");
char buf[BUFFER_SIZE];
/* Instead of including *all* dot h's in the project (thus creating a
@@ -1783,9 +2016,6 @@ static char *show_rcs(void)
#endif /* def FEATURE_CGI_EDIT_ACTIONS */
SHOW_RCS(cgisimple_h_rcs)
SHOW_RCS(cgisimple_rcs)
-#ifdef __MINGW32__
- SHOW_RCS(cygwin_h_rcs)
-#endif
SHOW_RCS(deanimate_h_rcs)
SHOW_RCS(deanimate_rcs)
SHOW_RCS(encode_h_rcs)
@@ -1935,6 +2165,7 @@ static jb_err cgi_show_file(struct client_state *csp,
s = html_encode_and_free_original(s);
if (NULL == s)
{
+ free_map(exports);
return JB_ERR_MEMORY;
}
@@ -2006,19 +2237,18 @@ static jb_err load_file(const char *filename, char **buffer, size_t *length)
filename);
}
- *buffer = (char *)zalloc(*length + 1);
- if (NULL == *buffer)
- {
- err = JB_ERR_MEMORY;
- }
- else if (!fread(*buffer, *length, 1, fp))
+ *buffer = zalloc_or_die(*length + 1);
+
+ if (1 != fread(*buffer, *length, 1, fp))
{
/*
- * May happen if the file size changes between fseek() and
- * fread(). If it does, we just log it and serve what we got.
+ * May theoretically happen if the file size changes between
+ * fseek() and fread() because it's edited in-place. Privoxy
+ * and common text editors don't do that, thus we just fail.
*/
log_error(LOG_LEVEL_ERROR,
"Couldn't completely read file %s.", filename);
+ freez(*buffer);
err = JB_ERR_FILE;
}