merge Debian changes from 3.0.7 to 3.0.10
[privoxy.git] / loaders.c
1 const char loaders_rcs[] = "$Id: loaders.c,v 1.67 2008/03/30 14:52:08 fabiankeil Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/loaders.c,v $
5  *
6  * Purpose     :  Functions to load and unload the various
7  *                configuration files.  Also contains code to manage
8  *                the list of active loaders, and to automatically
9  *                unload files that are no longer in use.
10  *
11  * Copyright   :  Written by and Copyright (C) 2001-2007 the SourceForge
12  *                Privoxy team. http://www.privoxy.org/
13  *
14  *                Based on the Internet Junkbuster originally written
15  *                by and Copyright (C) 1997 Anonymous Coders and
16  *                Junkbusters Corporation.  http://www.junkbusters.com
17  *
18  *                This program is free software; you can redistribute it
19  *                and/or modify it under the terms of the GNU General
20  *                Public License as published by the Free Software
21  *                Foundation; either version 2 of the License, or (at
22  *                your option) any later version.
23  *
24  *                This program is distributed in the hope that it will
25  *                be useful, but WITHOUT ANY WARRANTY; without even the
26  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
27  *                PARTICULAR PURPOSE.  See the GNU General Public
28  *                License for more details.
29  *
30  *                The GNU General Public License should be included with
31  *                this file.  If not, you can view it at
32  *                http://www.gnu.org/copyleft/gpl.html
33  *                or write to the Free Software Foundation, Inc., 59
34  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
35  *
36  * Revisions   :
37  *    $Log: loaders.c,v $
38  *    Revision 1.67  2008/03/30 14:52:08  fabiankeil
39  *    Rename load_actions_file() and load_re_filterfile()
40  *    as they load multiple files "now".
41  *
42  *    Revision 1.66  2008/03/21 11:16:30  fabiankeil
43  *    Garbage-collect csp->my_ip_addr_str and csp->my_hostname.
44  *
45  *    Revision 1.65  2007/12/07 18:29:23  fabiankeil
46  *    Remove now-obsolete csp member x_forwarded.
47  *
48  *    Revision 1.64  2007/06/01 14:12:38  fabiankeil
49  *    Add unload_forward_spec() in preparation for forward-override{}.
50  *
51  *    Revision 1.63  2007/05/14 10:41:15  fabiankeil
52  *    Ditch the csp member cookie_list[] which isn't used anymore.
53  *
54  *    Revision 1.62  2007/04/30 15:02:18  fabiankeil
55  *    Introduce dynamic pcrs jobs that can resolve variables.
56  *
57  *    Revision 1.61  2007/04/15 16:39:21  fabiankeil
58  *    Introduce tags as alternative way to specify which
59  *    actions apply to a request. At the moment tags can be
60  *    created based on client and server headers.
61  *
62  *    Revision 1.60  2007/03/20 15:16:34  fabiankeil
63  *    Use dedicated header filter actions instead of abusing "filter".
64  *    Replace "filter-client-headers" and "filter-client-headers"
65  *    with "server-header-filter" and "client-header-filter".
66  *
67  *    Revision 1.59  2007/01/25 13:38:20  fabiankeil
68  *    Freez csp->error_message in sweep().
69  *
70  *    Revision 1.58  2006/12/31 14:25:20  fabiankeil
71  *    Fix gcc43 compiler warnings.
72  *
73  *    Revision 1.57  2006/12/21 12:22:22  fabiankeil
74  *    html_encode filter descriptions.
75  *
76  *    Have "Ignoring job ..." error messages
77  *    print the filter file name correctly.
78  *
79  *    Revision 1.56  2006/09/07 10:40:30  fabiankeil
80  *    Turns out trusted referrers above our arbitrary
81  *    limit are downgraded too ordinary trusted URLs.
82  *    Adjusted error message.
83  *
84  *    Revision 1.55  2006/09/07 10:25:39  fabiankeil
85  *    Fix typo.
86  *
87  *    Revision 1.54  2006/09/07 10:22:20  fabiankeil
88  *    If too many trusted referrers are used,
89  *    print only one error message instead of logging
90  *    every single trusted referrer above the arbitrary
91  *    limit.
92  *
93  *    Revision 1.53  2006/08/31 16:25:06  fabiankeil
94  *    Work around a buffer overflow that caused Privoxy to
95  *    segfault if too many trusted referrers were used. Good
96  *    enough for now, but should be replaced with a real
97  *    solution after the next release.
98  *
99  *    Revision 1.52  2006/07/18 14:48:46  david__schmidt
100  *    Reorganizing the repository: swapping out what was HEAD (the old 3.1 branch)
101  *    with what was really the latest development (the v_3_0_branch branch)
102  *
103  *    Revision 1.50.2.8  2006/01/30 15:16:25  david__schmidt
104  *    Remove a little residual debugging info
105  *
106  *    Revision 1.50.2.7  2006/01/29 23:10:56  david__schmidt
107  *    Multiple filter file support
108  *
109  *    Revision 1.50.2.6  2003/10/24 10:17:54  oes
110  *    Nit: Allowed tabs as separators in filter headings
111  *
112  *    Revision 1.50.2.5  2003/05/08 15:19:15  oes
113  *    sweep: Made loop structure of sweep step mirror that of mark step
114  *
115  *    Revision 1.50.2.4  2003/05/06 15:57:12  oes
116  *    Bugfix: Update last_active pointer in sweep() before
117  *    leaving an active client. Closes bugs #724395, #727882
118  *
119  *    Revision 1.50.2.3  2002/11/20 17:12:30  oes
120  *    Ooops, forgot one change.
121  *
122  *    Revision 1.50.2.2  2002/11/20 14:38:15  oes
123  *    Fixed delayed/incomplete freeing of client resources and
124  *    simplified loop structure in sweep.
125  *    Thanks to Oliver Stoeneberg for the hint.
126  *
127  *    Revision 1.50.2.1  2002/07/26 15:19:24  oes
128  *    - PCRS jobs now chained in order of appearance. Previous
129  *      reverse chaining was counter-intuitive.
130  *    - Changed loglevel of PCRS job compile errors to
131  *      LOG_LEVEL_ERROR
132  *
133  *    Revision 1.50  2002/04/24 02:12:16  oes
134  *    Jon's multiple AF patch: Sweep now takes care of all AFs
135  *
136  *    Revision 1.49  2002/04/19 16:53:25  jongfoster
137  *    Optimize away a function call by using an equivalent macro
138  *
139  *    Revision 1.48  2002/04/05 00:56:09  gliptak
140  *    Correcting typo to clean up on realloc failure
141  *
142  *    Revision 1.47  2002/03/26 22:29:55  swa
143  *    we have a new homepage!
144  *
145  *    Revision 1.46  2002/03/24 13:25:43  swa
146  *    name change related issues
147  *
148  *    Revision 1.45  2002/03/16 23:54:06  jongfoster
149  *    Adding graceful termination feature, to help look for memory leaks.
150  *    If you enable this (which, by design, has to be done by hand
151  *    editing config.h) and then go to http://i.j.b/die, then the program
152  *    will exit cleanly after the *next* request.  It should free all the
153  *    memory that was used.
154  *
155  *    Revision 1.44  2002/03/16 21:51:00  jongfoster
156  *    Fixing free(NULL).
157  *
158  *    Revision 1.43  2002/03/16 20:28:34  oes
159  *    Added descriptions to the filters so users will know what they select in the cgi editor
160  *
161  *    Revision 1.42  2002/03/13 00:27:05  jongfoster
162  *    Killing warnings
163  *
164  *    Revision 1.41  2002/03/12 01:42:50  oes
165  *    Introduced modular filters
166  *
167  *    Revision 1.40  2002/03/08 17:46:04  jongfoster
168  *    Fixing int/size_t warnings
169  *
170  *    Revision 1.39  2002/03/07 03:46:17  oes
171  *    Fixed compiler warnings
172  *
173  *    Revision 1.38  2002/03/06 22:54:35  jongfoster
174  *    Automated function-comment nitpicking.
175  *
176  *    Revision 1.37  2002/03/03 15:07:49  oes
177  *    Re-enabled automatic config reloading
178  *
179  *    Revision 1.36  2002/01/22 23:46:18  jongfoster
180  *    Moving edit_read_line() and simple_read_line() to loaders.c, and
181  *    extending them to support reading MS-DOS, Mac and UNIX style files
182  *    on all platforms.
183  *
184  *    Modifying read_config_line() (without changing it's prototype) to
185  *    be a trivial wrapper for edit_read_line().  This means that we have
186  *    one function to read a line and handle comments, which is common
187  *    between the initialization code and the edit interface.
188  *
189  *    Revision 1.35  2002/01/17 21:03:08  jongfoster
190  *    Moving all our URL and URL pattern parsing code to urlmatch.c.
191  *
192  *    Renaming free_url to free_url_spec, since it frees a struct url_spec.
193  *
194  *    Revision 1.34  2001/12/30 14:07:32  steudten
195  *    - Add signal handling (unix)
196  *    - Add SIGHUP handler (unix)
197  *    - Add creation of pidfile (unix)
198  *    - Add action 'top' in rc file (RH)
199  *    - Add entry 'SIGNALS' to manpage
200  *    - Add exit message to logfile (unix)
201  *
202  *    Revision 1.33  2001/11/13 00:16:38  jongfoster
203  *    Replacing references to malloc.h with the standard stdlib.h
204  *    (See ANSI or K&R 2nd Ed)
205  *
206  *    Revision 1.32  2001/11/07 00:02:13  steudten
207  *    Add line number in error output for lineparsing for
208  *    actionsfile and configfile.
209  *    Special handling for CLF added.
210  *
211  *    Revision 1.31  2001/10/26 17:39:01  oes
212  *    Removed csp->referrer
213  *    Moved ijb_isspace and ijb_tolower to project.h
214  *
215  *    Revision 1.30  2001/10/25 03:40:48  david__schmidt
216  *    Change in porting tactics: OS/2's EMX porting layer doesn't allow multiple
217  *    threads to call select() simultaneously.  So, it's time to do a real, live,
218  *    native OS/2 port.  See defines for __EMX__ (the porting layer) vs. __OS2__
219  *    (native). Both versions will work, but using __OS2__ offers multi-threading.
220  *
221  *    Revision 1.29  2001/10/23 21:38:53  jongfoster
222  *    Adding error-checking to create_url_spec()
223  *
224  *    Revision 1.28  2001/10/07 15:40:39  oes
225  *    Replaced 6 boolean members of csp with one bitmap (csp->flags)
226  *
227  *    Revision 1.27  2001/09/22 16:36:59  jongfoster
228  *    Removing unused parameter fs from read_config_line()
229  *
230  *    Revision 1.26  2001/09/22 14:05:22  jongfoster
231  *    Bugfix: Multiple escaped "#" characters in a configuration
232  *    file are now permitted.
233  *    Also removing 3 unused headers.
234  *
235  *    Revision 1.25  2001/09/13 22:44:03  jongfoster
236  *    Adding {} to an if statement
237  *
238  *    Revision 1.24  2001/07/30 22:08:36  jongfoster
239  *    Tidying up #defines:
240  *    - All feature #defines are now of the form FEATURE_xxx
241  *    - Permanently turned off WIN_GUI_EDIT
242  *    - Permanently turned on WEBDAV and SPLIT_PROXY_ARGS
243  *
244  *    Revision 1.23  2001/07/20 15:51:54  oes
245  *    Fixed indentation of prepocessor commands
246  *
247  *    Revision 1.22  2001/07/20 15:16:17  haroon
248  *    - per Guy's suggestion, added a while loop in sweep() to catch not just
249  *      the last inactive CSP but all other consecutive inactive CSPs after that
250  *      as well
251  *
252  *    Revision 1.21  2001/07/18 17:26:24  oes
253  *    Changed to conform to new pcrs interface
254  *
255  *    Revision 1.20  2001/07/17 13:07:01  oes
256  *    Fixed segv when last line in config files
257  *     lacked a terminating (\r)\n
258  *
259  *    Revision 1.19  2001/07/13 14:01:54  oes
260  *    Removed all #ifdef PCRS
261  *
262  *    Revision 1.18  2001/06/29 21:45:41  oes
263  *    Indentation, CRLF->LF, Tab-> Space
264  *
265  *    Revision 1.17  2001/06/29 13:31:51  oes
266  *    Various adaptions
267  *
268  *    Revision 1.16  2001/06/09 10:55:28  jongfoster
269  *    Changing BUFSIZ ==> BUFFER_SIZE
270  *
271  *    Revision 1.15  2001/06/07 23:14:14  jongfoster
272  *    Removing ACL and forward file loaders - these
273  *    files have been merged into the config file.
274  *    Cosmetic: Moving unloader funcs next to their
275  *    respective loader funcs
276  *
277  *    Revision 1.14  2001/06/01 03:27:04  oes
278  *    Fixed line continuation problem
279  *
280  *    Revision 1.13  2001/05/31 21:28:49  jongfoster
281  *    Removed all permissionsfile code - it's now called the actions
282  *    file, and (almost) all the code is in actions.c
283  *
284  *    Revision 1.12  2001/05/31 17:32:31  oes
285  *
286  *     - Enhanced domain part globbing with infix and prefix asterisk
287  *       matching and optional unanchored operation
288  *
289  *    Revision 1.11  2001/05/29 23:25:24  oes
290  *
291  *     - load_config_line() and load_permissions_file() now use chomp()
292  *
293  *    Revision 1.10  2001/05/29 09:50:24  jongfoster
294  *    Unified blocklist/imagelist/permissionslist.
295  *    File format is still under discussion, but the internal changes
296  *    are (mostly) done.
297  *
298  *    Also modified interceptor behaviour:
299  *    - We now intercept all URLs beginning with one of the following
300  *      prefixes (and *only* these prefixes):
301  *        * http://i.j.b/
302  *        * http://ijbswa.sf.net/config/
303  *        * http://ijbswa.sourceforge.net/config/
304  *    - New interceptors "home page" - go to http://i.j.b/ to see it.
305  *    - Internal changes so that intercepted and fast redirect pages
306  *      are not replaced with an image.
307  *    - Interceptors now have the option to send a binary page direct
308  *      to the client. (i.e. ijb-send-banner uses this)
309  *    - Implemented show-url-info interceptor.  (Which is why I needed
310  *      the above interceptors changes - a typical URL is
311  *      "http://i.j.b/show-url-info?url=www.somesite.com/banner.gif".
312  *      The previous mechanism would not have intercepted that, and
313  *      if it had been intercepted then it then it would have replaced
314  *      it with an image.)
315  *
316  *    Revision 1.9  2001/05/26 17:12:07  jongfoster
317  *    Fatal errors loading configuration files now give better error messages.
318  *
319  *    Revision 1.8  2001/05/26 00:55:20  jongfoster
320  *    Removing duplicated code.  load_forwardfile() now uses create_url_spec()
321  *
322  *    Revision 1.7  2001/05/26 00:28:36  jongfoster
323  *    Automatic reloading of config file.
324  *    Removed obsolete SIGHUP support (Unix) and Reload menu option (Win32).
325  *    Most of the global variables have been moved to a new
326  *    struct configuration_spec, accessed through csp->config->globalname
327  *    Most of the globals remaining are used by the Win32 GUI.
328  *
329  *    Revision 1.6  2001/05/23 12:27:33  oes
330  *
331  *    Fixed ugly indentation of my last changes
332  *
333  *    Revision 1.5  2001/05/23 10:39:05  oes
334  *    - Added support for escaping the comment character
335  *      in config files by a backslash
336  *    - Added support for line continuation in config
337  *      files
338  *    - Fixed a buffer overflow bug with long config lines
339  *
340  *    Revision 1.4  2001/05/22 18:56:28  oes
341  *    CRLF -> LF
342  *
343  *    Revision 1.3  2001/05/20 01:21:20  jongfoster
344  *    Version 2.9.4 checkin.
345  *    - Merged popupfile and cookiefile, and added control over PCRS
346  *      filtering, in new "permissionsfile".
347  *    - Implemented LOG_LEVEL_FATAL, so that if there is a configuration
348  *      file error you now get a message box (in the Win32 GUI) rather
349  *      than the program exiting with no explanation.
350  *    - Made killpopup use the PCRS MIME-type checking and HTTP-header
351  *      skipping.
352  *    - Removed tabs from "config"
353  *    - Moved duplicated url parsing code in "loaders.c" to a new funcition.
354  *    - Bumped up version number.
355  *
356  *    Revision 1.2  2001/05/17 23:01:01  oes
357  *     - Cleaned CRLF's from the sources and related files
358  *
359  *    Revision 1.1.1.1  2001/05/15 13:58:59  oes
360  *    Initial import of version 2.9.3 source tree
361  *
362  *
363  *********************************************************************/
364 \f
365
366 #include "config.h"
367
368 #include <stdio.h>
369 #include <stdlib.h>
370 #include <sys/types.h>
371 #include <string.h>
372 #include <errno.h>
373 #include <sys/stat.h>
374 #include <ctype.h>
375 #include <assert.h>
376
377 #if !defined(_WIN32) && !defined(__OS2__)
378 #include <unistd.h>
379 #endif
380
381 #include "project.h"
382 #include "list.h"
383 #include "loaders.h"
384 #include "filters.h"
385 #include "parsers.h"
386 #include "jcc.h"
387 #include "miscutil.h"
388 #include "errlog.h"
389 #include "actions.h"
390 #include "urlmatch.h"
391 #include "encode.h"
392
393 const char loaders_h_rcs[] = LOADERS_H_VERSION;
394
395 /*
396  * Currently active files.
397  * These are also entered in the main linked list of files.
398  */
399
400 #ifdef FEATURE_TRUST
401 static struct file_list *current_trustfile      = NULL;
402 #endif /* def FEATURE_TRUST */
403
404 static int load_one_re_filterfile(struct client_state *csp, int fileid);
405
406 static struct file_list *current_re_filterfile[MAX_AF_FILES]  = {
407    NULL, NULL, NULL, NULL, NULL,
408    NULL, NULL, NULL, NULL, NULL
409 };
410
411 /*
412  * Pseudo filter type for load_one_re_filterfile
413  */
414 #define NO_NEW_FILTER -1
415
416
417 /*********************************************************************
418  *
419  * Function    :  sweep
420  *
421  * Description :  Basically a mark and sweep garbage collector, it is run
422  *                (by the parent thread) every once in a while to reclaim memory.
423  *
424  * It uses a mark and sweep strategy:
425  *   1) mark all files as inactive
426  *
427  *   2) check with each client:
428  *       if it is active,   mark its files as active
429  *       if it is inactive, free its resources
430  *
431  *   3) free the resources of all of the files that
432  *      are still marked as inactive (and are obsolete).
433  *
434  *   N.B. files that are not obsolete don't have an unloader defined.
435  *
436  * Parameters  :  None
437  *
438  * Returns     :  N/A
439  *
440  *********************************************************************/
441 void sweep(void)
442 {
443    struct file_list *fl, *nfl;
444    struct client_state *csp, *last_active;
445    int i;
446
447    /* clear all of the file's active flags */
448    for ( fl = files->next; NULL != fl; fl = fl->next )
449    {
450       fl->active = 0;
451    }
452
453    last_active = clients;
454    csp = clients->next;
455
456    while (NULL != csp)
457    {
458       if (csp->flags & CSP_FLAG_ACTIVE)
459       {
460          /* Mark this client's files as active */
461
462          /*
463           * Always have a configuration file.
464           * (Also note the slightly non-standard extra
465           * indirection here.)
466           */
467          csp->config->config_file_list->active = 1;
468
469          /* 
470           * Actions files
471           */
472          for (i = 0; i < MAX_AF_FILES; i++)
473          {
474             if (csp->actions_list[i])     
475             {
476                csp->actions_list[i]->active = 1;
477             }
478          }
479
480          /*
481           * Filter files
482           */
483          for (i = 0; i < MAX_AF_FILES; i++)
484          {
485             if (csp->rlist[i])     
486             {
487                csp->rlist[i]->active = 1;
488             }
489          }
490
491          /*
492           * Trust file
493           */
494 #ifdef FEATURE_TRUST
495          if (csp->tlist)
496          {
497             csp->tlist->active = 1;
498          }
499 #endif /* def FEATURE_TRUST */
500          
501          last_active = csp;
502          csp = csp->next;
503
504       }
505       else 
506       /*
507        * This client is not active. Free its resources.
508        */
509       {
510          last_active->next = csp->next;
511
512          freez(csp->ip_addr_str);
513          freez(csp->iob->buf);
514          freez(csp->x_forwarded_for);
515          freez(csp->error_message);
516
517          if (csp->action->flags & ACTION_FORWARD_OVERRIDE &&
518              NULL != csp->fwd)
519          {
520             unload_forward_spec(csp->fwd);
521          }
522          free_http_request(csp->http);
523
524          destroy_list(csp->headers);
525          destroy_list(csp->tags);
526
527          free_current_action(csp->action);
528
529 #ifdef FEATURE_STATISTICS
530          urls_read++;
531          if (csp->flags & CSP_FLAG_REJECTED)
532          {
533             urls_rejected++;
534          }
535 #endif /* def FEATURE_STATISTICS */
536
537          freez(csp);
538          
539          csp = last_active->next;
540       }
541    }
542
543    nfl = files;
544    fl = files->next;
545
546    while (fl != NULL)
547    {
548       if ( ( 0 == fl->active ) && ( NULL != fl->unloader ) )
549       {
550          nfl->next = fl->next;
551
552          (fl->unloader)(fl->f);
553
554          freez(fl->filename);
555          freez(fl);
556
557          fl = nfl->next;
558       }
559       else
560       {
561          nfl = fl;
562          fl = fl->next;
563       }
564    }
565
566 }
567
568
569 /*********************************************************************
570  *
571  * Function    :  check_file_changed
572  *
573  * Description :  Helper function to check if a file needs reloading.
574  *                If "current" is still current, return it.  Otherwise
575  *                allocates a new (zeroed) "struct file_list", fills
576  *                in the disk file name and timestamp, and returns it.
577  *
578  * Parameters  :
579  *          1  :  current = The file_list currently being used - will
580  *                          be checked to see if it is out of date.
581  *                          May be NULL (which is treated as out of
582  *                          date).
583  *          2  :  filename = Name of file to check.
584  *          3  :  newfl    = New file list. [Output only]
585  *                           This will be set to NULL, OR a struct
586  *                           file_list newly allocated on the
587  *                           heap, with the filename and lastmodified
588  *                           fields filled, and all others zeroed.
589  *
590  * Returns     :  If file unchanged: 0 (and sets newfl == NULL)
591  *                If file changed: 1 and sets newfl != NULL
592  *                On error: 1 and sets newfl == NULL
593  *
594  *********************************************************************/
595 int check_file_changed(const struct file_list * current,
596                        const char * filename,
597                        struct file_list ** newfl)
598 {
599    struct file_list *fs;
600    struct stat statbuf[1];
601
602    *newfl = NULL;
603
604    if (stat(filename, statbuf) < 0)
605    {
606       /* Error, probably file not found. */
607       return 1;
608    }
609
610    if (current
611        && (current->lastmodified == statbuf->st_mtime)
612        && (0 == strcmp(current->filename, filename)))
613    {
614       return 0;
615    }
616
617    fs = (struct file_list *)zalloc(sizeof(struct file_list));
618    if (fs == NULL)
619    {
620       /* Out of memory error */
621       return 1;
622    }
623
624
625    fs->filename = strdup(filename);
626    fs->lastmodified = statbuf->st_mtime;
627
628    if (fs->filename == NULL)
629    {
630       /* Out of memory error */
631       freez (fs);
632       return 1;
633    }
634    *newfl = fs;
635    return 1;
636 }
637
638
639 /*********************************************************************
640  *
641  * Function    :  simple_read_line
642  *
643  * Description :  Read a single line from a file and return it.
644  *                This is basically a version of fgets() that malloc()s
645  *                it's own line buffer.  Note that the buffer will
646  *                always be a multiple of BUFFER_SIZE bytes long.
647  *                Therefore if you are going to keep the string for
648  *                an extended period of time, you should probably
649  *                strdup() it and free() the original, to save memory.
650  *
651  *
652  * Parameters  :
653  *          1  :  dest = destination for newly malloc'd pointer to
654  *                line data.  Will be set to NULL on error.
655  *          2  :  fp = File to read from
656  *          3  :  newline = Standard for newlines in the file.
657  *                Will be unchanged if it's value on input is not
658  *                NEWLINE_UNKNOWN.
659  *                On output, may be changed from NEWLINE_UNKNOWN to
660  *                actual convention in file.
661  *
662  * Returns     :  JB_ERR_OK     on success
663  *                JB_ERR_MEMORY on out-of-memory
664  *                JB_ERR_FILE   on EOF.
665  *
666  *********************************************************************/
667 jb_err simple_read_line(FILE *fp, char **dest, int *newline)
668 {
669    size_t len = 0;
670    size_t buflen = BUFFER_SIZE;
671    char * buf;
672    char * p;
673    int ch;
674    int realnewline = NEWLINE_UNKNOWN;
675
676    if (NULL == (buf = malloc(buflen)))
677    {
678       return JB_ERR_MEMORY;
679    }
680
681    p = buf;
682
683 /*
684  * Character codes.  If you have a wierd compiler and the following are
685  * incorrect, you also need to fix NEWLINE() in loaders.h
686  */
687 #define CHAR_CR '\r' /* ASCII 13 */
688 #define CHAR_LF '\n' /* ASCII 10 */
689
690    for (;;)
691    {
692       ch = getc(fp);
693       if (ch == EOF)
694       {
695          if (len > 0)
696          {
697             *p = '\0';
698             *dest = buf;
699             return JB_ERR_OK;
700          }
701          else
702          {
703             free(buf);
704             *dest = NULL;
705             return JB_ERR_FILE;
706          }
707       }
708       else if (ch == CHAR_CR)
709       {
710          ch = getc(fp);
711          if (ch == CHAR_LF)
712          {
713             if (*newline == NEWLINE_UNKNOWN)
714             {
715                *newline = NEWLINE_DOS;
716             }
717          }
718          else
719          {
720             if (ch != EOF)
721             {
722                ungetc(ch, fp);
723             }
724             if (*newline == NEWLINE_UNKNOWN)
725             {
726                *newline = NEWLINE_MAC;
727             }
728          }
729          *p = '\0';
730          *dest = buf;
731          if (*newline == NEWLINE_UNKNOWN)
732          {
733             *newline = realnewline;
734          }
735          return JB_ERR_OK;
736       }
737       else if (ch == CHAR_LF)
738       {
739          *p = '\0';
740          *dest = buf;
741          if (*newline == NEWLINE_UNKNOWN)
742          {
743             *newline = NEWLINE_UNIX;
744          }
745          return JB_ERR_OK;
746       }
747       else if (ch == 0)
748       {
749          *p = '\0';
750          *dest = buf;
751          return JB_ERR_OK;
752       }
753
754       *p++ = (char)ch;
755
756       if (++len >= buflen)
757       {
758          buflen += BUFFER_SIZE;
759          if (NULL == (p = realloc(buf, buflen)))
760          {
761             free(buf);
762             return JB_ERR_MEMORY;
763          }
764          buf = p;
765          p = buf + len;
766       }
767    }
768 }
769
770
771 /*********************************************************************
772  *
773  * Function    :  edit_read_line
774  *
775  * Description :  Read a single non-empty line from a file and return
776  *                it.  Trims comments, leading and trailing whitespace
777  *                and respects escaping of newline and comment char.
778  *                Provides the line in 2 alternative forms: raw and
779  *                preprocessed.
780  *                - raw is the raw data read from the file.  If the
781  *                  line is not modified, then this should be written
782  *                  to the new file.
783  *                - prefix is any comments and blank lines that were
784  *                  read from the file.  If the line is modified, then
785  *                  this should be written out to the file followed
786  *                  by the modified data.  (If this string is non-empty
787  *                  then it will have a newline at the end).
788  *                - data is the actual data that will be parsed
789  *                  further by appropriate routines.
790  *                On EOF, the 3 strings will all be set to NULL and
791  *                0 will be returned.
792  *
793  * Parameters  :
794  *          1  :  fp = File to read from
795  *          2  :  raw_out = destination for newly malloc'd pointer to
796  *                raw line data.  May be NULL if you don't want it.
797  *          3  :  prefix_out = destination for newly malloc'd pointer to
798  *                comments.  May be NULL if you don't want it.
799  *          4  :  data_out = destination for newly malloc'd pointer to
800  *                line data with comments and leading/trailing spaces
801  *                removed, and line continuation performed.  May be
802  *                NULL if you don't want it.
803  *          5  :  newline = Standard for newlines in the file.
804  *                On input, set to value to use or NEWLINE_UNKNOWN.
805  *                On output, may be changed from NEWLINE_UNKNOWN to
806  *                actual convention in file.  May be NULL if you
807  *                don't want it.
808  *          6  :  line_number = Line number in file.  In "lines" as
809  *                reported by a text editor, not lines containing data.
810  *
811  * Returns     :  JB_ERR_OK     on success
812  *                JB_ERR_MEMORY on out-of-memory
813  *                JB_ERR_FILE   on EOF.
814  *
815  *********************************************************************/
816 jb_err edit_read_line(FILE *fp,
817                       char **raw_out,
818                       char **prefix_out,
819                       char **data_out,
820                       int *newline,
821                       unsigned long *line_number)
822 {
823    char *p;          /* Temporary pointer   */
824    char *linebuf;    /* Line read from file */
825    char *linestart;  /* Start of linebuf, usually first non-whitespace char */
826    int contflag = 0; /* Nonzero for line continuation - i.e. line ends '\' */
827    int is_empty = 1; /* Flag if not got any data yet */
828    char *raw    = NULL; /* String to be stored in raw_out    */
829    char *prefix = NULL; /* String to be stored in prefix_out */
830    char *data   = NULL; /* String to be stored in data_out   */
831    int scrapnewline;    /* Used for (*newline) if newline==NULL */
832    jb_err rval = JB_ERR_OK;
833
834    assert(fp);
835    assert(raw_out || data_out);
836    assert(newline == NULL
837        || *newline == NEWLINE_UNKNOWN
838        || *newline == NEWLINE_UNIX
839        || *newline == NEWLINE_DOS
840        || *newline == NEWLINE_MAC);
841
842    if (newline == NULL)
843    {
844       scrapnewline = NEWLINE_UNKNOWN;
845       newline = &scrapnewline;
846    }
847
848    /* Set output parameters to NULL */
849    if (raw_out)
850    {
851       *raw_out    = NULL;
852    }
853    if (prefix_out)
854    {
855       *prefix_out = NULL;
856    }
857    if (data_out)
858    {
859       *data_out   = NULL;
860    }
861
862    /* Set string variables to new, empty strings. */
863
864    if (raw_out)
865    {
866       if ((raw = malloc(1)) == NULL)
867       {
868          return JB_ERR_MEMORY;
869       }
870       *raw = '\0';
871    }
872    if (prefix_out)
873    {
874       if ((prefix = malloc(1)) == NULL)
875       {
876          freez(raw);
877          return JB_ERR_MEMORY;
878       }
879       *prefix = '\0';
880    }
881    if (data_out)
882    {
883       if ((data = malloc(1)) == NULL)
884       {
885          freez(raw);
886          freez(prefix);
887          return JB_ERR_MEMORY;
888       }
889       *data = '\0';
890    }
891
892    /* Main loop.  Loop while we need more data & it's not EOF. */
893
894    while ( (contflag || is_empty)
895         && (JB_ERR_OK == (rval = simple_read_line(fp, &linebuf, newline))))
896    {
897       if (line_number)
898       {
899          (*line_number)++;
900       }
901       if (raw)
902       {
903          string_append(&raw,linebuf);
904          if (string_append(&raw,NEWLINE(*newline)))
905          {
906             freez(prefix);
907             freez(data);
908             free(linebuf);
909             return JB_ERR_MEMORY;
910          }
911       }
912
913       /* Line continuation? Trim escape and set flag. */
914       p = linebuf + strlen(linebuf) - 1;
915       contflag = ((*linebuf != '\0') && (*p == '\\'));
916       if (contflag)
917       {
918          *p = '\0';
919       }
920
921       /* Trim leading spaces if we're at the start of the line */
922       linestart = linebuf;
923       if (*data == '\0')
924       {
925          /* Trim leading spaces */
926          while (*linestart && isspace((int)(unsigned char)*linestart))
927          {
928             linestart++;
929          }
930       }
931
932       /* Handle comment characters. */
933       p = linestart;
934       while ((p = strchr(p, '#')) != NULL)
935       {
936          /* Found a comment char.. */
937          if ((p != linebuf) && (*(p-1) == '\\'))
938          {
939             /* ..and it's escaped, left-shift the line over the escape. */
940             char *q = p - 1;
941             while ((*q = *(q + 1)) != '\0')
942             {
943                q++;
944             }
945             /* Now scan from just after the "#". */
946          }
947          else
948          {
949             /* Real comment.  Save it... */
950             if (p == linestart)
951             {
952                /* Special case:  Line only contains a comment, so all the
953                 * previous whitespace is considered part of the comment.
954                 * Undo the whitespace skipping, if any.
955                 */
956                linestart = linebuf;
957                p = linestart;
958             }
959             if (prefix)
960             {
961                string_append(&prefix,p);
962                if (string_append(&prefix, NEWLINE(*newline)))
963                {
964                   freez(raw);
965                   freez(data);
966                   free(linebuf);
967                   return JB_ERR_MEMORY;
968                }
969             }
970
971             /* ... and chop off the rest of the line */
972             *p = '\0';
973          }
974       } /* END while (there's a # character) */
975
976       /* Write to the buffer */
977       if (*linestart)
978       {
979          is_empty = 0;
980          if (data)
981          {
982             if (string_append(&data, linestart))
983             {
984                freez(raw);
985                freez(prefix);
986                free(linebuf);
987                return JB_ERR_MEMORY;
988             }
989          }
990       }
991
992       free(linebuf);
993    } /* END while(we need more data) */
994
995    /* Handle simple_read_line() errors - ignore EOF */
996    if ((rval != JB_ERR_OK) && (rval != JB_ERR_FILE))
997    {
998       freez(raw);
999       freez(prefix);
1000       freez(data);
1001       return rval;
1002    }
1003
1004    if (raw ? (*raw == '\0') : is_empty)
1005    {
1006       /* EOF and no data there.  (Definition of "data" depends on whether
1007        * the caller cares about "raw" or just "data").
1008        */
1009
1010       freez(raw);
1011       freez(prefix);
1012       freez(data);
1013
1014       return JB_ERR_FILE;
1015    }
1016    else
1017    {
1018       /* Got at least some data */
1019
1020       /* Remove trailing whitespace */
1021       chomp(data);
1022
1023       if (raw_out)
1024       {
1025          *raw_out    = raw;
1026       }
1027       else
1028       {
1029          freez(raw);
1030       }
1031       if (prefix_out)
1032       {
1033          *prefix_out = prefix;
1034       }
1035       else
1036       {
1037          freez(prefix);
1038       }
1039       if (data_out)
1040       {
1041          *data_out   = data;
1042       }
1043       else
1044       {
1045          freez(data);
1046       }
1047       return JB_ERR_OK;
1048    }
1049 }
1050
1051
1052 /*********************************************************************
1053  *
1054  * Function    :  read_config_line
1055  *
1056  * Description :  Read a single non-empty line from a file and return
1057  *                it.  Trims comments, leading and trailing whitespace
1058  *                and respects escaping of newline and comment char.
1059  *
1060  * Parameters  :
1061  *          1  :  buf = Buffer to use.
1062  *          2  :  buflen = Size of buffer in bytes.
1063  *          3  :  fp = File to read from
1064  *          4  :  linenum = linenumber in file
1065  *
1066  * Returns     :  NULL on EOF or error
1067  *                Otherwise, returns buf.
1068  *
1069  *********************************************************************/
1070 char *read_config_line(char *buf, size_t buflen, FILE *fp, unsigned long *linenum)
1071 {
1072    jb_err err;
1073    char *buf2 = NULL;
1074    err = edit_read_line(fp, NULL, NULL, &buf2, NULL, linenum);
1075    if (err)
1076    {
1077       if (err == JB_ERR_MEMORY)
1078       {
1079          log_error(LOG_LEVEL_FATAL, "Out of memory loading a config file");
1080       }
1081       return NULL;
1082    }
1083    else
1084    {
1085       assert(buf2);
1086       assert(strlen(buf2) + 1U < buflen);
1087       strncpy(buf, buf2, buflen - 1);
1088       free(buf2);
1089       buf[buflen - 1] = '\0';
1090       return buf;
1091    }
1092 }
1093
1094
1095 #ifdef FEATURE_TRUST
1096 /*********************************************************************
1097  *
1098  * Function    :  unload_trustfile
1099  *
1100  * Description :  Unloads a trustfile.
1101  *
1102  * Parameters  :
1103  *          1  :  f = the data structure associated with the trustfile.
1104  *
1105  * Returns     :  N/A
1106  *
1107  *********************************************************************/
1108 static void unload_trustfile(void *f)
1109 {
1110    struct block_spec *cur = (struct block_spec *)f;
1111    struct block_spec *next;
1112
1113    while (cur != NULL)
1114    {
1115       next = cur->next;
1116
1117       free_url_spec(cur->url);
1118       free(cur);
1119
1120       cur = next;
1121    }
1122
1123 }
1124
1125
1126 #ifdef FEATURE_GRACEFUL_TERMINATION
1127 /*********************************************************************
1128  *
1129  * Function    :  unload_current_trust_file
1130  *
1131  * Description :  Unloads current trust file - reset to state at
1132  *                beginning of program.
1133  *
1134  * Parameters  :  None
1135  *
1136  * Returns     :  N/A
1137  *
1138  *********************************************************************/
1139 void unload_current_trust_file(void)
1140 {
1141    if (current_trustfile)
1142    {
1143       current_trustfile->unloader = unload_trustfile;
1144       current_trustfile = NULL;
1145    }
1146 }
1147 #endif /* FEATURE_GRACEFUL_TERMINATION */
1148
1149
1150 /*********************************************************************
1151  *
1152  * Function    :  load_trustfile
1153  *
1154  * Description :  Read and parse a trustfile and add to files list.
1155  *
1156  * Parameters  :
1157  *          1  :  csp = Current client state (buffers, headers, etc...)
1158  *
1159  * Returns     :  0 => Ok, everything else is an error.
1160  *
1161  *********************************************************************/
1162 int load_trustfile(struct client_state *csp)
1163 {
1164    FILE *fp;
1165
1166    struct block_spec *b, *bl;
1167    struct url_spec **tl;
1168
1169    char  buf[BUFFER_SIZE], *p, *q;
1170    int reject, trusted;
1171    struct file_list *fs;
1172    unsigned long linenum = 0;
1173    int trusted_referrers = 0;
1174
1175    if (!check_file_changed(current_trustfile, csp->config->trustfile, &fs))
1176    {
1177       /* No need to load */
1178       if (csp)
1179       {
1180          csp->tlist = current_trustfile;
1181       }
1182       return(0);
1183    }
1184    if (!fs)
1185    {
1186       goto load_trustfile_error;
1187    }
1188
1189    fs->f = bl = (struct block_spec *)zalloc(sizeof(*bl));
1190    if (bl == NULL)
1191    {
1192       goto load_trustfile_error;
1193    }
1194
1195    if ((fp = fopen(csp->config->trustfile, "r")) == NULL)
1196    {
1197       goto load_trustfile_error;
1198    }
1199
1200    tl = csp->config->trust_list;
1201
1202    while (read_config_line(buf, sizeof(buf), fp, &linenum) != NULL)
1203    {
1204       trusted = 0;
1205       reject  = 1;
1206
1207       if (*buf == '+')
1208       {
1209          trusted = 1;
1210          *buf = '~';
1211       }
1212
1213       if (*buf == '~')
1214       {
1215          reject = 0;
1216          p = buf;
1217          q = p+1;
1218          while ((*p++ = *q++) != '\0')
1219          {
1220             /* nop */
1221          }
1222       }
1223
1224       /* skip blank lines */
1225       if (*buf == '\0')
1226       {
1227          continue;
1228       }
1229
1230       /* allocate a new node */
1231       if ((b = zalloc(sizeof(*b))) == NULL)
1232       {
1233          fclose(fp);
1234          goto load_trustfile_error;
1235       }
1236
1237       /* add it to the list */
1238       b->next  = bl->next;
1239       bl->next = b;
1240
1241       b->reject = reject;
1242
1243       /* Save the URL pattern */
1244       if (create_url_spec(b->url, buf))
1245       {
1246          fclose(fp);
1247          goto load_trustfile_error;
1248       }
1249
1250       /*
1251        * save a pointer to URL's spec in the list of trusted URL's, too
1252        */
1253       if (trusted)
1254       {
1255          if(++trusted_referrers < MAX_TRUSTED_REFERRERS)
1256          {
1257             *tl++ = b->url;
1258          }
1259       }
1260    }
1261
1262    if(trusted_referrers >= MAX_TRUSTED_REFERRERS) 
1263    {
1264       /*
1265        * FIXME: ... after Privoxy 3.0.4 is out.
1266        */
1267        log_error(LOG_LEVEL_ERROR, "Too many trusted referrers. Current limit is %d, you are using %d.\n"
1268           "  Additional trusted referrers are treated like ordinary trusted URLs.\n"
1269           "  (You can increase this limit by changing MAX_TRUSTED_REFERRERS in project.h and recompiling).",
1270           MAX_TRUSTED_REFERRERS, trusted_referrers);
1271    }
1272
1273    *tl = NULL;
1274
1275    fclose(fp);
1276
1277    /* the old one is now obsolete */
1278    if (current_trustfile)
1279    {
1280       current_trustfile->unloader = unload_trustfile;
1281    }
1282
1283    fs->next    = files->next;
1284    files->next = fs;
1285    current_trustfile = fs;
1286
1287    if (csp)
1288    {
1289       csp->tlist = fs;
1290    }
1291
1292    return(0);
1293
1294 load_trustfile_error:
1295    log_error(LOG_LEVEL_FATAL, "can't load trustfile '%s': %E",
1296              csp->config->trustfile);
1297    return(-1);
1298
1299 }
1300 #endif /* def FEATURE_TRUST */
1301
1302
1303 /*********************************************************************
1304  *
1305  * Function    :  unload_re_filterfile
1306  *
1307  * Description :  Unload the re_filter list by freeing all chained
1308  *                re_filterfile specs and their data.
1309  *
1310  * Parameters  :
1311  *          1  :  f = the data structure associated with the filterfile.
1312  *
1313  * Returns     :  N/A
1314  *
1315  *********************************************************************/
1316 static void unload_re_filterfile(void *f)
1317 {
1318    struct re_filterfile_spec *a, *b = (struct re_filterfile_spec *)f;
1319
1320    while (b != NULL)
1321    {
1322       a = b->next;
1323
1324       destroy_list(b->patterns);
1325       pcrs_free_joblist(b->joblist);
1326       freez(b->name);
1327       freez(b->description);
1328       freez(b);
1329
1330       b = a;
1331    }
1332
1333    return;
1334 }
1335
1336 /*********************************************************************
1337  *
1338  * Function    :  unload_forward_spec
1339  *
1340  * Description :  Unload the forward spec settings by freeing all 
1341  *                memory referenced by members and the memory for
1342  *                the spec itself.
1343  *
1344  * Parameters  :
1345  *          1  :  fwd = the forward spec.
1346  *
1347  * Returns     :  N/A
1348  *
1349  *********************************************************************/
1350 void unload_forward_spec(struct forward_spec *fwd)
1351 {
1352    free_url_spec(fwd->url);
1353    freez(fwd->gateway_host);
1354    freez(fwd->forward_host);
1355    free(fwd);
1356
1357    return;
1358 }
1359
1360
1361 #ifdef FEATURE_GRACEFUL_TERMINATION
1362 /*********************************************************************
1363  *
1364  * Function    :  unload_current_re_filterfile
1365  *
1366  * Description :  Unloads current re_filter file - reset to state at
1367  *                beginning of program.
1368  *
1369  * Parameters  :  None
1370  *
1371  * Returns     :  N/A
1372  *
1373  *********************************************************************/
1374 void unload_current_re_filterfile(void)
1375 {
1376    int i;
1377
1378    for (i = 0; i < MAX_AF_FILES; i++)
1379    {
1380       if (current_re_filterfile[i])
1381       {
1382          current_re_filterfile[i]->unloader = unload_re_filterfile;
1383          current_re_filterfile[i] = NULL;
1384       }
1385    }
1386 }
1387 #endif
1388
1389
1390 /*********************************************************************
1391  *
1392  * Function    :  load_re_filterfiles
1393  *
1394  * Description :  Loads all the filterfiles. 
1395  *                Generate a chained list of re_filterfile_spec's from
1396  *                the "FILTER: " blocks, compiling all their substitutions
1397  *                into chained lists of pcrs_job structs.
1398  *
1399  * Parameters  :
1400  *          1  :  csp = Current client state (buffers, headers, etc...)
1401  *
1402  * Returns     :  0 => Ok, everything else is an error.
1403  *
1404  *********************************************************************/
1405 int load_re_filterfiles(struct client_state *csp)
1406 {
1407    int i;
1408    int result;
1409
1410    for (i = 0; i < MAX_AF_FILES; i++)
1411    {
1412       if (csp->config->re_filterfile[i])
1413       {
1414          result = load_one_re_filterfile(csp, i);
1415          if (result)
1416          {
1417             return result;
1418          }
1419       }
1420       else if (current_re_filterfile[i])
1421       {
1422          current_re_filterfile[i]->unloader = unload_re_filterfile;
1423          current_re_filterfile[i] = NULL;
1424       }
1425    }
1426
1427    return 0;
1428 }
1429
1430
1431 /*********************************************************************
1432  *
1433  * Function    :  load_one_re_filterfile
1434  *
1435  * Description :  Load a re_filterfile. 
1436  *                Generate a chained list of re_filterfile_spec's from
1437  *                the "FILTER: " blocks, compiling all their substitutions
1438  *                into chained lists of pcrs_job structs.
1439  *
1440  * Parameters  :
1441  *          1  :  csp = Current client state (buffers, headers, etc...)
1442  *
1443  * Returns     :  0 => Ok, everything else is an error.
1444  *
1445  *********************************************************************/
1446 int load_one_re_filterfile(struct client_state *csp, int fileid)
1447 {
1448    FILE *fp;
1449
1450    struct re_filterfile_spec *new_bl, *bl = NULL;
1451    struct file_list *fs;
1452
1453    char  buf[BUFFER_SIZE];
1454    int error;
1455    unsigned long linenum = 0;
1456    pcrs_job *dummy, *lastjob = NULL;
1457
1458    /*
1459     * No need to reload if unchanged
1460     */
1461    if (!check_file_changed(current_re_filterfile[fileid], csp->config->re_filterfile[fileid], &fs))
1462    {
1463       if (csp)
1464       {
1465          csp->rlist[fileid] = current_re_filterfile[fileid];
1466       }
1467       return(0);
1468    }
1469    if (!fs)
1470    {
1471       goto load_re_filterfile_error;
1472    }
1473
1474    /* 
1475     * Open the file or fail
1476     */
1477    if ((fp = fopen(csp->config->re_filterfile[fileid], "r")) == NULL)
1478    {
1479       goto load_re_filterfile_error;
1480    }
1481
1482    /* 
1483     * Read line by line
1484     */
1485    while (read_config_line(buf, sizeof(buf), fp, &linenum) != NULL)
1486    {
1487       int new_filter = NO_NEW_FILTER;
1488
1489       if (strncmp(buf, "FILTER:", 7) == 0)
1490       {
1491          new_filter = FT_CONTENT_FILTER;
1492       }
1493       else if (strncmp(buf, "SERVER-HEADER-FILTER:", 21) == 0)
1494       {
1495          new_filter = FT_SERVER_HEADER_FILTER;
1496       }
1497       else if (strncmp(buf, "CLIENT-HEADER-FILTER:", 21) == 0)
1498       {
1499          new_filter = FT_CLIENT_HEADER_FILTER;
1500       }
1501       else if (strncmp(buf, "CLIENT-HEADER-TAGGER:", 21) == 0)
1502       {
1503          new_filter = FT_CLIENT_HEADER_TAGGER;
1504       }
1505       else if (strncmp(buf, "SERVER-HEADER-TAGGER:", 21) == 0)
1506       {
1507          new_filter = FT_SERVER_HEADER_TAGGER;
1508       }
1509
1510       /*
1511        * If this is the head of a new filter block, make it a
1512        * re_filterfile spec of its own and chain it to the list:
1513        */
1514       if (new_filter != NO_NEW_FILTER)
1515       {
1516          new_bl = (struct re_filterfile_spec  *)zalloc(sizeof(*bl));
1517          if (new_bl == NULL)
1518          {
1519             goto load_re_filterfile_error;
1520          }
1521          if (new_filter == FT_CONTENT_FILTER)
1522          {
1523             new_bl->name = chomp(buf + 7);
1524          }
1525          else
1526          {
1527             new_bl->name = chomp(buf + 21);
1528          }
1529          new_bl->type = new_filter;
1530
1531          /*
1532           * If a filter description is available,
1533           * encode it to HTML and save it.
1534           */
1535          if (NULL != (new_bl->description = strpbrk(new_bl->name, " \t")))
1536          {
1537             *new_bl->description++ = '\0';
1538             new_bl->description = html_encode(chomp(new_bl->description));
1539             if (NULL == new_bl->description)
1540             {
1541                new_bl->description = strdup("Out of memory while encoding this filter's description to HTML");
1542             }
1543          }
1544          else
1545          {
1546             new_bl->description = strdup("No description available for this filter");
1547          }
1548
1549          new_bl->name = strdup(chomp(new_bl->name));
1550          
1551          /*
1552           * If this is the first filter block, chain it
1553           * to the file_list rather than its (nonexistant)
1554           * predecessor
1555           */
1556          if (fs->f == NULL)
1557          {
1558             fs->f = new_bl;
1559          }
1560          else
1561          {
1562             bl->next = new_bl;
1563          }
1564          bl = new_bl;
1565
1566          log_error(LOG_LEVEL_RE_FILTER, "Reading in filter \"%s\" (\"%s\")", bl->name, bl->description);
1567
1568          continue;
1569       }
1570
1571       /* 
1572        * Else, save the expression, make it a pcrs_job
1573        * and chain it into the current filter's joblist 
1574        */
1575       if (bl != NULL)
1576       {
1577          error = enlist(bl->patterns, buf);
1578          if (JB_ERR_MEMORY == error)
1579          {
1580             log_error(LOG_LEVEL_FATAL,
1581                "Out of memory while enlisting re_filter job \'%s\' for filter %s.", buf, bl->name);
1582          }
1583          assert(JB_ERR_OK == error);
1584
1585          if (pcrs_job_is_dynamic(buf))
1586          {
1587             /*
1588              * Dynamic pattern that might contain variables
1589              * and has to be recompiled for every request
1590              */
1591             if (bl->joblist != NULL)
1592             {
1593                 pcrs_free_joblist(bl->joblist);
1594                 bl->joblist = NULL;
1595             }
1596             bl->dynamic = 1;
1597             log_error(LOG_LEVEL_RE_FILTER,
1598                "Adding dynamic re_filter job \'%s\' to filter %s succeeded.", buf, bl->name);
1599             continue;             
1600          }
1601          else if (bl->dynamic)
1602          {
1603             /*
1604              * A previous job was dynamic and as we
1605              * recompile the whole filter anyway, it
1606              * makes no sense to compile this job now.
1607              */
1608             log_error(LOG_LEVEL_RE_FILTER,
1609                "Adding static re_filter job \'%s\' to dynamic filter %s succeeded.", buf, bl->name);
1610             continue;
1611          }
1612
1613          if ((dummy = pcrs_compile_command(buf, &error)) == NULL)
1614          {
1615             log_error(LOG_LEVEL_ERROR,
1616                "Adding re_filter job \'%s\' to filter %s failed with error %d.", buf, bl->name, error);
1617             continue;
1618          }
1619          else
1620          {
1621             if (bl->joblist == NULL)
1622             {
1623                bl->joblist = dummy;
1624             }
1625             else
1626             {
1627                lastjob->next = dummy;
1628             }
1629             lastjob = dummy;
1630             log_error(LOG_LEVEL_RE_FILTER, "Adding re_filter job \'%s\' to filter %s succeeded.", buf, bl->name);
1631          }
1632       }
1633       else
1634       {
1635          log_error(LOG_LEVEL_ERROR, "Ignoring job %s outside filter block in %s, line %d",
1636             buf, csp->config->re_filterfile[fileid], linenum);
1637       }
1638    }
1639
1640    fclose(fp);
1641
1642    /* 
1643     * Schedule the now-obsolete old data for unloading
1644     */
1645    if ( NULL != current_re_filterfile[fileid] )
1646    {
1647       current_re_filterfile[fileid]->unloader = unload_re_filterfile;
1648    }
1649
1650    /*
1651     * Chain this file into the global list of loaded files
1652     */
1653    fs->next    = files->next;
1654    files->next = fs;
1655    current_re_filterfile[fileid] = fs;
1656
1657    if (csp)
1658    {
1659       csp->rlist[fileid] = fs;
1660    }
1661
1662    return( 0 );
1663
1664 load_re_filterfile_error:
1665    log_error(LOG_LEVEL_FATAL, "can't load re_filterfile '%s': %E",
1666              csp->config->re_filterfile[fileid]);
1667    return(-1);
1668
1669 }
1670
1671
1672 /*********************************************************************
1673  *
1674  * Function    :  add_loader
1675  *
1676  * Description :  Called from `load_config'.  Called once for each input
1677  *                file found in config.
1678  *
1679  * Parameters  :
1680  *          1  :  loader = pointer to a function that can parse and load
1681  *                the appropriate config file.
1682  *          2  :  config = The configuration_spec to add the loader to.
1683  *
1684  * Returns     :  N/A
1685  *
1686  *********************************************************************/
1687 void add_loader(int (*loader)(struct client_state *),
1688                 struct configuration_spec * config)
1689 {
1690    int i;
1691
1692    for (i=0; i < NLOADERS; i++)
1693    {
1694       if (config->loaders[i] == NULL)
1695       {
1696          config->loaders[i] = loader;
1697          break;
1698       }
1699    }
1700
1701 }
1702
1703
1704 /*********************************************************************
1705  *
1706  * Function    :  run_loader
1707  *
1708  * Description :  Called from `load_config' and `listen_loop'.  This
1709  *                function keeps the "csp" current with any file mods
1710  *                since the last loop.  If a file is unchanged, the
1711  *                loader functions do NOT reload the file.
1712  *
1713  * Parameters  :
1714  *          1  :  csp = Current client state (buffers, headers, etc...)
1715  *                      Must be non-null.  Reads: "csp->config"
1716  *                      Writes: various data members.
1717  *
1718  * Returns     :  0 => Ok, everything else is an error.
1719  *
1720  *********************************************************************/
1721 int run_loader(struct client_state *csp)
1722 {
1723    int ret = 0;
1724    int i;
1725
1726    for (i=0; i < NLOADERS; i++)
1727    {
1728       if (csp->config->loaders[i] == NULL)
1729       {
1730          break;
1731       }
1732       ret |= (csp->config->loaders[i])(csp);
1733    }
1734    return(ret);
1735
1736 }
1737
1738
1739 /*
1740   Local Variables:
1741   tab-width: 3
1742   end:
1743 */