1 #! /bin/sh /usr/share/dpatch/dpatch-run
2 ## 12_multiple-filters.dpatch
3 ## by David Schmidt <david__schmidt@users.sourceforge.net>
5 ## All lines beginning with `## DP:' are a description of the patch.
6 ## DP: Multiple filter file support
9 diff -urNad privoxy~/actions.c privoxy/actions.c
10 --- privoxy~/actions.c 2006-02-11 23:44:25.000000000 +0100
11 +++ privoxy/actions.c 2006-02-11 23:44:37.000000000 +0100
16 -static struct file_list *current_actions_file[MAX_ACTION_FILES] = {
17 +static struct file_list *current_actions_file[MAX_AF_FILES] = {
18 NULL, NULL, NULL, NULL, NULL,
19 NULL, NULL, NULL, NULL, NULL
25 - for (i = 0; i < MAX_ACTION_FILES; i++)
26 + for (i = 0; i < MAX_AF_FILES; i++)
28 if (current_actions_file[i])
34 - for (i = 0; i < MAX_ACTION_FILES; i++)
35 + for (i = 0; i < MAX_AF_FILES; i++)
37 if (csp->config->actions_file[i])
39 diff -urNad privoxy~/cgiedit.c privoxy/cgiedit.c
40 --- privoxy~/cgiedit.c 2006-02-11 23:44:25.000000000 +0100
41 +++ privoxy/cgiedit.c 2006-02-11 23:44:37.000000000 +0100
46 - for (i = 0; i < MAX_ACTION_FILES; i++)
47 + for (i = 0; i < MAX_AF_FILES; i++)
49 if (((fl = csp->actions_list[i]) != NULL) && ((b = fl->f) != NULL))
52 struct file_line * cur_line;
55 - struct file_list *filter_file;
56 struct re_filterfile_spec *filter_group;
57 + int i, have_filters = 0;
59 if (0 == (csp->config->feature_flags & RUNTIME_FEATURE_CGI_EDIT_ACTIONS))
61 @@ -3008,10 +3008,15 @@
63 if (!err) err = actions_to_radio(exports, cur_line->data.action);
65 - filter_file = csp->rlist;
66 - filter_group = ((filter_file != NULL) ? filter_file->f : NULL);
68 - if (!err) err = map_conditional(exports, "any-filters-defined", (filter_group != NULL));
69 + for (i = 0; i < MAX_AF_FILES; i++)
71 + if ((csp->rlist[i] != NULL) && (csp->rlist[i]->f != NULL))
73 + if (!err) err = map_conditional(exports, "any-filters-defined", 1);
81 @@ -3020,10 +3025,8 @@
85 - if (filter_group == NULL)
87 + if (0 == have_filters)
88 err = map(exports, "filter-params", 1, "", 1);
92 /* We have some entries in the filter list */
93 @@ -3047,69 +3050,76 @@
97 - for (;(!err) && (filter_group != NULL); filter_group = filter_group->next)
98 + for (i = 0; i < MAX_AF_FILES; i++)
100 - char current_mode = 'x';
101 - struct list_entry *filter_name;
103 - struct map *line_exports;
106 - filter_name = cur_line->data.action->multi_add[ACTION_MULTI_FILTER]->first;
107 - while ((filter_name != NULL)
108 - && (0 != strcmp(filter_group->name, filter_name->str)))
110 - filter_name = filter_name->next;
113 - if (filter_name != NULL)
115 - current_mode = 'y';
118 + if ((csp->rlist[i] != NULL) && (csp->rlist[i]->f != NULL))
120 - filter_name = cur_line->data.action->multi_remove[ACTION_MULTI_FILTER]->first;
121 - while ((filter_name != NULL)
122 - && (0 != strcmp(filter_group->name, filter_name->str)))
124 - filter_name = filter_name->next;
126 - if (filter_name != NULL)
127 + filter_group = csp->rlist[i]->f;
128 + for (;(!err) && (filter_group != NULL); filter_group = filter_group->next)
130 - current_mode = 'n';
133 + char current_mode = 'x';
134 + struct list_entry *filter_name;
136 + struct map *line_exports;
139 - /* Generate a unique serial number */
140 - snprintf(number, sizeof(number), "%x", index++);
141 - number[sizeof(number) - 1] = '\0';
142 + filter_name = cur_line->data.action->multi_add[ACTION_MULTI_FILTER]->first;
143 + while ((filter_name != NULL)
144 + && (0 != strcmp(filter_group->name, filter_name->str)))
146 + filter_name = filter_name->next;
149 - line_exports = new_map();
150 - if (line_exports == NULL)
152 - err = JB_ERR_MEMORY;
157 - if (!err) err = map(line_exports, "index", 1, number, 1);
158 - if (!err) err = map(line_exports, "name", 1, filter_group->name, 1);
159 - if (!err) err = map(line_exports, "description", 1, filter_group->description, 1);
160 - if (!err) err = map_radio(line_exports, "this-filter", "ynx", current_mode);
161 + if (filter_name != NULL)
163 + current_mode = 'y';
167 + filter_name = cur_line->data.action->multi_remove[ACTION_MULTI_FILTER]->first;
168 + log_error(LOG_LEVEL_CGI, "cgiedit: filter_group->name: [%s]",filter_group->name);
169 + while ((filter_name != NULL)
170 + && (0 != strcmp(filter_group->name, filter_name->str)))
172 + filter_name = filter_name->next;
174 + if (filter_name != NULL)
176 + current_mode = 'n';
183 - this_line = strdup(filter_template);
184 - if (this_line == NULL) err = JB_ERR_MEMORY;
186 - if (!err) err = template_fill(&this_line, line_exports);
187 - string_join(&result, this_line);
188 + /* Generate a unique serial number */
189 + snprintf(number, sizeof(number), "%x", index++);
190 + number[sizeof(number) - 1] = '\0';
192 - free_map(line_exports);
193 + line_exports = new_map();
194 + if (line_exports == NULL)
196 + err = JB_ERR_MEMORY;
201 + if (!err) err = map(line_exports, "index", 1, number, 1);
202 + if (!err) err = map(line_exports, "name", 1, filter_group->name, 1);
203 + if (!err) err = map(line_exports, "description", 1, filter_group->description, 1);
204 + if (!err) err = map_radio(line_exports, "this-filter", "ynx", current_mode);
209 + this_line = strdup(filter_template);
210 + if (this_line == NULL) err = JB_ERR_MEMORY;
212 + if (!err) err = template_fill(&this_line, line_exports);
213 + string_join(&result, this_line);
215 + free_map(line_exports);
221 freez(filter_template);
224 @@ -3213,7 +3223,7 @@
225 get_string_param(parameters, "p", &action_set_name);
226 if (action_set_name != NULL)
228 - for (index = 0; index < MAX_ACTION_FILES; index++)
229 + for (index = 0; index < MAX_AF_FILES; index++)
231 if (((fl = csp->actions_list[index]) != NULL) && ((b = fl->f) != NULL))
233 diff -urNad privoxy~/cgisimple.c privoxy/cgisimple.c
234 --- privoxy~/cgisimple.c 2006-02-11 23:44:37.000000000 +0100
235 +++ privoxy/cgisimple.c 2006-02-11 23:44:37.000000000 +0100
237 switch (*(lookup(parameters, "file")))
240 - if (!get_number_param(csp, parameters, "index", &i) && i < MAX_ACTION_FILES && csp->actions_list[i])
241 + if (!get_number_param(csp, parameters, "index", &i) && i < MAX_AF_FILES && csp->actions_list[i])
243 filename = csp->actions_list[i]->filename;
244 file_description = "Actions File";
250 + if (!get_number_param(csp, parameters, "index", &i) && i < MAX_AF_FILES && csp->rlist[i])
252 - filename = csp->rlist->filename;
253 + filename = csp->rlist[i]->filename;
254 file_description = "Filter File";
258 * FIXME: Shouldn't include hardwired HTML here, use line template instead!
261 - for (i = 0; i < MAX_ACTION_FILES; i++)
262 + for (i = 0; i < MAX_AF_FILES; i++)
264 if (((fl = csp->actions_list[i]) != NULL) && ((b = fl->f) != NULL))
266 @@ -983,13 +983,29 @@
267 if (!err) err = map(exports, "actions-filenames", 1, "<tr><td>None specified</td></tr>", 1);
272 + * List all re_filterfiles in use, together with view options.
273 + * FIXME: Shouldn't include hardwired HTML here, use line template instead!
276 + for (i = 0; i < MAX_AF_FILES; i++)
278 - if (!err) err = map(exports, "re-filter-filename", 1, html_encode(csp->rlist->filename), 0);
279 + if (((fl = csp->rlist[i]) != NULL) && ((b = fl->f) != NULL))
281 + if (!err) err = string_append(&s, "<tr><td>");
282 + if (!err) err = string_join(&s, html_encode(csp->rlist[i]->filename));
283 + snprintf(buf, 100, "</td><td class=\"buttons\"><a href=\"/show-status?file=filter&index=%d\">View</a>", i);
284 + if (!err) err = string_append(&s, buf);
285 + if (!err) err = string_append(&s, "</td></tr>\n");
290 + if (!err) err = map(exports, "re-filter-filename", 1, s, 0);
294 - if (!err) err = map(exports, "re-filter-filename", 1, "None specified", 1);
295 + if (!err) err = map(exports, "re-filter-filename", 1, "<tr><td>None specified</td></tr>", 1);
296 if (!err) err = map_block_killer(exports, "have-filterfile");
299 @@ -1206,7 +1222,7 @@
301 matches = strdup("<table class=\"transparent\">");
303 - for (i = 0; i < MAX_ACTION_FILES; i++)
304 + for (i = 0; i < MAX_AF_FILES; i++)
306 if (NULL == csp->config->actions_file_short[i]
307 || !strcmp(csp->config->actions_file_short[i], "standard")) continue;
308 diff -urNad privoxy~/config privoxy/config
309 --- privoxy~/config 2006-02-11 23:44:37.000000000 +0100
310 +++ privoxy/config 2006-02-11 23:44:37.000000000 +0100
315 -# The filter file to use
316 +# The filter file(s) to use
320 @@ -199,21 +199,23 @@
324 -# The filter file contains content modification rules that use
325 +# The filter files contain content modification rules that use
326 # regular expressions. These rules permit powerful changes on the
327 # content of Web pages, e.g., you could disable your favorite
328 # JavaScript annoyances, re-write the actual displayed text,
329 -# or just have some fun replacing "Microsoft" with "MicroSuck"
330 -# wherever it appears on a Web page.
331 +# or just have some fun playing buzzword bingo with a web page.
333 # The +filter{name} actions rely on the relevant filter (name)
334 -# to be defined in the filter file!
335 +# to be defined in a filter file!
337 # A pre-defined filter file called default.filter that contains
338 # a bunch of handy filters for common problems is included in the
339 # distribution. See the section on the filter action for a list.
341 +# When adding your own, it is recommended you add them to the
344 filterfile default.filter
345 +#filterfile user.filter
349 diff -urNad privoxy~/filters.c privoxy/filters.c
350 --- privoxy~/filters.c 2006-02-11 23:44:25.000000000 +0100
351 +++ privoxy/filters.c 2006-02-11 23:44:37.000000000 +0100
352 @@ -1290,6 +1290,8 @@
353 struct re_filterfile_spec *b;
354 struct list_entry *filtername;
356 + int i, found_filters = 0;
361 @@ -1299,10 +1301,26 @@
363 size = csp->iob->eod - csp->iob->cur;
365 - if ( ( NULL == (fl = csp->rlist) ) || ( NULL == fl->f) )
367 + * Need to check the set of re_filterfiles...
369 + for (i = 0; i < MAX_AF_FILES; i++)
371 + fl = csp->rlist[i];
382 + if (0 == found_filters)
384 log_error(LOG_LEVEL_ERROR, "Unable to get current state of regexp filtering.");
390 @@ -1320,6 +1338,11 @@
391 csp->flags |= CSP_FLAG_MODIFIED;
394 + for (i = 0; i < MAX_AF_FILES; i++)
396 + fl = csp->rlist[i];
397 + if ((NULL == fl) || (NULL == fl->f))
400 * For all applying +filter actions, look if a filter by that
401 * name exists and if yes, execute it's pcrs_joblist on the
402 @@ -1356,6 +1379,7 @@
409 * If there were no hits, destroy our copy and let
410 @@ -1536,7 +1560,7 @@
412 init_current_action(csp->action);
414 - for (i = 0; i < MAX_ACTION_FILES; i++)
415 + for (i = 0; i < MAX_AF_FILES; i++)
417 if (((fl = csp->actions_list[i]) == NULL) || ((b = fl->f) == NULL))
419 diff -urNad privoxy~/loadcfg.c privoxy/loadcfg.c
420 --- privoxy~/loadcfg.c 2006-02-11 23:44:37.000000000 +0100
421 +++ privoxy/loadcfg.c 2006-02-11 23:44:37.000000000 +0100
423 * - savearg now embeds option names in help links
425 * Revision 1.45 2002/04/24 02:11:54 oes
426 - * Jon's multiple AF patch: Allow up to MAX_ACTION_FILES actionsfile options
427 + * Jon's multiple AF patch: Allow up to MAX_AF_FILES actionsfile options
429 * Revision 1.44 2002/04/08 20:37:13 swa
432 freez(config->haddr);
433 freez(config->logfile);
435 - for (i = 0; i < MAX_ACTION_FILES; i++)
436 + for (i = 0; i < MAX_AF_FILES; i++)
438 freez(config->actions_file_short[i]);
439 freez(config->actions_file[i]);
441 list_remove_all(config->trust_info);
442 #endif /* def FEATURE_TRUST */
444 - freez(config->re_filterfile);
445 + for (i = 0; i < MAX_AF_FILES; i++)
447 + freez(config->re_filterfile[i]);
453 @@ -694,16 +698,16 @@
454 * *************************************************************************/
455 case hash_actions_file :
457 - while ((i < MAX_ACTION_FILES) && (NULL != config->actions_file[i]))
458 + while ((i < MAX_AF_FILES) && (NULL != config->actions_file[i]))
463 - if (i >= MAX_ACTION_FILES)
464 + if (i >= MAX_AF_FILES)
466 log_error(LOG_LEVEL_FATAL, "Too many 'actionsfile' directives in config file - limit is %d.\n"
467 - "(You can increase this limit by changing MAX_ACTION_FILES in project.h and recompiling).",
469 + "(You can increase this limit by changing MAX_AF_FILES in project.h and recompiling).",
472 config->actions_file_short[i] = strdup(arg);
473 p = malloc(strlen(arg) + sizeof(".action"));
474 @@ -860,15 +864,27 @@
475 * In confdir by default.
476 * *************************************************************************/
477 case hash_filterfile :
478 - if(config->re_filterfile)
480 + while ((i < MAX_AF_FILES) && (NULL != config->re_filterfile[i]))
482 - log_error(LOG_LEVEL_ERROR, "Ignoring extraneous directive 'filterfile %s' "
483 - "in line %lu in configuration file (%s).", arg, linenum, configfile);
484 - string_append(&config->proxy_args,
485 - " <b><font color=\"red\">WARNING: extraneous directive, ignored</font></b>");
489 - config->re_filterfile = make_path(config->confdir, arg);
491 + if (i >= MAX_AF_FILES)
493 + log_error(LOG_LEVEL_FATAL, "Too many 'filterfile' directives in config file - limit is %d.\n"
494 + "(You can increase this limit by changing MAX_AF_FILES in project.h and recompiling).",
497 + config->re_filterfile_short[i] = strdup(arg);
498 + p = malloc(strlen(arg));
501 + log_error(LOG_LEVEL_FATAL, "Out of memory");
504 + config->re_filterfile[i] = make_path(config->confdir, p);
508 /* *************************************************************************
509 diff -urNad privoxy~/loaders.c privoxy/loaders.c
510 --- privoxy~/loaders.c 2006-02-11 23:44:25.000000000 +0100
511 +++ privoxy/loaders.c 2006-02-11 23:44:37.000000000 +0100
513 static struct file_list *current_trustfile = NULL;
514 #endif /* def FEATURE_TRUST */
516 -static struct file_list *current_re_filterfile = NULL;
517 +static int load_one_re_filterfile(struct client_state *csp, int fileid);
519 +static struct file_list *current_re_filterfile[MAX_AF_FILES] = {
520 + NULL, NULL, NULL, NULL, NULL,
521 + NULL, NULL, NULL, NULL, NULL
530 - for (i = 0; i < MAX_ACTION_FILES; i++)
531 + for (i = 0; i < MAX_AF_FILES; i++)
533 if (csp->actions_list[i])
535 @@ -397,11 +402,14 @@
543 + for (i = 0; i < MAX_AF_FILES; i++)
545 - csp->rlist->active = 1;
548 + csp->rlist[i]->active = 1;
553 @@ -1247,10 +1255,15 @@
554 *********************************************************************/
555 void unload_current_re_filterfile(void)
557 - if (current_re_filterfile)
560 + for (i = 0; i < MAX_AF_FILES; i++)
562 - current_re_filterfile->unloader = unload_re_filterfile;
563 - current_re_filterfile = NULL;
564 + if (current_re_filterfile[i])
566 + current_re_filterfile[i]->unloader = unload_re_filterfile;
567 + current_re_filterfile[i] = NULL;
572 @@ -1273,6 +1286,46 @@
573 *********************************************************************/
574 int load_re_filterfile(struct client_state *csp)
579 + for (i = 0; i < MAX_AF_FILES; i++)
581 + if (csp->config->re_filterfile[i])
583 + result = load_one_re_filterfile(csp, i);
589 + else if (current_re_filterfile[i])
591 + current_re_filterfile[i]->unloader = unload_re_filterfile;
592 + current_re_filterfile[i] = NULL;
599 +/*********************************************************************
601 + * Function : load_one_re_filterfile
603 + * Description : Load a re_filterfile.
604 + * Generate a chained list of re_filterfile_spec's from
605 + * the "FILTER: " blocks, compiling all their substitutions
606 + * into chained lists of pcrs_job structs.
609 + * 1 : csp = Current client state (buffers, headers, etc...)
611 + * Returns : 0 => Ok, everything else is an error.
613 + *********************************************************************/
614 +int load_one_re_filterfile(struct client_state *csp, int fileid)
618 struct re_filterfile_spec *new_bl, *bl = NULL;
619 @@ -1286,11 +1339,12 @@
621 * No need to reload if unchanged
623 - if (!check_file_changed(current_re_filterfile, csp->config->re_filterfile, &fs))
624 + log_error(LOG_LEVEL_RE_FILTER, "load_one_re_filterfile: checking: %s\n",csp->config->re_filterfile[fileid]);
625 + if (!check_file_changed(current_re_filterfile[fileid], csp->config->re_filterfile[fileid], &fs))
629 - csp->rlist = current_re_filterfile;
630 + csp->rlist[fileid] = current_re_filterfile[fileid];
634 @@ -1302,7 +1356,7 @@
636 * Open the file or fail
638 - if ((fp = fopen(csp->config->re_filterfile, "r")) == NULL)
639 + if ((fp = fopen(csp->config->re_filterfile[fileid], "r")) == NULL)
641 goto load_re_filterfile_error;
643 @@ -1397,9 +1451,9 @@
645 * Schedule the now-obsolete old data for unloading
647 - if ( NULL != current_re_filterfile )
648 + if ( NULL != current_re_filterfile[fileid] )
650 - current_re_filterfile->unloader = unload_re_filterfile;
651 + current_re_filterfile[fileid]->unloader = unload_re_filterfile;
655 @@ -1407,18 +1461,18 @@
657 fs->next = files->next;
659 - current_re_filterfile = fs;
660 + current_re_filterfile[fileid] = fs;
665 + csp->rlist[fileid] = fs;
670 load_re_filterfile_error:
671 log_error(LOG_LEVEL_FATAL, "can't load re_filterfile '%s': %E",
672 - csp->config->re_filterfile);
673 + csp->config->re_filterfile[fileid]);
677 diff -urNad privoxy~/project.h privoxy/project.h
678 --- privoxy~/project.h 2006-02-11 23:44:25.000000000 +0100
679 +++ privoxy/project.h 2006-02-11 23:44:37.000000000 +0100
680 @@ -1010,10 +1010,10 @@
681 #define RC_FLAG_BLOCKED 0x20
684 - * Maximum number of actions files. This limit is arbitrary - it's just used
685 + * Maximum number of actions/filter files. This limit is arbitrary - it's just used
688 -#define MAX_ACTION_FILES 10
689 +#define MAX_AF_FILES 10
692 * The state of a Privoxy processing thread.
693 @@ -1069,10 +1069,10 @@
696 /** Actions files associated with this client */
697 - struct file_list *actions_list[MAX_ACTION_FILES];
698 + struct file_list *actions_list[MAX_AF_FILES];
700 - /** pcrs job file. */
701 - struct file_list *rlist;
702 + /** pcrs job files. */
703 + struct file_list *rlist[MAX_AF_FILES];
705 /** Length after content modification. */
706 size_t content_length;
707 @@ -1328,10 +1328,10 @@
710 /** The full paths to the actions files. */
711 - const char *actions_file[MAX_ACTION_FILES];
712 + const char *actions_file[MAX_AF_FILES];
714 /** The short names of the actions files. */
715 - const char *actions_file_short[MAX_ACTION_FILES];
716 + const char *actions_file_short[MAX_AF_FILES];
718 /** The administrator's email address */
720 @@ -1342,8 +1342,11 @@
721 /** URL to the user manual (on our website or local copy) */
724 - /** The file name of the pcre filter file */
725 - const char *re_filterfile;
726 + /** The file names of the pcre filter files. */
727 + const char *re_filterfile[MAX_AF_FILES];
729 + /** The short names of the pcre filter files. */
730 + const char *re_filterfile_short[MAX_AF_FILES];
732 #ifdef FEATURE_COOKIE_JAR
734 diff -urNad privoxy~/templates/show-status privoxy/templates/show-status
735 --- privoxy~/templates/show-status 2006-02-11 23:44:25.000000000 +0100
736 +++ privoxy/templates/show-status 2006-02-11 23:44:37.000000000 +0100
737 @@ -149,17 +149,12 @@
741 - <th colspan="2"><a href="@user-manual@filter-file.html">Filter File:</a></th>
742 + <th colspan="2"><a href="@user-manual@filter-file.html">Filter Files:</a></th>
748 - <td class="buttons">
749 - <!-- @if-have-filterfile-start -->
750 - <a href="show-status?file=filter">View</a>
751 - <!-- if-have-filterfile-end@ -->
754 <!-- @if-trust-support-start -->