b926bcaed027a5abe6c58a1529e3740f74561466
[privoxy.git] / debian / patches / 12_multiple-filters.dpatch
1 #! /bin/sh /usr/share/dpatch/dpatch-run
2 ## 12_multiple-filters.dpatch 
3 ## by David Schmidt <david__schmidt@users.sourceforge.net>
4 ##
5 ## All lines beginning with `## DP:' are a description of the patch.
6 ## DP: Multiple filter file support
7
8 @DPATCH@
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
12 @@ -871,7 +871,7 @@
13  }
14  
15  
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
20  };
21 @@ -894,7 +894,7 @@
22  {
23     int i;
24  
25 -   for (i = 0; i < MAX_ACTION_FILES; i++)
26 +   for (i = 0; i < MAX_AF_FILES; i++)
27     {
28        if (current_actions_file[i])
29        {
30 @@ -979,7 +979,7 @@
31     int i;
32     int result;
33  
34 -   for (i = 0; i < MAX_ACTION_FILES; i++)
35 +   for (i = 0; i < MAX_AF_FILES; i++)
36     {
37        if (csp->config->actions_file[i])
38        {
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
42 @@ -2560,7 +2560,7 @@
43        }
44  
45        buttons = strdup("");
46 -      for (i = 0; i < MAX_ACTION_FILES; i++)
47 +      for (i = 0; i < MAX_AF_FILES; i++)
48        {
49           if (((fl = csp->actions_list[i]) != NULL) && ((b = fl->f) != NULL))
50           {
51 @@ -2958,8 +2958,8 @@
52     struct file_line * cur_line;
53     unsigned line_number;
54     jb_err err;
55 -   struct file_list *filter_file;
56     struct re_filterfile_spec *filter_group;
57 +   int i, have_filters = 0;
58  
59     if (0 == (csp->config->feature_flags & RUNTIME_FEATURE_CGI_EDIT_ACTIONS))
60     {
61 @@ -3008,10 +3008,15 @@
62  
63     if (!err) err = actions_to_radio(exports, cur_line->data.action);
64  
65 -   filter_file = csp->rlist;
66 -   filter_group = ((filter_file != NULL) ? filter_file->f : NULL);
67 -
68 -   if (!err) err = map_conditional(exports, "any-filters-defined", (filter_group != NULL));
69 +   for (i = 0; i < MAX_AF_FILES; i++)
70 +   {
71 +      if ((csp->rlist[i] != NULL) && (csp->rlist[i]->f != NULL))
72 +      {
73 +         if (!err) err = map_conditional(exports, "any-filters-defined", 1);
74 +         have_filters = 1;
75 +         break;
76 +      }
77 +   }
78  
79     if (err)
80     {
81 @@ -3020,10 +3025,8 @@
82        return err;
83     }
84  
85 -   if (filter_group == NULL)
86 -   {
87 +   if (0 == have_filters)
88        err = map(exports, "filter-params", 1, "", 1);
89 -   }
90     else
91     {
92        /* We have some entries in the filter list */
93 @@ -3047,69 +3050,76 @@
94  
95        result = strdup("");
96  
97 -      for (;(!err) && (filter_group != NULL); filter_group = filter_group->next)
98 +      for (i = 0; i < MAX_AF_FILES; i++)
99        {
100 -         char current_mode = 'x';
101 -         struct list_entry *filter_name;
102 -         char * this_line;
103 -         struct map *line_exports;
104 -         char number[20];
105 -
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)))
109 -         {
110 -              filter_name = filter_name->next;
111 -         }
112 -
113 -         if (filter_name != NULL)
114 -         {
115 -            current_mode = 'y';
116 -         }
117 -         else
118 +         if ((csp->rlist[i] != NULL) && (csp->rlist[i]->f != NULL))
119           {
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)))
123 -            {
124 -                 filter_name = filter_name->next;
125 -            }
126 -            if (filter_name != NULL)
127 +            filter_group = csp->rlist[i]->f;
128 +            for (;(!err) && (filter_group != NULL); filter_group = filter_group->next)
129              {
130 -               current_mode = 'n';
131 -            }
132 -         }
133 +               char current_mode = 'x';
134 +               struct list_entry *filter_name;
135 +               char * this_line;
136 +               struct map *line_exports;
137 +               char number[20];
138  
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)))
145 +               {
146 +                    filter_name = filter_name->next;
147 +               }
148  
149 -         line_exports = new_map();
150 -         if (line_exports == NULL)
151 -         {
152 -            err = JB_ERR_MEMORY;
153 -            freez(result);
154 -         }
155 -         else
156 -         {
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)
162 +               {
163 +                  current_mode = 'y';
164 +               }
165 +               else
166 +               {
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)))
171 +                  {
172 +                       filter_name = filter_name->next;
173 +                  }
174 +                  if (filter_name != NULL)
175 +                  {
176 +                     current_mode = 'n';
177 +                  }
178 +               }
179  
180 -            this_line = NULL;
181 -            if (!err)
182 -            {
183 -               this_line = strdup(filter_template);
184 -               if (this_line == NULL) err = JB_ERR_MEMORY;
185 -            }
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';
191  
192 -            free_map(line_exports);
193 +               line_exports = new_map();
194 +               if (line_exports == NULL)
195 +               {
196 +                  err = JB_ERR_MEMORY;
197 +                  freez(result);
198 +               }
199 +               else
200 +               {
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);
205 +
206 +                  this_line = NULL;
207 +                  if (!err)
208 +                  {
209 +                     this_line = strdup(filter_template);
210 +                     if (this_line == NULL) err = JB_ERR_MEMORY;
211 +                  }
212 +                  if (!err) err = template_fill(&this_line, line_exports);
213 +                  string_join(&result, this_line);
214 +
215 +                  free_map(line_exports);
216 +               }
217 +            }
218           }
219        }
220 -
221        freez(filter_template);
222  
223        if (!err)
224 @@ -3213,7 +3223,7 @@
225     get_string_param(parameters, "p", &action_set_name);
226     if (action_set_name != NULL)
227     {
228 -      for (index = 0; index < MAX_ACTION_FILES; index++)
229 +      for (index = 0; index < MAX_AF_FILES; index++)
230        {
231           if (((fl = csp->actions_list[index]) != NULL) && ((b = fl->f) != NULL))
232           {
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
236 @@ -829,7 +829,7 @@
237     switch (*(lookup(parameters, "file")))
238     {
239     case 'a':
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])
242        {
243           filename = csp->actions_list[i]->filename;
244           file_description = "Actions File";
245 @@ -837,9 +837,9 @@
246        break;
247  
248     case 'f':
249 -      if (csp->rlist)
250 +      if (!get_number_param(csp, parameters, "index", &i) && i < MAX_AF_FILES && csp->rlist[i])
251        {
252 -         filename = csp->rlist->filename;
253 +         filename = csp->rlist[i]->filename;
254           file_description = "Filter File";
255        }
256        break;
257 @@ -954,7 +954,7 @@
258      * FIXME: Shouldn't include hardwired HTML here, use line template instead!
259      */
260     s = strdup("");
261 -   for (i = 0; i < MAX_ACTION_FILES; i++)
262 +   for (i = 0; i < MAX_AF_FILES; i++)
263     {
264        if (((fl = csp->actions_list[i]) != NULL) && ((b = fl->f) != NULL))
265        {
266 @@ -983,13 +983,29 @@
267        if (!err) err = map(exports, "actions-filenames", 1, "<tr><td>None specified</td></tr>", 1);
268     }
269  
270 -   if (csp->rlist)
271 +   /* 
272 +    * List all re_filterfiles in use, together with view options.
273 +    * FIXME: Shouldn't include hardwired HTML here, use line template instead!
274 +    */
275 +   s = strdup("");
276 +   for (i = 0; i < MAX_AF_FILES; i++)
277     {
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))
280 +      {
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");
286 +      }
287 +   }
288 +   if (*s != '\0')   
289 +   {
290 +      if (!err) err = map(exports, "re-filter-filename", 1, s, 0);
291     }
292     else
293     {
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");
297     }
298  
299 @@ -1206,7 +1222,7 @@
300  
301        matches = strdup("<table class=\"transparent\">");
302  
303 -      for (i = 0; i < MAX_ACTION_FILES; i++)
304 +      for (i = 0; i < MAX_AF_FILES; i++)
305        {
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
311 @@ -182,7 +182,7 @@
312  #  
313  #  Specifies:
314  #  
315 -#      The filter file to use
316 +#      The filter file(s) to use
317  #  
318  #  Type of value:
319  #  
320 @@ -199,21 +199,23 @@
321  #  
322  #  Notes:
323  #  
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.
332  #  
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!
336  #  
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.
340 -#  
341 +#      When adding your own, it is recommended you add them to the
342 +#      user.filter file.
343 +#
344  filterfile default.filter
345 +#filterfile user.filter
346  
347  #  
348  #  1.5. logfile
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;
355  
356 +   int i, found_filters = 0;
357 +
358     /* 
359      * Sanity first
360      */
361 @@ -1299,10 +1301,26 @@
362     }
363     size = csp->iob->eod - csp->iob->cur;
364  
365 -   if ( ( NULL == (fl = csp->rlist) ) || ( NULL == fl->f) )
366 +   /*
367 +    * Need to check the set of re_filterfiles...
368 +    */
369 +   for (i = 0; i < MAX_AF_FILES; i++)
370 +   {
371 +      fl = csp->rlist[i];
372 +      if (NULL != fl)
373 +      {
374 +         if (NULL != fl->f)
375 +         {
376 +           found_filters = 1;
377 +           break;
378 +         }
379 +      }
380 +   }
381 +
382 +   if (0 == found_filters)
383     {
384        log_error(LOG_LEVEL_ERROR, "Unable to get current state of regexp filtering.");
385 -      return(NULL);
386 +         return(NULL);
387     }
388  
389     /*
390 @@ -1320,6 +1338,11 @@
391        csp->flags |= CSP_FLAG_MODIFIED;
392     }
393  
394 +   for (i = 0; i < MAX_AF_FILES; i++)
395 +   {
396 +     fl = csp->rlist[i];
397 +     if ((NULL == fl) || (NULL == fl->f))
398 +       break;
399     /*
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 @@
403           }
404        }
405     }
406 +   }
407  
408     /*
409      * If there were no hits, destroy our copy and let
410 @@ -1536,7 +1560,7 @@
411  
412     init_current_action(csp->action);
413  
414 -   for (i = 0; i < MAX_ACTION_FILES; i++)
415 +   for (i = 0; i < MAX_AF_FILES; i++)
416     {
417        if (((fl = csp->actions_list[i]) == NULL) || ((b = fl->f) == NULL))
418        {
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
422 @@ -65,7 +65,7 @@
423   *     - savearg now embeds option names in help links
424   *
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
428   *
429   *    Revision 1.44  2002/04/08 20:37:13  swa
430   *    fixed JB spelling
431 @@ -510,7 +510,7 @@
432     freez(config->haddr);
433     freez(config->logfile);
434  
435 -   for (i = 0; i < MAX_ACTION_FILES; i++)
436 +   for (i = 0; i < MAX_AF_FILES; i++)
437     {
438        freez(config->actions_file_short[i]);
439        freez(config->actions_file[i]);
440 @@ -530,7 +530,11 @@
441     list_remove_all(config->trust_info);
442  #endif /* def FEATURE_TRUST */
443  
444 -   freez(config->re_filterfile);
445 +   for (i = 0; i < MAX_AF_FILES; i++)
446 +   {
447 +      freez(config->re_filterfile[i]);
448 +   }
449 +
450     freez(config);
451  }
452  
453 @@ -694,16 +698,16 @@
454   * *************************************************************************/
455           case hash_actions_file :
456              i = 0;
457 -            while ((i < MAX_ACTION_FILES) && (NULL != config->actions_file[i]))
458 +            while ((i < MAX_AF_FILES) && (NULL != config->actions_file[i]))
459              {
460                 i++;
461              }
462  
463 -            if (i >= MAX_ACTION_FILES)
464 +            if (i >= MAX_AF_FILES)
465              {
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).",
468 -                  MAX_ACTION_FILES);
469 +                  "(You can increase this limit by changing MAX_AF_FILES in project.h and recompiling).",
470 +                  MAX_AF_FILES);
471              }
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)
479 +            i = 0;
480 +            while ((i < MAX_AF_FILES) && (NULL != config->re_filterfile[i]))
481              {
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>");
486 -               continue;
487 +               i++;
488              }
489 -            config->re_filterfile = make_path(config->confdir, arg);
490 +
491 +            if (i >= MAX_AF_FILES)
492 +            {
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).",
495 +                  MAX_AF_FILES);
496 +            }
497 +            config->re_filterfile_short[i] = strdup(arg);
498 +            p = malloc(strlen(arg));
499 +            if (p == NULL)
500 +            {
501 +               log_error(LOG_LEVEL_FATAL, "Out of memory");
502 +            }
503 +            strcpy(p, arg);
504 +            config->re_filterfile[i] = make_path(config->confdir, p);
505 +            free(p);
506              continue;
507  
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
512 @@ -329,7 +329,12 @@
513  static struct file_list *current_trustfile      = NULL;
514  #endif /* def FEATURE_TRUST */
515  
516 -static struct file_list *current_re_filterfile  = NULL;
517 +static int load_one_re_filterfile(struct client_state *csp, int fileid);
518 +
519 +static struct file_list *current_re_filterfile[MAX_AF_FILES]  = {
520 +   NULL, NULL, NULL, NULL, NULL,
521 +   NULL, NULL, NULL, NULL, NULL
522 +};
523  
524  
525  
526 @@ -388,7 +393,7 @@
527           /* 
528            * Actions files
529            */
530 -         for (i = 0; i < MAX_ACTION_FILES; i++)
531 +         for (i = 0; i < MAX_AF_FILES; i++)
532           {
533              if (csp->actions_list[i])     
534              {
535 @@ -397,11 +402,14 @@
536           }
537  
538           /*
539 -          * Filter file
540 +          * Filter files
541            */
542 -         if (csp->rlist)
543 +         for (i = 0; i < MAX_AF_FILES; i++)
544           {
545 -            csp->rlist->active = 1;
546 +            if (csp->rlist[i])     
547 +            {
548 +               csp->rlist[i]->active = 1;
549 +            }
550           }
551  
552           /*
553 @@ -1247,10 +1255,15 @@
554   *********************************************************************/
555  void unload_current_re_filterfile(void)
556  {
557 -   if (current_re_filterfile)
558 +   int i;
559 +
560 +   for (i = 0; i < MAX_AF_FILES; i++)
561     {
562 -      current_re_filterfile->unloader = unload_re_filterfile;
563 -      current_re_filterfile = NULL;
564 +      if (current_re_filterfile[i])
565 +      {
566 +         current_re_filterfile[i]->unloader = unload_re_filterfile;
567 +         current_re_filterfile[i] = NULL;
568 +      }
569     }
570  }
571  #endif
572 @@ -1273,6 +1286,46 @@
573   *********************************************************************/
574  int load_re_filterfile(struct client_state *csp)
575  {
576 +   int i;
577 +   int result;
578 +
579 +   for (i = 0; i < MAX_AF_FILES; i++)
580 +   {
581 +      if (csp->config->re_filterfile[i])
582 +      {
583 +         result = load_one_re_filterfile(csp, i);
584 +         if (result)
585 +         {
586 +            return result;
587 +         }
588 +      }
589 +      else if (current_re_filterfile[i])
590 +      {
591 +         current_re_filterfile[i]->unloader = unload_re_filterfile;
592 +         current_re_filterfile[i] = NULL;
593 +      }
594 +   }
595 +
596 +   return 0;
597 +}
598 +
599 +/*********************************************************************
600 + *
601 + * Function    :  load_one_re_filterfile
602 + *
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.
607 + *
608 + * Parameters  :
609 + *          1  :  csp = Current client state (buffers, headers, etc...)
610 + *
611 + * Returns     :  0 => Ok, everything else is an error.
612 + *
613 + *********************************************************************/
614 +int load_one_re_filterfile(struct client_state *csp, int fileid)
615 +{
616     FILE *fp;
617  
618     struct re_filterfile_spec *new_bl, *bl = NULL;
619 @@ -1286,11 +1339,12 @@
620     /*
621      * No need to reload if unchanged
622      */
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))
626     {
627        if (csp)
628        {
629 -         csp->rlist = current_re_filterfile;
630 +         csp->rlist[fileid] = current_re_filterfile[fileid];
631        }
632        return(0);
633     }
634 @@ -1302,7 +1356,7 @@
635     /* 
636      * Open the file or fail
637      */
638 -   if ((fp = fopen(csp->config->re_filterfile, "r")) == NULL)
639 +   if ((fp = fopen(csp->config->re_filterfile[fileid], "r")) == NULL)
640     {
641        goto load_re_filterfile_error;
642     }
643 @@ -1397,9 +1451,9 @@
644     /* 
645      * Schedule the now-obsolete old data for unloading
646      */
647 -   if ( NULL != current_re_filterfile )
648 +   if ( NULL != current_re_filterfile[fileid] )
649     {
650 -      current_re_filterfile->unloader = unload_re_filterfile;
651 +      current_re_filterfile[fileid]->unloader = unload_re_filterfile;
652     }
653  
654     /*
655 @@ -1407,18 +1461,18 @@
656      */
657     fs->next    = files->next;
658     files->next = fs;
659 -   current_re_filterfile = fs;
660 +   current_re_filterfile[fileid] = fs;
661  
662     if (csp)
663     {
664 -      csp->rlist = fs;
665 +      csp->rlist[fileid] = fs;
666     }
667  
668     return( 0 );
669  
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]);
674     return(-1);
675  
676  }
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
682  
683  /**
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
686   * to size an array.
687   */
688 -#define MAX_ACTION_FILES 10
689 +#define MAX_AF_FILES 10
690  
691  /**
692   * The state of a Privoxy processing thread.
693 @@ -1069,10 +1069,10 @@
694     char   *x_forwarded;
695  
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];
699  
700 -   /** pcrs job file. */
701 -   struct file_list *rlist;
702 +   /** pcrs job files. */
703 +   struct file_list *rlist[MAX_AF_FILES];
704  
705     /** Length after content modification. */
706     size_t content_length;
707 @@ -1328,10 +1328,10 @@
708     const char *logdir;
709  
710     /** The full paths to the actions files. */
711 -   const char *actions_file[MAX_ACTION_FILES];
712 +   const char *actions_file[MAX_AF_FILES];
713  
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];
717  
718     /** The administrator's email address */
719     char *admin_address;
720 @@ -1342,8 +1342,11 @@
721     /** URL to the user manual (on our website or local copy) */
722     char *usermanual;
723  
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];
728 +
729 +   /** The short names of the pcre filter files. */
730 +   const char *re_filterfile_short[MAX_AF_FILES];
731  
732  #ifdef FEATURE_COOKIE_JAR
733  
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 @@
738              </tr>
739                @actions-filenames@
740             <tr>
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>
743             </tr>
744             <tr>
745               <td>
746                 @re-filter-filename@
747               </td>
748 -             <td class="buttons">
749 -               <!-- @if-have-filterfile-start -->
750 -               <a href="show-status?file=filter">View</a>
751 -               <!-- if-have-filterfile-end@ -->
752 -             </td>
753             </tr>
754  <!-- @if-trust-support-start -->
755             <tr>