-const char cgiedit_rcs[] = "$Id: cgiedit.c,v 1.54 2007/05/14 10:33:51 fabiankeil Exp $";
+const char cgiedit_rcs[] = "$Id: cgiedit.c,v 1.81 2014/06/02 06:22:20 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/cgiedit.c,v $
*
* Purpose : CGI-based actionsfile editor.
*
- * Functions declared include: cgi_edit_*
- *
* NOTE: The CGIs in this file use parameter names
* such as "f" and "s" which are really *BAD* choices.
* However, I'm trying to save bytes in the
*
* Stick to the short names in this file for consistency.
*
- * Copyright : Written by and Copyright (C) 2001-2007 the SourceForge
+ * Copyright : Written by and Copyright (C) 2001-2014 the
* Privoxy team. http://www.privoxy.org/
*
* Based on the Internet Junkbuster originally written
* or write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
- * Revisions :
- * $Log: cgiedit.c,v $
- * Revision 1.54 2007/05/14 10:33:51 fabiankeil
- * - Use strlcpy() and strlcat() instead of strcpy() and strcat().
- *
- * Revision 1.53 2007/04/15 16:39:20 fabiankeil
- * Introduce tags as alternative way to specify which
- * actions apply to a request. At the moment tags can be
- * created based on client and server headers.
- *
- * 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@.
- *
- * 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"
- * with "server-header-filter" and "client-header-filter".
- *
- * Revision 1.48 2007/02/13 14:35:25 fabiankeil
- * Replace hash escaping code to prevent
- * crashes, memory and file corruption.
- *
- * Revision 1.47 2006/12/28 18:04:25 fabiankeil
- * Fixed gcc43 conversion warnings.
- *
- * Revision 1.46 2006/12/27 18:44:52 fabiankeil
- * Stop shadowing string.h's index().
- *
- * Revision 1.45 2006/12/21 12:57:48 fabiankeil
- * Add config option "split-large-forms"
- * to work around the browser bug reported
- * in BR #1570678.
- *
- * Revision 1.44 2006/12/09 13:49:16 fabiankeil
- * Fix configure option --disable-toggle.
- * Thanks to Peter Thoenen for reporting this.
- *
- * Revision 1.43 2006/07/18 14:48:45 david__schmidt
- * Reorganizing the repository: swapping out what was HEAD (the old 3.1 branch)
- * with what was really the latest development (the v_3_0_branch branch)
- *
- * Revision 1.41.2.12 2006/01/30 15:16:25 david__schmidt
- * Remove a little residual debugging info
- *
- * Revision 1.41.2.11 2006/01/29 23:10:56 david__schmidt
- * Multiple filter file support
- *
- * Revision 1.41.2.10 2005/07/04 03:13:43 david__schmidt
- * Undo some damaging memory leak patches
- *
- * Revision 1.41.2.9 2005/07/04 00:31:04 david__schmidt
- * Removing a double free
- *
- * Revision 1.41.2.8 2005/05/07 21:50:54 david__schmidt
- * A few memory leaks plugged (mostly on error paths)
- *
- * Revision 1.41.2.7 2004/02/17 13:30:23 oes
- * Moved cgi_error_disabled() from cgiedit.c to
- * cgi.c to re-enable build with --disable-editor.
- * Fixes Bug #892744. Thanks to Matthew Fischer
- * for spotting.
- *
- * Revision 1.41.2.6 2003/12/18 08:13:48 oes
- * One line lost in last commit
- *
- * Revision 1.41.2.5 2003/12/17 16:33:47 oes
- * - All edit functions that redirect back to the list page
- * now use cgi_redirect
- * - All redirects now contain useless parameter "foo", whose
- * value are raw seconds since epoch, in order to force
- * Opera and Konqueror to properly reload the list. Closes
- * bug #859993
- *
- * Revision 1.41.2.4 2003/03/11 11:53:59 oes
- * Cosmetic: Renamed cryptic variable
- *
- * Revision 1.41.2.3 2002/11/12 15:01:41 oes
- * Fix: Don't free uninitialized struct editable_file
- *
- * Revision 1.41.2.2 2002/08/05 20:02:59 oes
- * Bugfix: "Insert new section at top" did not work properly if first non-comment line in file was of type FILE_LINE_ACTION
- *
- * Revision 1.41.2.1 2002/08/02 12:43:14 oes
- * Fixed bug #588514: first_time now set on a per-string basis in actions_from_radio; javascriptify now called on copies
- *
- * Revision 1.41 2002/05/21 19:09:45 oes
- * - Made Add/Edit/Remove URL Submit and Cancel
- * buttons jump back to relevant section in eal
- * - Bugfix: remove-url-form needs p export
- *
- * Revision 1.40 2002/05/19 11:34:35 jongfoster
- * Handling read-only actions files better - report the actual
- * error, not "Out of memory"!
- *
- * Bug report:
- * http://sourceforge.net/tracker/index.php?func=detail
- * &aid=557905&group_id=11118&atid=111118
- *
- * Revision 1.39 2002/05/12 21:39:15 jongfoster
- * - Adding Doxygen-style comments to structures and #defines.
- * - Correcting function comments
- *
- * Revision 1.38 2002/05/03 23:00:38 jongfoster
- * Support for templates for "standard actions" buttons.
- * See bug #549871
- *
- * Revision 1.37 2002/04/30 11:14:52 oes
- * Made csp the first parameter in *action_to_html
- *
- * Revision 1.36 2002/04/26 21:53:30 jongfoster
- * Fixing a memory leak. (Near, but not caused by, my earlier commit).
- *
- * Revision 1.35 2002/04/26 21:50:02 jongfoster
- * Honouring default exports in edit-actions-for-url-filter template.
- *
- * Revision 1.34 2002/04/26 12:54:17 oes
- * Adaptions to changes in actions.c
- *
- * Revision 1.33 2002/04/24 02:17:47 oes
- * - Moved get_char_param, get_string_param and get_number_param to cgi.c
- * - Comments
- * - Activated Jon's code for editing multiple AFs
- * - cgi_edit_list_actions now provides context-sensitive
- * help, looks up all action sets from standard.action and
- * makes buttons for them in the catchall section
- * - cgi_edit_action_submit now honors a p parameter, looks up
- * the corresponding action set, and sets the catchall pattern's
- * actions accordingly.
- *
- * Revision 1.32 2002/04/19 16:55:31 jongfoster
- * Fixing newline problems. If we do our own text file newline
- * mangling, we don't want the library to do any, so we need to
- * open the files in *binary* mode.
- *
- * Revision 1.31 2002/04/18 19:21:08 jongfoster
- * Added code to detect "conventional" action files, that start
- * with a set of actions for all URLs (the pattern "/").
- * These are special-cased in the "edit-actions-list" CGI, so
- * that a special UI can be written for them.
- *
- * Revision 1.30 2002/04/10 13:38:35 oes
- * load_template signature changed
- *
- * Revision 1.29 2002/04/08 16:59:08 oes
- * Fixed comment
- *
- * Revision 1.28 2002/03/27 12:30:29 oes
- * Deleted unsused variable
- *
- * Revision 1.27 2002/03/26 23:06:04 jongfoster
- * Removing duplicate @ifs on the toggle page
- *
- * Revision 1.26 2002/03/26 22:59:17 jongfoster
- * Fixing /toggle to display status consistently.
- *
- * Revision 1.25 2002/03/26 22:29:54 swa
- * we have a new homepage!
- *
- * Revision 1.24 2002/03/24 15:23:33 jongfoster
- * Name changes
- *
- * Revision 1.23 2002/03/24 13:32:41 swa
- * name change related issues
- *
- * Revision 1.22 2002/03/24 13:25:43 swa
- * name change related issues
- *
- * Revision 1.21 2002/03/22 18:02:48 jongfoster
- * Fixing remote toggle
- *
- * Revision 1.20 2002/03/16 20:28:34 oes
- * Added descriptions to the filters so users will know what they select in the cgi editor
- *
- * Revision 1.19 2002/03/16 18:38:14 jongfoster
- * Stopping stupid or malicious users from breaking the actions
- * file using the web-based editor.
- *
- * Revision 1.18 2002/03/16 14:57:44 jongfoster
- * Full support for enabling/disabling modular filters.
- *
- * Revision 1.17 2002/03/16 14:26:42 jongfoster
- * First version of modular filters support - READ ONLY!
- * Fixing a double-free bug in the out-of-memory handling in map_radio().
- *
- * Revision 1.16 2002/03/07 03:46:17 oes
- * Fixed compiler warnings
- *
- * Revision 1.15 2002/03/06 22:54:35 jongfoster
- * Automated function-comment nitpicking.
- *
- * Revision 1.14 2002/03/05 00:24:51 jongfoster
- * Patch to always edit the current actions file.
- *
- * Revision 1.13 2002/03/04 02:07:59 david__schmidt
- * Enable web editing of actions file on OS/2 (it had been broken all this time!)
- *
- * Revision 1.12 2002/03/03 09:18:03 joergs
- * Made jumbjuster work on AmigaOS again.
- *
- * Revision 1.11 2002/01/23 01:03:31 jongfoster
- * Fixing gcc [CygWin] compiler warnings
- *
- * Revision 1.10 2002/01/23 00:22:59 jongfoster
- * Adding new function cgi_edit_actions_section_swap(), to reorder
- * the actions file.
- *
- * Adding get_url_spec_param() to get a validated URL pattern.
- *
- * Moving edit_read_line() out of this file and into loaders.c.
- *
- * Adding missing html_encode() to many CGI functions.
- *
- * Moving the functions that #include actionlist.h to the end of the file,
- * because the Visual C++ 97 debugger gets extremely confused if you try
- * to debug any code that comes after them in the file.
- *
- * Major optimizations in cgi_edit_actions_list() to reduce the size of
- * the generated HTML (down 40% from 550k to 304k), with major side-effects
- * throughout the editor and templates. In particular, the length of the
- * URLs throughout the editor has been drastically reduced, by cutting
- * paramater names down to 1 character and CGI names down to 3-4
- * characters, by removing all non-essential CGI paramaters even at the
- * expense of having to re-read the actions file for the most trivial
- * page, and by using relative rather than absolute URLs. This means
- * that this (typical example):
- *
- * <a href="http://ijbswa.sourceforge.net/config/edit-actions-url-form?
- * filename=ijb&ver=1011487572&section=12&pattern=13
- * &oldval=www.oesterhelt.org%2Fdeanimate-demo">
- *
- * is now this:
- *
- * <a href="eau?f=ijb&v=1011487572&p=13">
- *
- * Revision 1.9 2002/01/17 20:56:22 jongfoster
- * Replacing hard references to the URL of the config interface
- * with #defines from project.h
- *
- * Revision 1.8 2001/11/30 23:35:51 jongfoster
- * Renaming actionsfile to ijb.action
- *
- * Revision 1.7 2001/11/13 00:28:24 jongfoster
- * - Renaming parameters from edit-actions-for-url so that they only
- * contain legal JavaScript characters. If we wanted to write
- * JavaScript that worked with Netscape 4, this is nessacery.
- * (Note that at the moment the JavaScript doesn't actually work
- * with Netscape 4, but now this is purely a template issue, not
- * one affecting code).
- * - Adding new CGIs for use by non-JavaScript browsers:
- * edit-actions-url-form
- * edit-actions-add-url-form
- * edit-actions-remove-url-form
- * - Fixing || bug.
- *
- * Revision 1.6 2001/10/29 03:48:09 david__schmidt
- * OS/2 native needed a snprintf() routine. Added one to miscutil, brackedted
- * by and __OS2__ ifdef.
- *
- * Revision 1.5 2001/10/25 03:40:48 david__schmidt
- * Change in porting tactics: OS/2's EMX porting layer doesn't allow multiple
- * threads to call select() simultaneously. So, it's time to do a real, live,
- * native OS/2 port. See defines for __EMX__ (the porting layer) vs. __OS2__
- * (native). Both versions will work, but using __OS2__ offers multi-threading.
- *
- * Revision 1.4 2001/10/23 21:48:19 jongfoster
- * Cleaning up error handling in CGI functions - they now send back
- * a HTML error page and should never cause a FATAL error. (Fixes one
- * potential source of "denial of service" attacks).
- *
- * CGI actions file editor that works and is actually useful.
- *
- * Ability to toggle JunkBuster remotely using a CGI call.
- *
- * You can turn off both the above features in the main configuration
- * file, e.g. if you are running a multi-user proxy.
- *
- * Revision 1.3 2001/10/14 22:12:49 jongfoster
- * New version of CGI-based actionsfile editor.
- * Major changes, including:
- * - Completely new file parser and file output routines
- * - edit-actions CGI renamed edit-actions-for-url
- * - All CGIs now need a filename parameter, except for...
- * - New CGI edit-actions which doesn't need a filename,
- * to allow you to start the editor up.
- * - edit-actions-submit now works, and now automatically
- * redirects you back to the main edit-actions-list handler.
- *
- * Revision 1.2 2001/09/16 17:05:14 jongfoster
- * Removing unused #include showarg.h
- *
- * Revision 1.1 2001/09/16 15:47:37 jongfoster
- * First version of CGI-based edit interface. This is very much a
- * work-in-progress, and you can't actually use it to edit anything
- * yet. You must #define FEATURE_CGI_EDIT_ACTIONS for these changes
- * to have any effect.
- *
- *
**********************************************************************/
-\f
+
#include "config.h"
{
/** Next entry in the linked list */
struct file_line * next;
-
+
/** The raw data, to write out if this line is unmodified. */
char * raw;
-
+
/** Comments and/or whitespace to put before this line if it's modified
and then written out. */
char * prefix;
are performed on the data read from file before it's stored here, so
it will be a single line of data. */
char * unprocessed;
-
+
/** The type of data on this line. One of the FILE_LINE_xxx constants. */
int type;
} setting;
- /* Add more data types here... e.g.
-
-
- struct url_spec url[1];
-
- struct
- {
- struct action_spec action[1];
- const char * name;
- } alias;
-
- */
-
} data;
};
/** This file_line is in a {{description}} block. */
#define FILE_LINE_DESCRIPTION_ENTRY 10
+/*
+ * Number of file modification time mismatches
+ * before the CGI editor gets turned off.
+ */
+#define ACCEPTABLE_TIMESTAMP_MISMATCHES 3
/**
* A configuration file, in a format that can be edited and written back to
For example "content-filter-params" */
const char *type; /**< Name of the filter type,
for example "server-header-filter". */
+ /* XXX: check if these two can be combined. */
+ const char *disable_all_option; /**< Name of the catch-all radio option that has
+ to be checked or unchecked for this filter type. */
+ const char *disable_all_param; /**< Name of the parameter that causes all filters of
+ this type to be disabled. */
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,
};
/* Accessed by index, keep the order in the way the FT_ macros are defined. */
-const static struct filter_type_info filter_type_info[] =
+static const struct filter_type_info filter_type_info[] =
{
{
ACTION_MULTI_FILTER,
"content-filter-params", "filter",
+ "filter-all", "filter_all",
"F", "FILTER"
},
{
ACTION_MULTI_CLIENT_HEADER_FILTER,
"client-header-filter-params", "client-header-filter",
+ "client-header-filter-all", "client_header_filter_all",
"C", "CLIENT-HEADER-FILTER"
},
{
ACTION_MULTI_SERVER_HEADER_FILTER,
"server-header-filter-params", "server-header-filter",
+ "server-header-filter-all", "server_header_filter_all",
"S", "SERVER-HEADER-FILTER"
},
{
ACTION_MULTI_CLIENT_HEADER_TAGGER,
"client-header-tagger-params", "client-header-tagger",
+ "client-header-tagger-all", "client_header_tagger_all",
"L", "CLIENT-HEADER-TAGGER"
},
{
ACTION_MULTI_SERVER_HEADER_TAGGER,
"server-header-tagger-params", "server-header-tagger",
+ "server-header-tagger-all", "server_header_tagger_all",
"E", "SERVER-HEADER-TAGGER"
},
+#ifdef FEATURE_EXTERNAL_FILTERS
+ {
+ ACTION_MULTI_EXTERNAL_FILTER,
+ "external-content-filter-params", "external-filter",
+ "external-content-filter-all", "external_content_filter_all",
+ "E", "EXTERNAL-CONTENT-FILTER"
+ },
+#endif
};
/* FIXME: Following non-static functions should be prototyped in .h or made static */
static jb_err map_copy_parameter_html(struct map *out,
const struct map *in,
const char *name);
-#if 0 /* unused function */
-static jb_err map_copy_parameter_url(struct map *out,
- const struct map *in,
- const char *name);
-#endif /* unused function */
-
-static jb_err get_file_name_param(struct client_state *csp,
- const struct map *parameters,
- const char *param_name,
+
+static jb_err get_file_name_param(struct client_state *csp,
+ const struct map *parameters,
+ const char *param_name,
const char **pfilename);
/* Internal convenience functions */
{
char buf[30];
- snprintf(buf, 30, "#l%d", sectionid);
+ snprintf(buf, sizeof(buf), "#l%u", sectionid);
return(strdup(buf));
}
{
char buf[6];
- snprintf(buf, sizeof(buf), "%i", number);
+ snprintf(buf, sizeof(buf), "%u", number);
return strdup(buf);
}
}
-#if 0 /* unused function */
-/*********************************************************************
- *
- * Function : map_copy_parameter_url
- *
- * Description : Copy a CGI parameter from one map to another, URL
- * encoding it.
- *
- * Parameters :
- * 1 : out = target map
- * 2 : in = source map
- * 3 : name = name of cgi parameter to copy
- *
- * Returns : JB_ERR_OK on success
- * JB_ERR_MEMORY on out-of-memory
- * JB_ERR_CGI_PARAMS if the parameter doesn't exist
- * in the source map
- *
- *********************************************************************/
-static jb_err map_copy_parameter_url(struct map *out,
- const struct map *in,
- const char *name)
-{
- const char * value;
- jb_err err;
-
- assert(out);
- assert(in);
- assert(name);
-
- value = lookup(in, name);
- err = map(out, name, 1, url_encode(value), 0);
-
- if (err)
- {
- /* Out of memory */
- return err;
- }
- else if (*value == '\0')
- {
- return JB_ERR_CGI_PARAMS;
- }
- else
- {
- return JB_ERR_OK;
- }
-}
-#endif /* 0 - unused function */
-
-
/*********************************************************************
*
* Function : cgi_edit_actions_url_form
if ( (cur_line == NULL)
|| (line_number != patternid)
- || (patternid < 1)
+ || (patternid < 1U)
|| (cur_line->type != FILE_LINE_URL))
{
/* Invalid "patternid" parameter */
if (cur_line->type == FILE_LINE_ACTION)
{
section_start_line_number = line_number;
- }
+ }
cur_line = cur_line->next;
}
if ( (cur_line == NULL)
|| (line_number != patternid)
- || (patternid < 1)
+ || (patternid < 1U)
|| (cur_line->type != FILE_LINE_URL))
{
/* Invalid "patternid" parameter */
/* Allocate new memory for string */
len = strlen(cur_line->unprocessed) + (size_t)numhash;
- if (NULL == (str = malloc(len + 1)))
- {
- /* Uh oh, just trashed file! */
- fclose(fp);
- return JB_ERR_MEMORY;
- }
+ str = malloc_or_die(len + 1);
/* Copy string but quote hashes */
src = cur_line->unprocessed;
/* Correct file->version_str */
freez(file->version_str);
- snprintf(version_buf, 22, "%u", file->version);
- version_buf[21] = '\0';
+ snprintf(version_buf, sizeof(version_buf), "%u", file->version);
+ version_buf[sizeof(version_buf)-1] = '\0';
file->version_str = strdup(version_buf);
if (version_buf == NULL)
{
line += 2;
/* Look for optional whitespace */
- while ( (*line == ' ') || (*line == '\t') )
+ while ((*line == ' ') || (*line == '\t'))
{
line++;
}
line += len;
/* Look for optional whitespace */
- while ( (*line == ' ') || (*line == '\t') )
+ while ((*line == ' ') || (*line == '\t'))
{
line++;
}
}
name_len = (size_t)(name_end - line) + 1; /* Length excluding \0 */
- if (NULL == (*pname = (char *) malloc(name_len + 1)))
- {
- return JB_ERR_MEMORY;
- }
+ *pname = malloc_or_die(name_len + 1);
strncpy(*pname, line, name_len);
(*pname)[name_len] = '\0';
/* Skip leading blanks. Should only happen if file is
* empty (which is valid, but pointless).
*/
- while ( (cur_line != NULL)
- && (cur_line->unprocessed[0] == '\0') )
+ while ((cur_line != NULL)
+ && (cur_line->unprocessed[0] == '\0'))
{
/* Blank line */
cur_line->type = FILE_LINE_BLANK;
cur_line = cur_line->next;
}
- if ( (cur_line != NULL)
- && (cur_line->unprocessed[0] != '{') )
+ if ((cur_line != NULL)
+ && (cur_line->unprocessed[0] != '{'))
{
/* File doesn't start with a header */
file->parse_error = cur_line;
return JB_ERR_PARSE;
}
- if ( (cur_line != NULL) && (0 ==
- match_actions_file_header_line(cur_line->unprocessed, "settings") ) )
+ if ((cur_line != NULL) && (0 ==
+ match_actions_file_header_line(cur_line->unprocessed, "settings")))
{
cur_line->type = FILE_LINE_SETTINGS_HEADER;
}
}
- if ( (cur_line != NULL) && (0 ==
- match_actions_file_header_line(cur_line->unprocessed, "description") ) )
+ if ((cur_line != NULL) && (0 ==
+ match_actions_file_header_line(cur_line->unprocessed, "description")))
{
cur_line->type = FILE_LINE_DESCRIPTION_HEADER;
}
}
- if ( (cur_line != NULL) && (0 ==
- match_actions_file_header_line(cur_line->unprocessed, "alias") ) )
+ if ((cur_line != NULL) && (0 ==
+ match_actions_file_header_line(cur_line->unprocessed, "alias")))
{
cur_line->type = FILE_LINE_ALIAS_HEADER;
return JB_ERR_PARSE;
}
- while ( (*text == ' ') || (*text == '\t') )
+ while ((*text == ' ') || (*text == '\t'))
{
text++;
len--;
}
- while ( (len > 0)
- && ( (text[len - 1] == ' ')
- || (text[len - 1] == '\t') ) )
+ while ((len > (size_t)0)
+ && ((text[len - 1] == ' ')
+ || (text[len - 1] == '\t')))
{
len--;
}
cur_line->type = FILE_LINE_ACTION;
/* Remove {} and make copy */
- if (NULL == (value = (char *) malloc(len + 1)))
- {
- /* Out of memory */
- free_alias_list(alias_list);
- return JB_ERR_MEMORY;
- }
+ value = malloc_or_die(len + 1);
strncpy(value, text, len);
value[len] = '\0';
if (rval)
{
/* Out of memory or empty file. */
- /* Note that empty file is not an error we propogate up */
+ /* Note that empty file is not an error we propagate up */
free(cur_line);
return ((rval == JB_ERR_FILE) ? JB_ERR_OK : rval);
}
* Probably an old-school URL like
* http://config.privoxy.org/edit-actions-list?f=default
*/
- err = get_file_name_param(csp, parameters, "f", &filename);
+ get_file_name_param(csp, parameters, "f", &filename);
}
if (NULL == filename || stat(filename, statbuf) < 0)
/* Correct file->version_str */
freez(file->version_str);
- snprintf(version_buf, 22, "%u", file->version);
- version_buf[21] = '\0';
+ snprintf(version_buf, sizeof(version_buf), "%u", file->version);
+ version_buf[sizeof(version_buf)-1] = '\0';
file->version_str = strdup(version_buf);
if (version_buf == NULL)
{
{
jb_err err;
struct editable_file *file;
+ static int acceptable_failures = ACCEPTABLE_TIMESTAMP_MISMATCHES - 1;
assert(csp);
assert(parameters);
}
else if (err == JB_ERR_MODIFIED)
{
+ assert(require_version);
err = cgi_error_modified(csp, rsp, lookup(parameters, "f"));
+ log_error(LOG_LEVEL_ERROR,
+ "Blocking CGI edit request due to modification time mismatch.");
+ if (acceptable_failures > 0)
+ {
+ log_error(LOG_LEVEL_INFO,
+ "The CGI editor will be turned off after another %d mismatche(s).",
+ acceptable_failures);
+ acceptable_failures--;
+ }
+ else
+ {
+ log_error(LOG_LEVEL_INFO,
+ "Timestamp mismatch limit reached, turning CGI editor off. "
+ "Reload the configuration file to re-enable it.");
+ csp->config->feature_flags &= ~RUNTIME_FEATURE_CGI_EDIT_ACTIONS;
+ }
}
if (err == JB_ERR_OK)
{
&& ((ch < 'a') || (ch > 'z'))
&& ((ch < '0') || (ch > '9'))
&& (ch != '-')
- && (ch != '_') )
+ && (ch != '_'))
{
/* Probable hack attempt. */
return JB_ERR_CGI_PARAMS;
/* Append extension */
name_size = len + strlen(suffix) + 1;
- name = malloc(name_size);
- if (name == NULL)
- {
- return JB_ERR_MEMORY;
- }
+ name = malloc_or_die(name_size);
strlcpy(name, param, name_size);
strlcat(name, suffix, name_size);
const char *orig_param;
char *param;
char *s;
- struct url_spec compiled[1];
+ struct pattern_spec compiled[1];
jb_err err;
assert(csp);
free(param);
return JB_ERR_MEMORY;
}
- err = create_url_spec(compiled, s);
+ err = create_pattern_spec(compiled, s);
free(s);
if (err)
{
free(param);
return (err == JB_ERR_MEMORY) ? JB_ERR_MEMORY : JB_ERR_CGI_PARAMS;
}
- free_url_spec(compiled);
+ free_pattern_spec(compiled);
if (param[strlen(param) - 1] == '\\')
{
free(param);
return JB_ERR_MEMORY;
}
- err = create_url_spec(compiled, s);
+ err = create_pattern_spec(compiled, s);
free(s);
if (err)
{
free(param);
return (err == JB_ERR_MEMORY) ? JB_ERR_MEMORY : JB_ERR_CGI_PARAMS;
}
- free_url_spec(compiled);
+ free_pattern_spec(compiled);
}
*pvalue = param;
assert(optionname);
assert(values);
- buf = malloc(buf_size);
- if (buf == NULL)
- {
- return JB_ERR_MEMORY;
- }
+ buf = malloc_or_die(buf_size);
strlcpy(buf, optionname, buf_size);
struct http_response *rsp,
const struct map *parameters)
{
+ (void)parameters;
if (0 == (csp->config->feature_flags & RUNTIME_FEATURE_CGI_EDIT_ACTIONS))
{
if (err)
{
/* No filename specified, can't read file, or out of memory. */
+ free_map(exports);
return (err == JB_ERR_FILE ? JB_ERR_OK : err);
}
*/
if (!err) err = map_conditional(exports, "all-urls-present", 1);
- snprintf(buf, 150, "%d", line_number);
+ snprintf(buf, sizeof(buf), "%u", line_number);
if (!err) err = map(exports, "all-urls-s", 1, buf, 1);
- snprintf(buf, 150, "%d", line_number + 2);
+ snprintf(buf, sizeof(buf), "%u", line_number + 2);
if (!err) err = map(exports, "all-urls-s-next", 1, buf, 1);
if (!err) err = map(exports, "all-urls-actions", 1,
actions_to_html(csp, cur_line->data.action), 0);
free(url_template);
edit_free_file(file);
free_map(exports);
- free(url_template);
return err;
}
return JB_ERR_MEMORY;
}
- snprintf(buf, 150, "%d", line_number);
+ snprintf(buf, sizeof(buf), "%u", line_number);
err = map(section_exports, "s", 1, buf, 1);
if (!err) err = map(section_exports, "actions", 1,
actions_to_html(csp, cur_line->data.action), 0);
- if ( (!err)
+ if ((!err)
&& (cur_line->next != NULL)
&& (cur_line->next->type == FILE_LINE_URL))
{
if (prev_section_line_number != ((unsigned)(-1)))
{
/* Not last section */
- snprintf(buf, 150, "%d", prev_section_line_number);
+ snprintf(buf, sizeof(buf), "%u", prev_section_line_number);
if (!err) err = map(section_exports, "s-prev", 1, buf, 1);
if (!err) err = map_block_keep(section_exports, "s-prev-exists");
}
return JB_ERR_MEMORY;
}
- snprintf(buf, 150, "%d", line_number);
+ snprintf(buf, sizeof(buf), "%u", line_number);
err = map(url_exports, "p", 1, buf, 1);
- snprintf(buf, 150, "%d", url_1_2);
+ snprintf(buf, sizeof(buf), "%d", url_1_2);
if (!err) err = map(url_exports, "url-1-2", 1, buf, 1);
if (!err) err = map(url_exports, "url-html", 1,
/* Could also do section-specific exports here, but it wouldn't be as fast */
- snprintf(buf, 150, "%d", line_number);
+ snprintf(buf, sizeof(buf), "%u", line_number);
if (!err) err = map(section_exports, "s-next", 1, buf, 1);
- if ( (cur_line != NULL)
- && (cur_line->type == FILE_LINE_ACTION))
+ if ((cur_line != NULL)
+ && (cur_line->type == FILE_LINE_ACTION))
{
/* Not last section */
if (!err) err = map_block_keep(section_exports, "s-next-exists");
if (!err) err = actions_to_radio(exports, cur_line->data.action);
/*
- * XXX: Some browsers (at least IE6 and IE7) have an artifical URL
+ * XXX: Some browsers (at least IE6 and IE7) have an artificial URL
* length limitation and ignore clicks on the Submit buttons if
* the resulting GET URL would be longer than their limit.
*
* browsers (BR #1570678).
*
* The config option split-large-forms works around this browser
- * bug (HTTP has no URL lenght limitation) by deviding the action
+ * bug (HTTP has no URL length limitation) by deviding the action
* list form into multiple smaller ones. It means the URLs are shorter
* and work in broken browsers as well, but the user can no longer change
* all actions with one submit.
* A better solution would be to switch to POST requests,
* but this will do for now.
*/
- if(!err && (csp->config->feature_flags & RUNTIME_FEATURE_SPLIT_LARGE_FORMS))
+ if (!err && (csp->config->feature_flags & RUNTIME_FEATURE_SPLIT_LARGE_FORMS))
{
/* Generate multiple smaller form by killing the big one. */
err = map_block_killer(exports, "one-form-only");
}
}
+#ifndef FEATURE_EXTERNAL_FILTERS
+ if (!err) err = map_block_killer(exports, "external-content-filters");
+#endif
+
if (err)
{
edit_free_file(file);
}
}
- if (!err) err = map_radio(exports, "filter-all", "nx",
- (cur_line->data.action->multi_remove_all[ACTION_MULTI_FILTER] ? 'n' : 'x'));
+ /* Check or uncheck the "disable all of this type" radio buttons. */
+ for (i = 0; i < MAX_FILTER_TYPES; i++)
+ {
+ const int a = filter_type_info[i].multi_action_index;
+ const int disable_all = cur_line->data.action->multi_remove_all[a];
+ if (err) break;
+ err = map_radio(exports, filter_type_info[i].disable_all_option, "nx", (disable_all ? 'n' : 'x'));
+ }
edit_free_file(file);
char target[1024];
jb_err err;
int filter_identifier;
+ int i;
const char * action_set_name;
- char ch;
struct file_list * fl;
struct url_actions * b;
{
if (!strncmp(b->url->spec, "standard.", 9) && !strcmp(b->url->spec + 9, action_set_name))
{
- copy_action(cur_line->data.action, b->action);
+ copy_action(cur_line->data.action, b->action);
goto found;
}
}
err = actions_from_radio(parameters, cur_line->data.action);
}
- if(err)
+ if (err)
{
/* Out of memory */
edit_free_file(file);
return err;
}
- ch = get_char_param(parameters, "filter_all");
- if (ch == 'N')
+ /* Check the "disable all of this type" parameters. */
+ for (i = 0; i < MAX_FILTER_TYPES; i++)
{
- list_remove_all(cur_line->data.action->multi_add[ACTION_MULTI_FILTER]);
- list_remove_all(cur_line->data.action->multi_remove[ACTION_MULTI_FILTER]);
- cur_line->data.action->multi_remove_all[ACTION_MULTI_FILTER] = 1;
- }
- else if (ch == 'X')
- {
- cur_line->data.action->multi_remove_all[ACTION_MULTI_FILTER] = 0;
+ const int multi_action_index = filter_type_info[i].multi_action_index;
+ const char ch = get_char_param(parameters, filter_type_info[i].disable_all_param);
+
+ if (ch == 'N')
+ {
+ list_remove_all(cur_line->data.action->multi_add[multi_action_index]);
+ list_remove_all(cur_line->data.action->multi_remove[multi_action_index]);
+ cur_line->data.action->multi_remove_all[multi_action_index] = 1;
+ }
+ else if (ch == 'X')
+ {
+ cur_line->data.action->multi_remove_all[multi_action_index] = 0;
+ }
}
for (filter_identifier = 0; !err; filter_identifier++)
}
}
- if(err)
+ if (err)
{
/* Out of memory */
edit_free_file(file);
}
newtext_size = len + 2;
- if (NULL == (newtext = malloc(newtext_size)))
- {
- /* Out of memory */
- free(actiontext);
- edit_free_file(file);
- return JB_ERR_MEMORY;
- }
+ newtext = malloc_or_die(newtext_size);
strlcpy(newtext, actiontext, newtext_size);
free(actiontext);
newtext[0] = '{';
return err;
}
- snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%i#l%d",
+ snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%i#l%u",
(long) time(NULL), file->identifier, sectionid);
edit_free_file(file);
if (cur_line->type == FILE_LINE_ACTION)
{
section_start_line_number = line_number;
- }
+ }
cur_line = cur_line->next;
line_number++;
}
- if ( (cur_line == NULL)
- || (cur_line->type != FILE_LINE_URL))
+ if ((cur_line == NULL)
+ || (cur_line->type != FILE_LINE_URL))
{
/* Invalid "patternid" parameter */
free(new_pattern);
return err;
}
- snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%i#l%d",
+ snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%i#l%u",
(long) time(NULL), file->identifier, section_start_line_number);
edit_free_file(file);
line_number++;
}
- if ( (cur_line == NULL)
- || (cur_line->type != FILE_LINE_ACTION))
+ if ((cur_line == NULL)
+ || (cur_line->type != FILE_LINE_ACTION))
{
/* Invalid "sectionid" parameter */
free(new_pattern);
return err;
}
- snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%i#l%d",
+ snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%i#l%u",
(long) time(NULL), file->identifier, sectionid);
edit_free_file(file);
return err;
}
- snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%i#l%d",
+ snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%u#l%u",
(long) time(NULL), file->identifier, section_start_line_number);
edit_free_file(file);
line_number++;
}
- if ( (cur_line == NULL)
- || (cur_line->type != FILE_LINE_ACTION) )
+ if ((cur_line == NULL)
+ || (cur_line->type != FILE_LINE_ACTION))
{
/* Invalid "sectionid" parameter */
edit_free_file(file);
return JB_ERR_CGI_PARAMS;
}
- if ( (cur_line->next != NULL)
- && (cur_line->next->type == FILE_LINE_URL) )
+ if ((cur_line->next != NULL)
+ && (cur_line->next->type == FILE_LINE_URL))
{
/* Section not empty. */
edit_free_file(file);
return err;
}
- snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%i",
+ snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%u",
(long) time(NULL), file->identifier);
edit_free_file(file);
/* There's something in the file, find the line before the first
* action.
*/
- while ( (cur_line->next != NULL)
- && (cur_line->next->type != FILE_LINE_ACTION) )
+ while ((cur_line->next != NULL)
+ && (cur_line->next->type != FILE_LINE_ACTION))
{
cur_line = cur_line->next;
line_number++;
line_number++;
}
- if ( (cur_line == NULL)
- || (cur_line->type != FILE_LINE_ACTION))
+ if ((cur_line == NULL)
+ || (cur_line->type != FILE_LINE_ACTION))
{
/* Invalid "sectionid" parameter */
edit_free_file(file);
}
/* Skip through the section to find the last line in it. */
- while ( (cur_line->next != NULL)
- && (cur_line->next->type != FILE_LINE_ACTION) )
+ while ((cur_line->next != NULL)
+ && (cur_line->next->type != FILE_LINE_ACTION))
{
cur_line = cur_line->next;
line_number++;
return err;
}
- snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%i",
+ snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%u",
(long) time(NULL), file->identifier);
edit_free_file(file);
line_number++;
}
- if ( (cur_line == NULL)
- || (cur_line->type != FILE_LINE_ACTION) )
+ if ((cur_line == NULL)
+ || (cur_line->type != FILE_LINE_ACTION))
{
/* Invalid "section1" parameter */
edit_free_file(file);
line_number++;
}
- if ( (cur_line == NULL)
- || (cur_line->type != FILE_LINE_ACTION) )
+ if ((cur_line == NULL)
+ || (cur_line->type != FILE_LINE_ACTION))
{
/* Invalid "section2" parameter */
edit_free_file(file);
}
} /* END if (section1 != section2) */
- snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%i",
+ snprintf(target, sizeof(target), CGI_PREFIX "edit-actions-list?foo=%lu&f=%u",
(long) time(NULL), file->identifier);
edit_free_file(file);
return cgi_redirect(rsp, target);
}
-#ifdef FEATURE_TOGGLE
-/*********************************************************************
- *
- * Function : cgi_toggle
- *
- * Description : CGI function that adds a new empty section to
- * an actions file.
- *
- * 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 :
- * set : If present, how to change toggle setting:
- * "enable", "disable", "toggle", or none (default).
- * mini : If present, use mini reply template.
- *
- * Returns : JB_ERR_OK on success
- * JB_ERR_MEMORY on out-of-memory
- *
- *********************************************************************/
-jb_err cgi_toggle(struct client_state *csp,
- struct http_response *rsp,
- const struct map *parameters)
-{
- struct map *exports;
- char mode;
- const char *template_name;
-
- assert(csp);
- assert(rsp);
- assert(parameters);
-
- if (0 == (csp->config->feature_flags & RUNTIME_FEATURE_CGI_TOGGLE))
- {
- return cgi_error_disabled(csp, rsp);
- }
-
- mode = get_char_param(parameters, "set");
-
- if (mode == 'E')
- {
- /* Enable */
- global_toggle_state = 1;
- }
- else if (mode == 'D')
- {
- /* Disable */
- global_toggle_state = 0;
- }
- else if (mode == 'T')
- {
- /* Toggle */
- global_toggle_state = !global_toggle_state;
- }
-
- if (NULL == (exports = default_exports(csp, "toggle")))
- {
- return JB_ERR_MEMORY;
- }
-
- template_name = (get_char_param(parameters, "mini")
- ? "toggle-mini"
- : "toggle");
-
- return template_fill_for_cgi(csp, template_name, exports, rsp);
-}
-#endif /* def FEATURE_TOGGLE */
/*********************************************************************
*
*
* Description : Converts a string into a form JavaScript will like.
*
- * Netscape 4's JavaScript sucks - it doesn't use
+ * Netscape 4's JavaScript sucks - it doesn't use
* "id" parameters, so you have to set the "name"
* used to submit a form element to something JavaScript
* will like. (Or access the elements by index in an
static jb_err actions_to_radio(struct map * exports,
const struct action_spec *action)
{
- unsigned mask = action->mask;
- unsigned add = action->add;
+ unsigned long mask;
+ unsigned long add;
int mapped_param;
int checked;
char current_mode;
return err;
}
+#endif /* def FEATURE_CGI_EDIT_ACTIONS */
-#endif /* def FEATURE_CGI_EDIT_ACTIONS */
+#ifdef FEATURE_TOGGLE
+/*********************************************************************
+ *
+ * Function : cgi_toggle
+ *
+ * Description : CGI function that adds a new empty section to
+ * an actions file.
+ *
+ * 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 :
+ * set : If present, how to change toggle setting:
+ * "enable", "disable", "toggle", or none (default).
+ * mini : If present, use mini reply template.
+ *
+ * Returns : JB_ERR_OK on success
+ * JB_ERR_MEMORY on out-of-memory
+ *
+ *********************************************************************/
+jb_err cgi_toggle(struct client_state *csp,
+ struct http_response *rsp,
+ const struct map *parameters)
+{
+ struct map *exports;
+ char mode;
+ const char *template_name;
+
+ assert(csp);
+ assert(rsp);
+ assert(parameters);
+
+ if (0 == (csp->config->feature_flags & RUNTIME_FEATURE_CGI_TOGGLE))
+ {
+ return cgi_error_disabled(csp, rsp);
+ }
+
+ mode = get_char_param(parameters, "set");
+
+ if (mode == 'E')
+ {
+ /* Enable */
+ global_toggle_state = 1;
+ }
+ else if (mode == 'D')
+ {
+ /* Disable */
+ global_toggle_state = 0;
+ }
+ else if (mode == 'T')
+ {
+ /* Toggle */
+ global_toggle_state = !global_toggle_state;
+ }
+
+ if (NULL == (exports = default_exports(csp, "toggle")))
+ {
+ return JB_ERR_MEMORY;
+ }
+
+ template_name = (get_char_param(parameters, "mini")
+ ? "toggle-mini"
+ : "toggle");
+
+ return template_fill_for_cgi(csp, template_name, exports, rsp);
+}
+#endif /* def FEATURE_TOGGLE */
/*