X-Git-Url: http://www.privoxy.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=actions.c;h=82495714995ca0d983f24d6b08b31d340135704d;hb=3d2d6a157f8b301b27c95d57a74ccf3d9bfa870c;hp=5b321145bb344d6f1b20bdf044443f2278f8c43e;hpb=e6a771dacfb7cce3e202e06cb46612cf5d35d920;p=privoxy.git
diff --git a/actions.c b/actions.c
index 5b321145..82495714 100644
--- a/actions.c
+++ b/actions.c
@@ -1,10 +1,9 @@
-const char actions_rcs[] = "$Id: actions.c,v 1.62 2011/02/14 16:01:20 fabiankeil Exp $";
+const char actions_rcs[] = "$Id: actions.c,v 1.77 2012/02/29 19:31:12 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/actions.c,v $
*
* Purpose : Declares functions to work with actions files
- * Functions declared include: FIXME
*
* Copyright : Written by and Copyright (C) 2001-2011 the
* Privoxy team. http://www.privoxy.org/
@@ -70,11 +69,13 @@ const char actions_h_rcs[] = ACTIONS_H_VERSION;
* an enumerated type (well, the preprocessor equivalent). Here are
* the values:
*/
-#define AV_NONE 0 /* +opt -opt */
-#define AV_ADD_STRING 1 /* +stropt{string} */
-#define AV_REM_STRING 2 /* -stropt */
-#define AV_ADD_MULTI 3 /* +multiopt{string} +multiopt{string2} */
-#define AV_REM_MULTI 4 /* -multiopt{string} -multiopt */
+enum action_value_type {
+ AV_NONE = 0, /* +opt -opt */
+ AV_ADD_STRING = 1, /* +stropt{string} */
+ AV_REM_STRING = 2, /* -stropt */
+ AV_ADD_MULTI = 3, /* +multiopt{string} +multiopt{string2} */
+ AV_REM_MULTI = 4 /* -multiopt{string} -multiopt */
+};
/*
* We need a structure to hold the name, flag changes,
@@ -83,10 +84,10 @@ const char actions_h_rcs[] = ACTIONS_H_VERSION;
struct action_name
{
const char * name;
- unsigned long mask; /* a bit set to "0" = remove action */
- unsigned long add; /* a bit set to "1" = add action */
- int takes_value; /* an AV_... constant */
- int index; /* index into strings[] or multi[] */
+ unsigned long mask; /* a bit set to "0" = remove action */
+ unsigned long add; /* a bit set to "1" = add action */
+ enum action_value_type value_type; /* an AV_... constant */
+ int index; /* index into strings[] or multi[] */
};
/*
@@ -319,7 +320,7 @@ void free_action (struct action_spec *src)
* Function : get_action_token
*
* Description : Parses a line for the first action.
- * Modifies it's input array, doesn't allocate memory.
+ * Modifies its input array, doesn't allocate memory.
* e.g. given:
* *line=" +abc{def} -ghi "
* Returns:
@@ -434,7 +435,7 @@ jb_err get_action_token(char **line, char **name, char **value)
*********************************************************************/
static int action_used_to_be_valid(const char *action)
{
- static const char *formerly_valid_actions[] = {
+ static const char * const formerly_valid_actions[] = {
"inspect-jpegs",
"kill-popups",
"send-vanilla-wafer",
@@ -511,7 +512,7 @@ jb_err get_actions(char *line,
cur_action->add &= action->mask;
cur_action->add |= action->add;
- switch (action->takes_value)
+ switch (action->value_type)
{
case AV_NONE:
/* ignore any option. */
@@ -772,36 +773,6 @@ jb_err merge_current_action (struct current_action_spec *dest,
return err;
}
-#if 0
-/*********************************************************************
- *
- * Function : update_action_bits_for_all_tags
- *
- * Description : Updates the action bits based on all matching tags.
- *
- * Parameters :
- * 1 : csp = Current client state (buffers, headers, etc...)
- *
- * Returns : 0 if no tag matched, or
- * 1 otherwise
- *
- *********************************************************************/
-int update_action_bits_for_all_tags(struct client_state *csp)
-{
- struct list_entry *tag;
- int updated = 0;
-
- for (tag = csp->tags->first; tag != NULL; tag = tag->next)
- {
- if (update_action_bits_for_tag(csp, tag->str))
- {
- updated = 1;
- }
- }
-
- return updated;
-}
-#endif
/*********************************************************************
*
@@ -1033,6 +1004,108 @@ int load_action_files(struct client_state *csp)
return 0;
}
+
+/*********************************************************************
+ *
+ * Function : referenced_filters_are_missing
+ *
+ * Description : Checks if any filters of a certain type referenced
+ * in an action spec are missing.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ * 2 : cur_action = The action spec to check.
+ * 3 : multi_index = The index where to look for the filter.
+ * 4 : filter_type = The filter type the caller is interested in.
+ *
+ * Returns : 0 => All referenced filters exists, everything else is an error.
+ *
+ *********************************************************************/
+static int referenced_filters_are_missing(const struct client_state *csp,
+ const struct action_spec *cur_action, int multi_index, enum filter_type filter_type)
+{
+ int i;
+ struct file_list *fl;
+ struct re_filterfile_spec *b;
+ struct list_entry *filtername;
+
+ for (filtername = cur_action->multi_add[multi_index]->first;
+ filtername; filtername = filtername->next)
+ {
+ int filter_found = 0;
+ for (i = 0; i < MAX_AF_FILES; i++)
+ {
+ fl = csp->rlist[i];
+ if ((NULL == fl) || (NULL == fl->f))
+ {
+ continue;
+ }
+
+ for (b = fl->f; b; b = b->next)
+ {
+ if (b->type != filter_type)
+ {
+ continue;
+ }
+ if (strcmp(b->name, filtername->str) == 0)
+ {
+ filter_found = 1;
+ }
+ }
+ }
+ if (!filter_found)
+ {
+ log_error(LOG_LEVEL_ERROR, "Missing filter '%s'", filtername->str);
+ return 1;
+ }
+ }
+
+ return 0;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : action_spec_is_valid
+ *
+ * Description : Should eventually figure out if an action spec
+ * is valid, but currently only checks that the
+ * referenced filters are accounted for.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ * 2 : cur_action = The action spec to check.
+ *
+ * Returns : 0 => No problems detected, everything else is an error.
+ *
+ *********************************************************************/
+static int action_spec_is_valid(struct client_state *csp, const struct action_spec *cur_action)
+{
+ struct {
+ int multi_index;
+ enum filter_type filter_type;
+ } filter_map[] = {
+ {ACTION_MULTI_FILTER, FT_CONTENT_FILTER},
+ {ACTION_MULTI_CLIENT_HEADER_FILTER, FT_CLIENT_HEADER_FILTER},
+ {ACTION_MULTI_SERVER_HEADER_FILTER, FT_SERVER_HEADER_FILTER},
+ {ACTION_MULTI_CLIENT_HEADER_TAGGER, FT_CLIENT_HEADER_TAGGER},
+ {ACTION_MULTI_SERVER_HEADER_TAGGER, FT_SERVER_HEADER_TAGGER}
+ };
+ int errors = 0;
+ int i;
+
+ for (i = 0; i < SZ(filter_map); i++)
+ {
+ errors += referenced_filters_are_missing(csp, cur_action,
+ filter_map[i].multi_index, filter_map[i].filter_type);
+ }
+
+ return errors;
+
+}
+
+
/*********************************************************************
*
* Function : load_one_actions_file
@@ -1121,7 +1194,7 @@ static int load_one_actions_file(struct client_state *csp, int fileid)
/* too short */
fclose(fp);
log_error(LOG_LEVEL_FATAL,
- "can't load actions file '%s': invalid line (%lu): %s",
+ "can't load actions file '%s': invalid line (%lu): %s",
csp->config->actions_file[fileid], linenum, buf);
return 1; /* never get here */
}
@@ -1222,7 +1295,7 @@ static int load_one_actions_file(struct client_state *csp, int fileid)
{
/* It's an actions block */
- char actions_buf[BUFFER_SIZE];
+ char *actions_buf;
char * end;
/* set mode */
@@ -1249,8 +1322,23 @@ static int load_one_actions_file(struct client_state *csp, int fileid)
}
init_action(cur_action);
- /* trim { */
- strlcpy(actions_buf, buf + 1, sizeof(actions_buf));
+ /*
+ * Copy the buffer before messing with it as we may need the
+ * unmodified version in for the fatal error messages. Given
+ * that this is not a common event, we could instead simply
+ * read the line again.
+ *
+ * buf + 1 to skip the leading '{'
+ */
+ actions_buf = strdup(buf + 1);
+ if (actions_buf == NULL)
+ {
+ fclose(fp);
+ log_error(LOG_LEVEL_FATAL,
+ "can't load actions file '%s': out of memory",
+ csp->config->actions_file[fileid]);
+ return 1; /* never get here */
+ }
/* check we have a trailing } and then trim it */
end = actions_buf + strlen(actions_buf) - 1;
@@ -1258,8 +1346,9 @@ static int load_one_actions_file(struct client_state *csp, int fileid)
{
/* No closing } */
fclose(fp);
- log_error(LOG_LEVEL_FATAL,
- "can't load actions file '%s': invalid line (%lu): %s",
+ freez(actions_buf);
+ log_error(LOG_LEVEL_FATAL, "can't load actions file '%s': "
+ "Missing trailing '}' in action section starting at line (%lu): %s",
csp->config->actions_file[fileid], linenum, buf);
return 1; /* never get here */
}
@@ -1272,11 +1361,21 @@ static int load_one_actions_file(struct client_state *csp, int fileid)
{
/* error */
fclose(fp);
- log_error(LOG_LEVEL_FATAL,
- "can't load actions file '%s': invalid line (%lu): %s",
+ freez(actions_buf);
+ log_error(LOG_LEVEL_FATAL, "can't load actions file '%s': "
+ "can't completely parse the action section starting at line (%lu): %s",
csp->config->actions_file[fileid], linenum, buf);
return 1; /* never get here */
}
+
+ if (action_spec_is_valid(csp, cur_action))
+ {
+ log_error(LOG_LEVEL_ERROR, "Invalid action section in file '%s', "
+ "starting at line %lu: %s",
+ csp->config->actions_file[fileid], linenum, buf);
+ }
+
+ freez(actions_buf);
}
}
else if (mode == MODE_SETTINGS)
@@ -1300,8 +1399,8 @@ static int load_one_actions_file(struct client_state *csp, int fileid)
csp->config->actions_file[fileid]);
return 1; /* never get here */
}
-
- num_fields = ssplit(version_string, ".", fields, 3, TRUE, FALSE);
+
+ num_fields = ssplit(version_string, ".", fields, SZ(fields), TRUE, FALSE);
if (num_fields < 1 || atoi(fields[0]) == 0)
{
@@ -1430,7 +1529,7 @@ static int load_one_actions_file(struct client_state *csp, int fileid)
{
fclose(fp);
log_error(LOG_LEVEL_FATAL,
- "can't load actions file '%s': line %lu: cannot create URL pattern from: %s",
+ "can't load actions file '%s': line %lu: cannot create URL or TAG pattern from: %s",
csp->config->actions_file[fileid], linenum, buf);
return 1; /* never get here */
}
@@ -1444,7 +1543,7 @@ static int load_one_actions_file(struct client_state *csp, int fileid)
/* oops - please have a {} line as 1st line in file. */
fclose(fp);
log_error(LOG_LEVEL_FATAL,
- "can't load actions file '%s': first needed line (%lu) is invalid: %s",
+ "can't load actions file '%s': line %lu should begin with a '{': %s",
csp->config->actions_file[fileid], linenum, buf);
return 1; /* never get here */
}
@@ -1491,7 +1590,7 @@ static int load_one_actions_file(struct client_state *csp, int fileid)
*
* Description : Converts a actionsfile entry from the internal
* structure into a text line. The output is split
- * into one line for each action with line continuation.
+ * into one line for each action with line continuation.
*
* Parameters :
* 1 : action = The action to format.
@@ -1576,7 +1675,7 @@ char * actions_to_text(const struct action_spec *action)
* Function : actions_to_html
*
* Description : Converts a actionsfile entry from numeric form
- * ("mask" and "add") to a
-seperated HTML string
+ * ("mask" and "add") to a
-separated HTML string
* in which each action is linked to its chapter in
* the user manual.
*
@@ -1682,12 +1781,12 @@ char * actions_to_html(const struct client_state *csp,
*
* Function : current_actions_to_html
*
- * Description : Converts a curren action spec to a
seperated HTML
+ * Description : Converts a curren action spec to a
separated HTML
* text in which each action is linked to its chapter in
* the user manual.
*
* Parameters :
- * 1 : csp = Client state (for config)
+ * 1 : csp = Client state (for config)
* 2 : action = Current action spec to be converted
*
* Returns : A string. Caller must free it.