X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=cgiedit.c;h=4caec74b3a6cb8c52b795a9308dad805787432de;hp=fb268c2c30dee229383a8363bde6e328d9b11e48;hb=f9888d9c1d0b5b4e082718508532ddaf2ba8759c;hpb=41eacd73b8d878f542afd6cdaab7abfeda89b017 diff --git a/cgiedit.c b/cgiedit.c index fb268c2c..4caec74b 100644 --- a/cgiedit.c +++ b/cgiedit.c @@ -1,4 +1,4 @@ -const char cgiedit_rcs[] = "$Id: cgiedit.c,v 1.49 2007/03/20 15:16:34 fabiankeil Exp $"; +const char cgiedit_rcs[] = "$Id: cgiedit.c,v 1.51 2007/04/08 13:21:05 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/cgiedit.c,v $ @@ -42,6 +42,15 @@ const char cgiedit_rcs[] = "$Id: cgiedit.c,v 1.49 2007/03/20 15:16:34 fabiankeil * * Revisions : * $Log: cgiedit.c,v $ + * 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@. + * * Revision 1.49 2007/03/20 15:16:34 fabiankeil * Use dedicated header filter actions instead of abusing "filter". * Replace "filter-client-headers" and "filter-client-headers" @@ -343,10 +352,6 @@ const char cgiedit_rcs[] = "$Id: cgiedit.c,v 1.49 2007/03/20 15:16:34 fabiankeil #include #include -#ifdef _WIN32 -#define snprintf _snprintf -#endif /* def _WIN32 */ - #include "project.h" #include "cgi.h" #include "cgiedit.h" @@ -470,8 +475,7 @@ struct editable_file { 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". */ - const char * identifier; /**< Filename stub - e.g. "wibble". Use for CGI param. */ - /**< Pre-encoded with url_encode() for ease of use. */ + 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 @@ -488,13 +492,30 @@ struct editable_file (Statically allocated) */ }; +/** + * Used by cgi_edit_actions_for_url() to replace filter related macros. + */ +struct cgi_filter_info +{ + const int multi_action_index; /**< The multi action index as defined in project.h */ + char *prepared_templates; /**< Temporary space for the filled-in templates for + this filter. Once all templated are aggregated + they replace the @$filtername-params@ macro. */ + 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 character capitalized */ + const char *anchor; /**< Anchor for the User Manual link, + for example "SERVER-HEADER-FILTER" */ +}; + + /* FIXME: Following non-static functions should be prototyped in .h or made static */ /* Functions to read and write arbitrary config files */ jb_err edit_read_file(struct client_state *csp, const struct map *parameters, int require_version, - const char *suffix, struct editable_file **pfile); jb_err edit_write_file(struct editable_file * file); void edit_free_file(struct editable_file * file); @@ -530,13 +551,6 @@ static int match_actions_file_header_line(const char * line, const char * name); static jb_err split_line_on_equals(const char * line, char ** pname, char ** pvalue); /* Internal parameter parsing functions */ -static jb_err get_file_name_param(struct client_state *csp, - const struct map *parameters, - const char *param_name, - const char *suffix, - char **pfilename, - const char **pparam); - static jb_err get_url_spec_param(struct client_state *csp, const struct map *parameters, const char *name, @@ -574,6 +588,10 @@ static char *section_target(const unsigned sectionid); * allocated string of the form #l, for use in link * targets. * + * XXX: The hash should be moved into the templates + * to make this function more generic and render + * stringify() obsolete. + * * Parameters : * 1 : sectionid = start line number of section * @@ -591,6 +609,27 @@ static char *section_target(const unsigned sectionid) } +/********************************************************************* + * + * Function : stringify + * + * Description : Convert a number into a dynamically allocated string. + * + * Parameters : + * 1 : number = The number to convert. + * + * Returns : String with link target, or NULL if out of memory + * + *********************************************************************/ +static char *stringify(const unsigned number) +{ + char buf[6]; + + snprintf(buf, sizeof(buf), "%i", number); + return strdup(buf); +} + + /********************************************************************* * * Function : map_copy_parameter_html @@ -688,6 +727,7 @@ static jb_err map_copy_parameter_url(struct map *out, } #endif /* 0 - unused function */ + /********************************************************************* * * Function : cgi_edit_actions_url_form @@ -701,7 +741,7 @@ static jb_err map_copy_parameter_url(struct map *out, * 3 : parameters = map of cgi parameters * * CGI Parameters - * f : (filename) Identifies the file to edit + * i : (action index) Identifies the file to edit * v : (version) File's last-modified time * p : (pattern) Line number of pattern to edit * @@ -772,7 +812,7 @@ jb_err cgi_edit_actions_url_form(struct client_state *csp, return JB_ERR_MEMORY; } - err = map(exports, "f", 1, file->identifier, 1); + err = map(exports, "f", 1, stringify(file->identifier), 0); if (!err) err = map(exports, "v", 1, file->version_str, 1); if (!err) err = map(exports, "p", 1, url_encode(lookup(parameters, "p")), 0); if (!err) err = map(exports, "u", 1, html_encode(cur_line->unprocessed), 0); @@ -861,7 +901,7 @@ jb_err cgi_edit_actions_add_url_form(struct client_state *csp, * 3 : parameters = map of cgi parameters * * CGI Parameters : - * f : (filename) Identifies the file to edit + * f : (number) The action file identifier. * v : (version) File's last-modified time * p : (pattern) Line number of pattern to edit * @@ -932,11 +972,12 @@ jb_err cgi_edit_actions_remove_url_form(struct client_state *csp, return JB_ERR_MEMORY; } - err = map(exports, "f", 1, file->identifier, 1); + err = map(exports, "f", 1, stringify(file->identifier), 0); if (!err) err = map(exports, "v", 1, file->version_str, 1); if (!err) err = map(exports, "p", 1, url_encode(lookup(parameters, "p")), 0); if (!err) err = map(exports, "u", 1, html_encode(cur_line->unprocessed), 0); if (!err) err = map(exports, "jumptarget", 1, section_target(section_start_line_number), 0); + if (!err) err = map(exports, "actions-file", 1, html_encode(file->filename), 0); edit_free_file(file); @@ -1145,8 +1186,6 @@ void edit_free_file(struct editable_file * file) } edit_free_file_lines(file->lines); - freez(file->filename); - freez(file->identifier); freez(file->version_str); file->version = 0; file->parse_error_text = NULL; /* Statically allocated */ @@ -1741,13 +1780,11 @@ jb_err edit_read_file_lines(FILE *fp, struct file_line ** pfile, int *newline) * 1 : csp = Current client state (buffers, headers, etc...) * 2 : parameters = map of cgi parameters. * 3 : require_version = true to check "ver" parameter. - * 4 : suffix = File extension, e.g. ".action". - * 5 : pfile = Destination for the file. Will be set + * 4 : pfile = Destination for the file. Will be set * to NULL on error. * * CGI Parameters : - * filename : The name of the file to read, without the - * path or ".action" extension. + * f : The action file identifier. * ver : (Only if require_version is nonzero) * Timestamp of the actions file. If wrong, this * function fails with JB_ERR_MODIFIED. @@ -1766,19 +1803,18 @@ jb_err edit_read_file_lines(FILE *fp, struct file_line ** pfile, int *newline) jb_err edit_read_file(struct client_state *csp, const struct map *parameters, int require_version, - const char *suffix, struct editable_file **pfile) { struct file_line * lines; FILE * fp; jb_err err; - char * filename; - const char * identifier; + const char * filename = NULL; struct editable_file * file; unsigned version = 0; struct stat statbuf[1]; char version_buf[22]; int newline = NEWLINE_UNKNOWN; + unsigned i; assert(csp); assert(parameters); @@ -1786,17 +1822,15 @@ jb_err edit_read_file(struct client_state *csp, *pfile = NULL; - err = get_file_name_param(csp, parameters, "f", suffix, - &filename, &identifier); - if (err) + if ((JB_ERR_OK == get_number_param(csp, parameters, "f", &i)) + && (i < MAX_AF_FILES) && (NULL != csp->config->actions_file[i])) { - return err; + filename = csp->config->actions_file[i]; } - if (stat(filename, statbuf) < 0) + if (filename == NULL || stat(filename, statbuf) < 0) { /* Error, probably file not found. */ - free(filename); return JB_ERR_FILE; } version = (unsigned) statbuf->st_mtime; @@ -1807,7 +1841,6 @@ jb_err edit_read_file(struct client_state *csp, err = get_number_param(csp, parameters, "v", &specified_version); if (err) { - free(filename); return err; } @@ -1819,7 +1852,6 @@ jb_err edit_read_file(struct client_state *csp, if (NULL == (fp = fopen(filename,"rb"))) { - free(filename); return JB_ERR_FILE; } @@ -1829,14 +1861,12 @@ jb_err edit_read_file(struct client_state *csp, if (err) { - free(filename); return err; } file = (struct editable_file *) zalloc(sizeof(*file)); if (err) { - free(filename); edit_free_file_lines(lines); return err; } @@ -1845,13 +1875,7 @@ jb_err edit_read_file(struct client_state *csp, file->newline = newline; file->filename = filename; file->version = version; - file->identifier = url_encode(identifier); - - if (file->identifier == NULL) - { - edit_free_file(file); - return JB_ERR_MEMORY; - } + file->identifier = i; /* Correct file->version_str */ freez(file->version_str); @@ -1891,8 +1915,7 @@ jb_err edit_read_file(struct client_state *csp, * to NULL on error. * * CGI Parameters : - * filename : The name of the actions file to read, without the - * path or ".action" extension. + * f : The actions file identifier. * ver : (Only if require_version is nonzero) * Timestamp of the actions file. If wrong, this * function fails with JB_ERR_MODIFIED. @@ -1922,7 +1945,7 @@ jb_err edit_read_actions_file(struct client_state *csp, *pfile = NULL; - err = edit_read_file(csp, parameters, require_version, ".action", &file); + err = edit_read_file(csp, parameters, require_version, &file); if (err) { /* Try to handle if possible */ @@ -1969,6 +1992,10 @@ jb_err edit_read_actions_file(struct client_state *csp, } +#if 0 +/* + * Currently not needed, but may become useful again in the future. + */ /********************************************************************* * * Function : get_file_name_param @@ -2083,6 +2110,7 @@ static jb_err get_file_name_param(struct client_state *csp, return JB_ERR_OK; } +#endif /*0*/ /********************************************************************* @@ -2361,7 +2389,7 @@ jb_err cgi_error_parse(struct client_state *csp, return JB_ERR_MEMORY; } - err = map(exports, "f", 1, file->identifier, 1); + err = map(exports, "f", 1, stringify(file->identifier), 0); if (!err) err = map(exports, "parse-error", 1, html_encode(file->parse_error_text), 0); cur_line = file->parse_error; @@ -2427,7 +2455,7 @@ jb_err cgi_error_file(struct client_state *csp, /********************************************************************* * - * Function : cgi_error_file + * Function : cgi_error_file_read_only * * Description : CGI function that is called when a file cannot be * opened for writing by the CGI editor. @@ -2695,13 +2723,14 @@ jb_err cgi_edit_actions_list(struct client_state *csp, /* Set up global exports */ - if (!err) err = map(exports, "f", 1, file->identifier, 1); + if (!err) err = map(exports, "actions-file", 1, html_encode(file->filename), 0); + if (!err) err = map(exports, "f", 1, stringify(file->identifier), 0); if (!err) err = map(exports, "v", 1, file->version_str, 1); /* Discourage private additions to default.action */ if (!err) err = map_conditional(exports, "default-action", - (strcmp("default", lookup(parameters, "f")) == 0)); + (strstr("default.action", file->filename) != NULL)); if (err) { edit_free_file(file); @@ -3062,7 +3091,7 @@ jb_err cgi_edit_actions_for_url(struct client_state *csp, return JB_ERR_MEMORY; } - err = map(exports, "f", 1, file->identifier, 1); + err = map(exports, "f", 1, stringify(file->identifier), 0); if (!err) err = map(exports, "v", 1, file->version_str, 1); if (!err) err = map(exports, "s", 1, url_encode(lookup(parameters, "s")), 0); @@ -3123,11 +3152,25 @@ jb_err cgi_edit_actions_for_url(struct client_state *csp, /* * 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; + /* XXX: Should we put these into an array? */ + static struct cgi_filter_info content_filter = { + ACTION_MULTI_FILTER, NULL, + "filter", "F", "FILTER" + }; + static struct cgi_filter_info server_header_filter = { + ACTION_MULTI_SERVER_HEADER_FILTER, NULL, + "server-header-filter", "S", "SERVER-HEADER-FILTER" + }; + static struct cgi_filter_info client_header_filter = { + ACTION_MULTI_CLIENT_HEADER_FILTER, NULL, + "client-header-filter", "C", "CLIENT-HEADER-FILTER" + }; + + content_filter.prepared_templates = strdup(""); + server_header_filter.prepared_templates = strdup(""); + client_header_filter.prepared_templates = strdup(""); err = template_load(csp, &filter_template, "edit-actions-for-url-filter", 0); if (err) @@ -3143,10 +3186,6 @@ jb_err cgi_edit_actions_for_url(struct client_state *csp, 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)) @@ -3154,40 +3193,23 @@ jb_err cgi_edit_actions_for_url(struct client_state *csp, filter_group = csp->rlist[i]->f; for (;(!err) && (filter_group != NULL); filter_group = filter_group->next) { + int multi_action_index; 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; + struct cgi_filter_info *current_filter = NULL; 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; + current_filter = &content_filter; 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 */ + current_filter = &server_header_filter; 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 */ + current_filter = &client_header_filter; break; default: log_error(LOG_LEVEL_FATAL, @@ -3195,7 +3217,8 @@ jb_err cgi_edit_actions_for_url(struct client_state *csp, filter_group->type, filter_group->name); /* Not reached. */ } - assert(multi_action_index); + assert(current_filter != NULL); + multi_action_index = current_filter->multi_action_index; filter_name = cur_line->data.action->multi_add[multi_action_index]->first; while ((filter_name != NULL) @@ -3230,26 +3253,27 @@ jb_err cgi_edit_actions_for_url(struct client_state *csp, if (line_exports == NULL) { err = JB_ERR_MEMORY; - freez(*current_params); /* XXX: really necessary? */ + freez(current_filter->prepared_templates); /* 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, current_filter->type, 1); + if (!err) err = map(line_exports, "abbr-filter-type", 1, current_filter->abbr_type, 1); + if (!err) err = map(line_exports, "anchor", 1, current_filter->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(¤t_filter->prepared_templates, filter_line); free_map(line_exports); } @@ -3258,14 +3282,14 @@ jb_err cgi_edit_actions_for_url(struct client_state *csp, } 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); + if (!err) err = map(exports, "content-filter-params", 1, content_filter.prepared_templates, 0); + if (!err) err = map(exports, "server-header-filter-params", 1, server_header_filter.prepared_templates, 0); + if (!err) err = map(exports, "client-header-filter-params", 1, client_header_filter.prepared_templates, 0); if (err) { - freez(content_filter_params); - freez(server_header_filter_params); - freez(client_header_filter_params); + freez(content_filter.prepared_templates); + freez(server_header_filter.prepared_templates); + freez(client_header_filter.prepared_templates); } } @@ -3526,13 +3550,13 @@ jb_err cgi_edit_actions_submit(struct client_state *csp, if (err == JB_ERR_FILE) { /* Read-only file. */ - err = cgi_error_file_read_only(csp, rsp, file->identifier); + err = cgi_error_file_read_only(csp, rsp, file->filename); } edit_free_file(file); return err; } - snprintf(target, 1024, CGI_PREFIX "edit-actions-list?foo=%lu&f=%s#l%d", + snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%i#l%d", (long) time(NULL), file->identifier, sectionid); edit_free_file(file); @@ -3647,13 +3671,13 @@ jb_err cgi_edit_actions_url(struct client_state *csp, if (err == JB_ERR_FILE) { /* Read-only file. */ - err = cgi_error_file_read_only(csp, rsp, file->identifier); + err = cgi_error_file_read_only(csp, rsp, file->filename); } edit_free_file(file); return err; } - snprintf(target, 1024, CGI_PREFIX "edit-actions-list?foo=%lu&f=%s#l%d", + snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%i#l%d", (long) time(NULL), file->identifier, section_start_line_number); edit_free_file(file); @@ -3776,13 +3800,13 @@ jb_err cgi_edit_actions_add_url(struct client_state *csp, if (err == JB_ERR_FILE) { /* Read-only file. */ - err = cgi_error_file_read_only(csp, rsp, file->identifier); + err = cgi_error_file_read_only(csp, rsp, file->filename); } edit_free_file(file); return err; } - snprintf(target, 1024, CGI_PREFIX "edit-actions-list?foo=%lu&f=%s#l%d", + snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%i#l%d", (long) time(NULL), file->identifier, sectionid); edit_free_file(file); @@ -3887,13 +3911,13 @@ jb_err cgi_edit_actions_remove_url(struct client_state *csp, if (err == JB_ERR_FILE) { /* Read-only file. */ - err = cgi_error_file_read_only(csp, rsp, file->identifier); + err = cgi_error_file_read_only(csp, rsp, file->filename); } edit_free_file(file); return err; } - snprintf(target, 1024, CGI_PREFIX "edit-actions-list?foo=%lu&f=%s#l%d", + snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%i#l%d", (long) time(NULL), file->identifier, section_start_line_number); edit_free_file(file); @@ -4009,13 +4033,13 @@ jb_err cgi_edit_actions_section_remove(struct client_state *csp, if (err == JB_ERR_FILE) { /* Read-only file. */ - err = cgi_error_file_read_only(csp, rsp, file->identifier); + err = cgi_error_file_read_only(csp, rsp, file->filename); } edit_free_file(file); return err; } - snprintf(target, 1024, CGI_PREFIX "edit-actions-list?foo=%lu&f=%s", + snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%i", (long) time(NULL), file->identifier); edit_free_file(file); @@ -4178,13 +4202,13 @@ jb_err cgi_edit_actions_section_add(struct client_state *csp, if (err == JB_ERR_FILE) { /* Read-only file. */ - err = cgi_error_file_read_only(csp, rsp, file->identifier); + err = cgi_error_file_read_only(csp, rsp, file->filename); } edit_free_file(file); return err; } - snprintf(target, 1024, CGI_PREFIX "edit-actions-list?foo=%lu&f=%s", + snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%i", (long) time(NULL), file->identifier); edit_free_file(file); @@ -4366,14 +4390,14 @@ jb_err cgi_edit_actions_section_swap(struct client_state *csp, if (err == JB_ERR_FILE) { /* Read-only file. */ - err = cgi_error_file_read_only(csp, rsp, file->identifier); + err = cgi_error_file_read_only(csp, rsp, file->filename); } edit_free_file(file); return err; } } /* END if (section1 != section2) */ - snprintf(target, 1024, CGI_PREFIX "edit-actions-list?foo=%lu&f=%s", + snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%i", (long) time(NULL), file->identifier); edit_free_file(file);