X-Git-Url: http://www.privoxy.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=actions.c;h=bd466f87d1a784e46e2199837220e92ba6206ce5;hb=07cf496b6edcbd3cf315ec7c48f2c94be27357b1;hp=d7212c6ddc690e83415489691cafa4135061c14b;hpb=994e35d0510a22346d510eee39829f91a2f13387;p=privoxy.git diff --git a/actions.c b/actions.c index d7212c6d..bd466f87 100644 --- a/actions.c +++ b/actions.c @@ -1,4 +1,4 @@ -const char actions_rcs[] = "$Id: actions.c,v 1.58 2009/05/16 13:27:20 fabiankeil Exp $"; +const char actions_rcs[] = "$Id: actions.c,v 1.72 2011/09/04 11:36:33 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/actions.c,v $ @@ -6,7 +6,7 @@ const char actions_rcs[] = "$Id: actions.c,v 1.58 2009/05/16 13:27:20 fabiankeil * Purpose : Declares functions to work with actions files * Functions declared include: FIXME * - * Copyright : Written by and Copyright (C) 2001-2008 the SourceForge + * Copyright : Written by and Copyright (C) 2001-2011 the * Privoxy team. http://www.privoxy.org/ * * Based on the Internet Junkbuster originally written @@ -434,7 +434,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", @@ -522,7 +522,7 @@ jb_err get_actions(char *line, if ((value == NULL) || (*value == '\0')) { - if (0 != strcmpic(action->name, "block")) + if (0 == strcmpic(action->name, "+block")) { /* * XXX: Temporary backwards compatibility hack. @@ -1033,6 +1033,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 @@ -1055,23 +1157,24 @@ static int load_one_actions_file(struct client_state *csp, int fileid) * Note: Keep these in the order they occur in the file, they are * sometimes tested with <= */ -#define MODE_START_OF_FILE 1 -#define MODE_SETTINGS 2 -#define MODE_DESCRIPTION 3 -#define MODE_ALIAS 4 -#define MODE_ACTIONS 5 - - int mode = MODE_START_OF_FILE; + enum { + MODE_START_OF_FILE = 1, + MODE_SETTINGS = 2, + MODE_DESCRIPTION = 3, + MODE_ALIAS = 4, + MODE_ACTIONS = 5 + } mode; FILE *fp; struct url_actions *last_perm; struct url_actions *perm; - char buf[BUFFER_SIZE]; + char *buf; struct file_list *fs; struct action_spec * cur_action = NULL; int cur_action_used = 0; struct action_alias * alias_list = NULL; unsigned long linenum = 0; + mode = MODE_START_OF_FILE; if (!check_file_changed(current_actions_file[fileid], csp->config->actions_file[fileid], &fs)) { @@ -1104,7 +1207,7 @@ static int load_one_actions_file(struct client_state *csp, int fileid) log_error(LOG_LEVEL_INFO, "Loading actions file: %s", csp->config->actions_file[fileid]); - while (read_config_line(buf, sizeof(buf), fp, &linenum) != NULL) + while (read_config_line(fp, &linenum, &buf) != NULL) { if (*buf == '{') { @@ -1120,7 +1223,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 */ } @@ -1221,11 +1324,11 @@ 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 */ - mode = MODE_ACTIONS; + mode = MODE_ACTIONS; /* free old action */ if (cur_action) @@ -1248,8 +1351,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; @@ -1257,8 +1375,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 */ } @@ -1271,11 +1390,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) @@ -1299,8 +1428,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) { @@ -1409,7 +1538,7 @@ static int load_one_actions_file(struct client_state *csp, int fileid) } else if (mode == MODE_ACTIONS) { - /* it's a URL pattern */ + /* it's an URL pattern */ /* allocate a new node */ if ((perm = zalloc(sizeof(*perm))) == NULL) @@ -1429,7 +1558,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 */ } @@ -1443,7 +1572,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 */ } @@ -1456,6 +1585,7 @@ static int load_one_actions_file(struct client_state *csp, int fileid) csp->config->actions_file[fileid], mode); return 1; /* never get here */ } + freez(buf); } fclose(fp); @@ -1489,7 +1619,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. @@ -1574,7 +1704,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. * @@ -1680,12 +1810,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.