X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=actions.c;h=b276abbefd08362e7684acc16db45951cb674a35;hp=8d9e5dee178a98e01e0ee162e344e8842e578a5a;hb=4169cab396ff364c0c43f49cdb8d855dadb59c39;hpb=69102b3b5cfcd3d40a42ead2d26f312c103eea7a diff --git a/actions.c b/actions.c index 8d9e5dee..b276abbe 100644 --- a/actions.c +++ b/actions.c @@ -1,4 +1,4 @@ -const char actions_rcs[] = "$Id: actions.c,v 1.79 2012/03/09 16:23:50 fabiankeil Exp $"; +const char actions_rcs[] = "$Id: actions.c,v 1.91 2013/12/24 13:35:07 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/actions.c,v $ @@ -55,6 +55,7 @@ const char actions_rcs[] = "$Id: actions.c,v 1.79 2012/03/09 16:23:50 fabiankeil #include "urlmatch.h" #include "cgi.h" #include "ssplit.h" +#include "filters.h" const char actions_h_rcs[] = ACTIONS_H_VERSION; @@ -156,11 +157,7 @@ jb_err merge_actions (struct action_spec *dest, if (str) { freez(dest->string[i]); - dest->string[i] = strdup(str); - if (NULL == dest->string[i]) - { - return JB_ERR_MEMORY; - } + dest->string[i] = strdup_or_die(str); } } @@ -212,7 +209,7 @@ jb_err merge_actions (struct action_spec *dest, * 1 : dest = Destination of copy. * 2 : src = Source for copy. * - * Returns : N/A + * Returns : JB_ERR_OK or JB_ERR_MEMORY * *********************************************************************/ jb_err copy_action (struct action_spec *dest, @@ -232,11 +229,7 @@ jb_err copy_action (struct action_spec *dest, char * str = src->string[i]; if (str) { - str = strdup(str); - if (!str) - { - return JB_ERR_MEMORY; - } + str = strdup_or_die(str); dest->string[i] = str; } } @@ -403,7 +396,17 @@ jb_err get_action_token(char **line, char **name, char **value) str++; *value = str; - str = strchr(str, '}'); + /* The value ends with the first non-escaped closing curly brace */ + while ((str = strchr(str, '}')) != NULL) + { + if (str[-1] == '\\') + { + /* Overwrite the '\' so the action doesn't see it. */ + string_move(str-1, str); + continue; + } + break; + } if (str == NULL) { /* error */ @@ -739,11 +742,7 @@ jb_err merge_current_action (struct current_action_spec *dest, char * str = src->string[i]; if (str) { - str = strdup(str); - if (!str) - { - return JB_ERR_MEMORY; - } + str = strdup_or_die(str); freez(dest->string[i]); dest->string[i] = str; } @@ -812,14 +811,14 @@ int update_action_bits_for_tag(struct client_state *csp, const char *tag) /* and through all the action patterns, */ for (b = b->next; NULL != b; b = b->next) { - /* skip the URL patterns, */ - if (NULL == b->url->tag_regex) + /* skip everything but TAG patterns, */ + if (!(b->url->flags & PATTERN_SPEC_TAG_PATTERN)) { continue; } /* and check if one of the tag patterns matches the tag, */ - if (0 == regexec(b->url->tag_regex, tag, 0, NULL, 0)) + if (0 == regexec(b->url->pattern.tag_regex, tag, 0, NULL, 0)) { /* if it does, update the action bit map, */ if (merge_current_action(csp->action, b->action)) @@ -837,6 +836,76 @@ int update_action_bits_for_tag(struct client_state *csp, const char *tag) } +/********************************************************************* + * + * Function : check_negative_tag_patterns + * + * Description : Updates the action bits based on NO-*-TAG patterns. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : flag = The tag pattern type + * + * Returns : JB_ERR_OK in case off success, or + * JB_ERR_MEMORY on out-of-memory error. + * + *********************************************************************/ +jb_err check_negative_tag_patterns(struct client_state *csp, unsigned int flag) +{ + struct list_entry *tag; + struct file_list *fl; + struct url_actions *b = NULL; + int i; + + for (i = 0; i < MAX_AF_FILES; i++) + { + fl = csp->actions_list[i]; + if ((fl == NULL) || ((b = fl->f) == NULL)) + { + continue; + } + for (b = b->next; NULL != b; b = b->next) + { + int tag_found = 0; + if (0 == (b->url->flags & flag)) + { + continue; + } + for (tag = csp->tags->first; NULL != tag; tag = tag->next) + { + if (0 == regexec(b->url->pattern.tag_regex, tag->str, 0, NULL, 0)) + { + /* + * The pattern matches at least one tag, thus the action + * section doesn't apply and we don't need to look at the + * other tags. + */ + tag_found = 1; + break; + } + } + if (!tag_found) + { + /* + * The pattern doesn't match any tags, + * thus the action section applies. + */ + if (merge_current_action(csp->action, b->action)) + { + log_error(LOG_LEVEL_ERROR, + "Out of memory while changing action bits"); + return JB_ERR_MEMORY; + } + log_error(LOG_LEVEL_HEADER, "Updated action bits based on: %s", + b->url->spec); + } + } + } + + return JB_ERR_OK; +} + + /********************************************************************* * * Function : free_current_action @@ -923,7 +992,7 @@ void unload_actions_file(void *file_data) while (cur != NULL) { next = cur->next; - free_url_spec(cur->url); + free_pattern_spec(cur->url); if ((next == NULL) || (next->action != cur->action)) { /* @@ -1018,42 +1087,18 @@ int load_action_files(struct client_state *csp) * 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. + * Returns : 0 => All referenced filters exist, 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) + if (NULL == get_filter(csp, filtername->str, filter_type)) { log_error(LOG_LEVEL_ERROR, "Missing filter '%s'", filtername->str); return 1; @@ -1330,15 +1375,7 @@ static int load_one_actions_file(struct client_state *csp, int fileid) * * 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 */ - } + actions_buf = strdup_or_die(buf + 1); /* check we have a trailing } and then trim it */ end = actions_buf + strlen(actions_buf) - 1; @@ -1391,16 +1428,9 @@ static int load_one_actions_file(struct client_state *csp, int fileid) char *version_string, *fields[3]; int num_fields; - if ((version_string = strdup(buf + 20)) == 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 */ - } + version_string = strdup_or_die(buf + 20); - num_fields = ssplit(version_string, ".", fields, SZ(fields), TRUE, FALSE); + num_fields = ssplit(version_string, ".", fields, SZ(fields)); if (num_fields < 1 || atoi(fields[0]) == 0) { @@ -1409,8 +1439,8 @@ static int load_one_actions_file(struct client_state *csp, int fileid) csp->config->actions_file[fileid], linenum, buf); } else if ( (atoi(fields[0]) > VERSION_MAJOR) - || ((num_fields) > 1 && (atoi(fields[1]) > VERSION_MINOR)) - || ((num_fields) > 2 && (atoi(fields[2]) > VERSION_POINT))) + || ((num_fields > 1) && (atoi(fields[1]) > VERSION_MINOR)) + || ((num_fields > 2) && (atoi(fields[2]) > VERSION_POINT))) { fclose(fp); log_error(LOG_LEVEL_FATAL, @@ -1482,14 +1512,7 @@ static int load_one_actions_file(struct client_state *csp, int fileid) return 1; /* never get here */ } - if ((new_alias->name = strdup(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 */ - } + new_alias->name = strdup_or_die(buf); strlcpy(actions_buf, start, sizeof(actions_buf)); @@ -1525,7 +1548,7 @@ static int load_one_actions_file(struct client_state *csp, int fileid) cur_action_used = 1; /* Save the URL pattern */ - if (create_url_spec(perm->url, buf)) + if (create_pattern_spec(perm->url, buf)) { fclose(fp); log_error(LOG_LEVEL_FATAL, @@ -1603,7 +1626,7 @@ char * actions_to_text(const struct action_spec *action) { unsigned long mask = action->mask; unsigned long add = action->add; - char *result = strdup(""); + char *result = strdup_or_die(""); struct list_entry * lst; /* sanity - prevents "-feature +feature" */ @@ -1692,7 +1715,7 @@ char * actions_to_html(const struct client_state *csp, { unsigned long mask = action->mask; unsigned long add = action->add; - char *result = strdup(""); + char *result = strdup_or_die(""); struct list_entry * lst; /* sanity - prevents "-feature +feature" */ @@ -1798,9 +1821,9 @@ char *current_action_to_html(const struct client_state *csp, { unsigned long flags = action->flags; struct list_entry * lst; - char *result = strdup(""); - char *active = strdup(""); - char *inactive = strdup(""); + char *result = strdup_or_die(""); + char *active = strdup_or_die(""); + char *inactive = strdup_or_die(""); #define DEFINE_ACTION_BOOL(__name, __bit) \ if (flags & __bit) \ @@ -1871,3 +1894,69 @@ char *current_action_to_html(const struct client_state *csp, } return result; } + + +/********************************************************************* + * + * Function : action_to_line_of_text + * + * Description : Converts a action spec to a single text line + * listing the enabled actions. + * + * Parameters : + * 1 : action = Current action spec to be converted + * + * Returns : A string. Caller must free it. + * Out-of-memory errors are fatal. + * + *********************************************************************/ +char *actions_to_line_of_text(const struct current_action_spec *action) +{ + char buffer[200]; + struct list_entry *lst; + char *active; + const unsigned long flags = action->flags; + + active = strdup_or_die(""); + +#define DEFINE_ACTION_BOOL(__name, __bit) \ + if (flags & __bit) \ + { \ + snprintf(buffer, sizeof(buffer), "+%s ", __name); \ + string_append(&active, buffer); \ + } \ + +#define DEFINE_ACTION_STRING(__name, __bit, __index) \ + if (flags & __bit) \ + { \ + snprintf(buffer, sizeof(buffer), "+%s{%s} ", \ + __name, action->string[__index]); \ + string_append(&active, buffer); \ + } \ + +#define DEFINE_ACTION_MULTI(__name, __index) \ + lst = action->multi[__index]->first; \ + while (lst != NULL) \ + { \ + snprintf(buffer, sizeof(buffer), "+%s{%s} ", \ + __name, lst->str); \ + string_append(&active, buffer); \ + lst = lst->next; \ + } \ + +#define DEFINE_ACTION_ALIAS 0 /* No aliases for output */ + +#include "actionlist.h" + +#undef DEFINE_ACTION_MULTI +#undef DEFINE_ACTION_STRING +#undef DEFINE_ACTION_BOOL +#undef DEFINE_ACTION_ALIAS + + if (active == NULL) + { + log_error(LOG_LEVEL_FATAL, "Out of memory in action_to_line_of_text()"); + } + + return active; +}