-const char cgiedit_rcs[] = "$Id: cgiedit.c,v 1.50 2007/03/29 11:40:34 fabiankeil Exp $";
+const char cgiedit_rcs[] = "$Id: cgiedit.c,v 1.52 2007/04/12 10:41:23 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/cgiedit.c,v $
*
* Revisions :
* $Log: cgiedit.c,v $
+ * Revision 1.52 2007/04/12 10:41:23 fabiankeil
+ * - Don't mistake VC++'s _snprintf() for a snprintf() replacement.
+ * - Move some cgi_edit_actions_for_url() variables into structs.
+ * - Remove bogus comment.
+ *
+ * Revision 1.51 2007/04/08 13:21:05 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.50 2007/03/29 11:40:34 fabiankeil
* Divide @filter-params@ into @client-header-filter-params@
* @content-filter-params@ and @server-header-filter-params@.
#include <assert.h>
#include <sys/stat.h>
-#ifdef _WIN32
-#define snprintf _snprintf
-#endif /* def _WIN32 */
-
#include "project.h"
#include "cgi.h"
#include "cgiedit.h"
{
struct file_line * lines; /**< The contents of the file. A linked list of lines. */
const char * filename; /**< Full pathname - e.g. "/etc/privoxy/wibble.action". */
- int identifier; /**< The file name's position in csp->config->actions_file[]. */
+ unsigned identifier; /**< The file name's position in csp->config->actions_file[]. */
const char * version_str; /**< Last modification time, as a string. For CGI param. */
/**< Can be used in URL without using url_param(). */
unsigned version; /**< Last modification time - prevents chaos with
(Statically allocated) */
};
+/**
+ * Information about the filter types.
+ * Used for macro replacement in cgi_edit_actions_for_url.
+ */
+struct filter_type_info
+{
+ const int multi_action_index; /**< The multi action index as defined in project.h */
+ const char *macro_name; /**< Name of the macro that has to be replaced
+ with the prepared templates.
+ For example "content-filter-params" */
+ const char *type; /**< Name of the filter type,
+ for example "server-header-filter". */
+ const char *abbr_type; /**< Abbreviation of the filter type, usually the
+ first or second character capitalized */
+ const char *anchor; /**< Anchor for the User Manual link,
+ for example "SERVER-HEADER-FILTER" */
+};
+
+/* Accessed by index, keep the order in the way the FT_ macros are defined. */
+const static struct filter_type_info filter_type_info[] =
+{
+ {
+ ACTION_MULTI_FILTER,
+ "content-filter-params", "filter",
+ "F", "FILTER"
+ },
+ {
+ ACTION_MULTI_CLIENT_HEADER_FILTER,
+ "client-header-filter-params", "client-header-filter",
+ "C", "CLIENT-HEADER-FILTER"
+ },
+ {
+ ACTION_MULTI_SERVER_HEADER_FILTER,
+ "server-header-filter-params", "server-header-filter",
+ "S", "SERVER-HEADER-FILTER"
+ },
+ {
+ ACTION_MULTI_CLIENT_HEADER_TAGGER,
+ "client-header-tagger-params", "client-header-tagger",
+ "L", "CLIENT-HEADER-TAGGER"
+ },
+ {
+ ACTION_MULTI_SERVER_HEADER_TAGGER,
+ "server-header-tagger-params", "server-header-tagger",
+ "E", "SERVER-HEADER-TAGGER"
+ },
+};
+
/* FIXME: Following non-static functions should be prototyped in .h or made static */
/* Functions to read and write arbitrary config files */
* Returns : String with link target, or NULL if out of memory
*
*********************************************************************/
-static char *stringify(const int number)
+static char *stringify(const unsigned number)
{
char buf[6];
struct stat statbuf[1];
char version_buf[22];
int newline = NEWLINE_UNKNOWN;
- int i;
+ unsigned i;
assert(csp);
assert(parameters);
if ((JB_ERR_OK == get_number_param(csp, parameters, "f", &i))
&& (i < MAX_AF_FILES) && (NULL != csp->config->actions_file[i]))
{
- /*
- * i is guaranteed to be non-negative because
- * get_number_param returned JB_ERR_OK.
- *
- * XXX: This comment wouldn't be necessary if
- * get_number_param's fourth parameter would simply
- * be changed to unsigned. I don't see the point of
- * overloading its meaning to signal problems.
- */
filename = csp->config->actions_file[i];
}
/*
* List available filters and their settings.
*/
- char *content_filter_params;
- char *server_header_filter_params;
- char *client_header_filter_params;
char *filter_template;
int filter_identifier = 0;
+ char *prepared_templates[MAX_FILTER_TYPES];
+
+ for (i = 0; i < MAX_FILTER_TYPES; i++)
+ {
+ prepared_templates[i] = strdup("");
+ }
err = template_load(csp, &filter_template, "edit-actions-for-url-filter", 0);
if (err)
err = template_fill(&filter_template, exports);
- content_filter_params = strdup("");
- server_header_filter_params = strdup("");
- client_header_filter_params = strdup("");
-
for (i = 0; i < MAX_AF_FILES; i++)
{
if ((csp->rlist[i] != NULL) && (csp->rlist[i]->f != NULL))
{
char current_mode = 'x';
char number[20];
- int multi_action_index = 0;
struct list_entry *filter_name;
struct map *line_exports;
- char *this_line;
- char *filter_type;
- char *abbr_filter_type;
- char *anchor;
- char **current_params;
+ const int type = filter_group->type;
+ const int multi_action_index = filter_type_info[type].multi_action_index;
- switch (filter_group->type)
- {
- case FT_CONTENT_FILTER:
- /* XXX: Should we call it content-filter instead? */
- filter_type = "filter";
- abbr_filter_type = "F";
- multi_action_index = ACTION_MULTI_FILTER;
- anchor = "FILTER";
- current_params = &content_filter_params;
- break;
- case FT_SERVER_HEADER_FILTER:
- filter_type = "server-header-filter";
- abbr_filter_type = "S";
- multi_action_index = ACTION_MULTI_SERVER_HEADER_FILTER;
- current_params = &server_header_filter_params;
- anchor = "SERVER-HEADER-FILTER"; /* XXX: no documentation available yet */
- break;
- case FT_CLIENT_HEADER_FILTER:
- filter_type = "client-header-filter";
- abbr_filter_type = "C";
- multi_action_index = ACTION_MULTI_CLIENT_HEADER_FILTER;
- current_params = &client_header_filter_params;
- anchor = "CLIENT-HEADER-FILTER"; /* XXX: no documentation available yet */
- break;
- default:
- log_error(LOG_LEVEL_FATAL,
- "cgi_edit_actions_for_url: Unknown filter type: %u for filter %s.",
- filter_group->type, filter_group->name);
- /* Not reached. */
- }
- assert(multi_action_index);
+ assert(type < MAX_FILTER_TYPES);
filter_name = cur_line->data.action->multi_add[multi_action_index]->first;
while ((filter_name != NULL)
if (line_exports == NULL)
{
err = JB_ERR_MEMORY;
- freez(*current_params); /* XXX: really necessary? */
}
else
{
+ char *filter_line;
+
if (!err) err = map(line_exports, "index", 1, number, 1);
if (!err) err = map(line_exports, "name", 1, filter_group->name, 1);
if (!err) err = map(line_exports, "description", 1, filter_group->description, 1);
if (!err) err = map_radio(line_exports, "this-filter", "ynx", current_mode);
- if (!err) err = map(line_exports, "filter-type", 1, filter_type, 1);
- if (!err) err = map(line_exports, "abbr-filter-type", 1, abbr_filter_type, 1);
- if (!err) err = map(line_exports, "anchor", 1, anchor, 1);
+ if (!err) err = map(line_exports, "filter-type", 1, filter_type_info[type].type, 1);
+ if (!err) err = map(line_exports, "abbr-filter-type", 1, filter_type_info[type].abbr_type, 1);
+ if (!err) err = map(line_exports, "anchor", 1, filter_type_info[type].anchor, 1);
- this_line = NULL;
if (!err)
{
- this_line = strdup(filter_template);
- if (this_line == NULL) err = JB_ERR_MEMORY;
+ filter_line = strdup(filter_template);
+ if (filter_line == NULL) err = JB_ERR_MEMORY;
}
- if (!err) err = template_fill(&this_line, line_exports);
- string_join(current_params, this_line);
+ if (!err) err = template_fill(&filter_line, line_exports);
+ string_join(&prepared_templates[type], filter_line);
free_map(line_exports);
}
}
freez(filter_template);
- if (!err) err = map(exports, "content-filter-params", 1, content_filter_params, 0);
- if (!err) err = map(exports, "server-header-filter-params", 1, server_header_filter_params, 0);
- if (!err) err = map(exports, "client-header-filter-params", 1, client_header_filter_params, 0);
+ /* Replace all filter macros with the aggregated templates */
+ for (i = 0; i < MAX_FILTER_TYPES; i++)
+ {
+ if (err) break;
+ err = map(exports, filter_type_info[i].macro_name, 1, prepared_templates[i], 0);
+ }
+
if (err)
{
- freez(content_filter_params);
- freez(server_header_filter_params);
- freez(client_header_filter_params);
+ /* Free aggregated templates */
+ for (i = 0; i < MAX_FILTER_TYPES; i++)
+ {
+ freez(prepared_templates[i]);
+ }
}
}
case 'C':
multi_action_index = ACTION_MULTI_CLIENT_HEADER_FILTER;
break;
+ case 'L':
+ multi_action_index = ACTION_MULTI_CLIENT_HEADER_TAGGER;
+ break;
+ case 'E':
+ multi_action_index = ACTION_MULTI_SERVER_HEADER_TAGGER;
+ break;
default:
log_error(LOG_LEVEL_ERROR,
"Unknown filter type: %c for filter %s. Filter ignored.", type, name);