Remove obsolete reference to mailing lists hosted at SourceForge
[privoxy.git] / loaders.c
1 const char loaders_rcs[] = "$Id: loaders.c,v 1.104 2016/05/22 12:43:07 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-2014 the
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  *********************************************************************/
37
38
39 #include "config.h"
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <sys/types.h>
44 #include <string.h>
45 #include <errno.h>
46 #include <sys/stat.h>
47 #include <ctype.h>
48 #include <assert.h>
49
50 #if !defined(_WIN32) && !defined(__OS2__)
51 #include <unistd.h>
52 #endif
53
54 #include "project.h"
55 #include "list.h"
56 #include "loaders.h"
57 #include "filters.h"
58 #include "parsers.h"
59 #include "jcc.h"
60 #include "miscutil.h"
61 #include "errlog.h"
62 #include "actions.h"
63 #include "urlmatch.h"
64 #include "encode.h"
65
66 const char loaders_h_rcs[] = LOADERS_H_VERSION;
67
68 /*
69  * Currently active files.
70  * These are also entered in the main linked list of files.
71  */
72
73 #ifdef FEATURE_TRUST
74 static struct file_list *current_trustfile      = NULL;
75 #endif /* def FEATURE_TRUST */
76
77 static int load_one_re_filterfile(struct client_state *csp, int fileid);
78
79 static struct file_list *current_re_filterfile[MAX_AF_FILES]  = {
80    NULL, NULL, NULL, NULL, NULL,
81    NULL, NULL, NULL, NULL, NULL
82 };
83
84
85 /*********************************************************************
86  *
87  * Function    :  sweep
88  *
89  * Description :  Basically a mark and sweep garbage collector, it is run
90  *                (by the parent thread) every once in a while to reclaim memory.
91  *
92  * It uses a mark and sweep strategy:
93  *   1) mark all files as inactive
94  *
95  *   2) check with each client:
96  *       if it is active,   mark its files as active
97  *       if it is inactive, free its resources
98  *
99  *   3) free the resources of all of the files that
100  *      are still marked as inactive (and are obsolete).
101  *
102  *   N.B. files that are not obsolete don't have an unloader defined.
103  *
104  * Parameters  :  None
105  *
106  * Returns     :  The number of threads that are still active.
107  *
108  *********************************************************************/
109 unsigned int sweep(void)
110 {
111    struct file_list *fl, *nfl;
112    struct client_state *csp;
113    struct client_states *last_active, *client_list;
114    int i;
115    unsigned int active_threads = 0;
116
117    /* clear all of the file's active flags */
118    for (fl = files->next; NULL != fl; fl = fl->next)
119    {
120       fl->active = 0;
121    }
122
123    last_active = clients;
124    client_list = clients->next;
125
126    while (NULL != client_list)
127    {
128       csp = &client_list->csp;
129       if (csp->flags & CSP_FLAG_ACTIVE)
130       {
131          /* Mark this client's files as active */
132
133          /*
134           * Always have a configuration file.
135           * (Also note the slightly non-standard extra
136           * indirection here.)
137           */
138          csp->config->config_file_list->active = 1;
139
140          /*
141           * Actions files
142           */
143          for (i = 0; i < MAX_AF_FILES; i++)
144          {
145             if (csp->actions_list[i])
146             {
147                csp->actions_list[i]->active = 1;
148             }
149          }
150
151          /*
152           * Filter files
153           */
154          for (i = 0; i < MAX_AF_FILES; i++)
155          {
156             if (csp->rlist[i])
157             {
158                csp->rlist[i]->active = 1;
159             }
160          }
161
162          /*
163           * Trust file
164           */
165 #ifdef FEATURE_TRUST
166          if (csp->tlist)
167          {
168             csp->tlist->active = 1;
169          }
170 #endif /* def FEATURE_TRUST */
171
172          active_threads++;
173
174          last_active = client_list;
175          client_list = client_list->next;
176       }
177       else
178       /*
179        * This client is not active. Free its resources.
180        */
181       {
182          last_active->next = client_list->next;
183
184          freez(csp->ip_addr_str);
185 #ifdef FEATURE_CLIENT_TAGS
186          freez(csp->client_address);
187 #endif
188          freez(csp->listen_addr_str);
189          freez(csp->client_iob->buf);
190          freez(csp->iob->buf);
191          freez(csp->error_message);
192
193          if (csp->action->flags & ACTION_FORWARD_OVERRIDE &&
194              NULL != csp->fwd)
195          {
196             unload_forward_spec(csp->fwd);
197          }
198          free_http_request(csp->http);
199
200          destroy_list(csp->headers);
201          destroy_list(csp->tags);
202
203          free_current_action(csp->action);
204
205 #ifdef FEATURE_STATISTICS
206          urls_read++;
207          if (csp->flags & CSP_FLAG_REJECTED)
208          {
209             urls_rejected++;
210          }
211 #endif /* def FEATURE_STATISTICS */
212
213          freez(client_list);
214
215          client_list = last_active->next;
216       }
217    }
218
219    nfl = files;
220    fl = files->next;
221
222    while (fl != NULL)
223    {
224       if ((0 == fl->active) && (NULL != fl->unloader))
225       {
226          nfl->next = fl->next;
227
228          (fl->unloader)(fl->f);
229
230          freez(fl->filename);
231          freez(fl);
232
233          fl = nfl->next;
234       }
235       else
236       {
237          nfl = fl;
238          fl = fl->next;
239       }
240    }
241
242    return active_threads;
243
244 }
245
246
247 /*********************************************************************
248  *
249  * Function    :  check_file_changed
250  *
251  * Description :  Helper function to check if a file needs reloading.
252  *                If "current" is still current, return it.  Otherwise
253  *                allocates a new (zeroed) "struct file_list", fills
254  *                in the disk file name and timestamp, and returns it.
255  *
256  * Parameters  :
257  *          1  :  current = The file_list currently being used - will
258  *                          be checked to see if it is out of date.
259  *                          May be NULL (which is treated as out of
260  *                          date).
261  *          2  :  filename = Name of file to check.
262  *          3  :  newfl    = New file list. [Output only]
263  *                           This will be set to NULL, OR a struct
264  *                           file_list newly allocated on the
265  *                           heap, with the filename and lastmodified
266  *                           fields filled, and all others zeroed.
267  *
268  * Returns     :  If file unchanged: 0 (and sets newfl == NULL)
269  *                If file changed: 1 and sets newfl != NULL
270  *                On error: 1 and sets newfl == NULL
271  *
272  *********************************************************************/
273 int check_file_changed(const struct file_list * current,
274                        const char * filename,
275                        struct file_list ** newfl)
276 {
277    struct file_list *fs;
278    struct stat statbuf[1];
279
280    *newfl = NULL;
281
282    if (stat(filename, statbuf) < 0)
283    {
284       /* Error, probably file not found. */
285       return 1;
286    }
287
288    if (current
289        && (current->lastmodified == statbuf->st_mtime)
290        && (0 == strcmp(current->filename, filename)))
291    {
292       return 0;
293    }
294
295    fs = zalloc_or_die(sizeof(struct file_list));
296    fs->filename = strdup_or_die(filename);
297    fs->lastmodified = statbuf->st_mtime;
298
299    if (fs->filename == NULL)
300    {
301       /* Out of memory error */
302       freez (fs);
303       return 1;
304    }
305    *newfl = fs;
306    return 1;
307 }
308
309
310 /*********************************************************************
311  *
312  * Function    :  simple_read_line
313  *
314  * Description :  Read a single line from a file and return it.
315  *                This is basically a version of fgets() that malloc()s
316  *                it's own line buffer.  Note that the buffer will
317  *                always be a multiple of BUFFER_SIZE bytes long.
318  *                Therefore if you are going to keep the string for
319  *                an extended period of time, you should probably
320  *                strdup() it and free() the original, to save memory.
321  *
322  *
323  * Parameters  :
324  *          1  :  dest = destination for newly malloc'd pointer to
325  *                line data.  Will be set to NULL on error.
326  *          2  :  fp = File to read from
327  *          3  :  newline = Standard for newlines in the file.
328  *                Will be unchanged if it's value on input is not
329  *                NEWLINE_UNKNOWN.
330  *                On output, may be changed from NEWLINE_UNKNOWN to
331  *                actual convention in file.
332  *
333  * Returns     :  JB_ERR_OK     on success
334  *                JB_ERR_MEMORY on out-of-memory
335  *                JB_ERR_FILE   on EOF.
336  *
337  *********************************************************************/
338 jb_err simple_read_line(FILE *fp, char **dest, int *newline)
339 {
340    size_t len = 0;
341    size_t buflen = BUFFER_SIZE;
342    char * buf;
343    char * p;
344    int ch;
345    int realnewline = NEWLINE_UNKNOWN;
346
347    if (NULL == (buf = malloc(buflen)))
348    {
349       return JB_ERR_MEMORY;
350    }
351
352    p = buf;
353
354 /*
355  * Character codes.  If you have a weird compiler and the following are
356  * incorrect, you also need to fix NEWLINE() in loaders.h
357  */
358 #define CHAR_CR '\r' /* ASCII 13 */
359 #define CHAR_LF '\n' /* ASCII 10 */
360
361    for (;;)
362    {
363       ch = getc(fp);
364       if (ch == EOF)
365       {
366          if (len > 0)
367          {
368             *p = '\0';
369             *dest = buf;
370             return JB_ERR_OK;
371          }
372          else
373          {
374             free(buf);
375             *dest = NULL;
376             return JB_ERR_FILE;
377          }
378       }
379       else if (ch == CHAR_CR)
380       {
381          ch = getc(fp);
382          if (ch == CHAR_LF)
383          {
384             if (*newline == NEWLINE_UNKNOWN)
385             {
386                *newline = NEWLINE_DOS;
387             }
388          }
389          else
390          {
391             if (ch != EOF)
392             {
393                ungetc(ch, fp);
394             }
395             if (*newline == NEWLINE_UNKNOWN)
396             {
397                *newline = NEWLINE_MAC;
398             }
399          }
400          *p = '\0';
401          *dest = buf;
402          if (*newline == NEWLINE_UNKNOWN)
403          {
404             *newline = realnewline;
405          }
406          return JB_ERR_OK;
407       }
408       else if (ch == CHAR_LF)
409       {
410          *p = '\0';
411          *dest = buf;
412          if (*newline == NEWLINE_UNKNOWN)
413          {
414             *newline = NEWLINE_UNIX;
415          }
416          return JB_ERR_OK;
417       }
418       else if (ch == 0)
419       {
420          *p = '\0';
421          *dest = buf;
422          return JB_ERR_OK;
423       }
424
425       *p++ = (char)ch;
426
427       if (++len >= buflen)
428       {
429          buflen += BUFFER_SIZE;
430          if (NULL == (p = realloc(buf, buflen)))
431          {
432             free(buf);
433             return JB_ERR_MEMORY;
434          }
435          buf = p;
436          p = buf + len;
437       }
438    }
439 }
440
441
442 /*********************************************************************
443  *
444  * Function    :  edit_read_line
445  *
446  * Description :  Read a single non-empty line from a file and return
447  *                it.  Trims comments, leading and trailing whitespace
448  *                and respects escaping of newline and comment char.
449  *                Provides the line in 2 alternative forms: raw and
450  *                preprocessed.
451  *                - raw is the raw data read from the file.  If the
452  *                  line is not modified, then this should be written
453  *                  to the new file.
454  *                - prefix is any comments and blank lines that were
455  *                  read from the file.  If the line is modified, then
456  *                  this should be written out to the file followed
457  *                  by the modified data.  (If this string is non-empty
458  *                  then it will have a newline at the end).
459  *                - data is the actual data that will be parsed
460  *                  further by appropriate routines.
461  *                On EOF, the 3 strings will all be set to NULL and
462  *                0 will be returned.
463  *
464  * Parameters  :
465  *          1  :  fp = File to read from
466  *          2  :  raw_out = destination for newly malloc'd pointer to
467  *                raw line data.  May be NULL if you don't want it.
468  *          3  :  prefix_out = destination for newly malloc'd pointer to
469  *                comments.  May be NULL if you don't want it.
470  *          4  :  data_out = destination for newly malloc'd pointer to
471  *                line data with comments and leading/trailing spaces
472  *                removed, and line continuation performed.  May be
473  *                NULL if you don't want it.
474  *          5  :  newline = Standard for newlines in the file.
475  *                On input, set to value to use or NEWLINE_UNKNOWN.
476  *                On output, may be changed from NEWLINE_UNKNOWN to
477  *                actual convention in file.  May be NULL if you
478  *                don't want it.
479  *          6  :  line_number = Line number in file.  In "lines" as
480  *                reported by a text editor, not lines containing data.
481  *
482  * Returns     :  JB_ERR_OK     on success
483  *                JB_ERR_MEMORY on out-of-memory
484  *                JB_ERR_FILE   on EOF.
485  *
486  *********************************************************************/
487 jb_err edit_read_line(FILE *fp,
488                       char **raw_out,
489                       char **prefix_out,
490                       char **data_out,
491                       int *newline,
492                       unsigned long *line_number)
493 {
494    char *p;          /* Temporary pointer   */
495    char *linebuf;    /* Line read from file */
496    char *linestart;  /* Start of linebuf, usually first non-whitespace char */
497    int contflag = 0; /* Nonzero for line continuation - i.e. line ends '\' */
498    int is_empty = 1; /* Flag if not got any data yet */
499    char *raw    = NULL; /* String to be stored in raw_out    */
500    char *prefix = NULL; /* String to be stored in prefix_out */
501    char *data   = NULL; /* String to be stored in data_out   */
502    int scrapnewline;    /* Used for (*newline) if newline==NULL */
503    jb_err rval = JB_ERR_OK;
504
505    assert(fp);
506    assert(raw_out || data_out);
507    assert(newline == NULL
508        || *newline == NEWLINE_UNKNOWN
509        || *newline == NEWLINE_UNIX
510        || *newline == NEWLINE_DOS
511        || *newline == NEWLINE_MAC);
512
513    if (newline == NULL)
514    {
515       scrapnewline = NEWLINE_UNKNOWN;
516       newline = &scrapnewline;
517    }
518
519    /* Set output parameters to NULL */
520    if (raw_out)
521    {
522       *raw_out    = NULL;
523    }
524    if (prefix_out)
525    {
526       *prefix_out = NULL;
527    }
528    if (data_out)
529    {
530       *data_out   = NULL;
531    }
532
533    /* Set string variables to new, empty strings. */
534
535    if (raw_out)
536    {
537       raw = strdup_or_die("");
538    }
539    if (prefix_out)
540    {
541       prefix = strdup_or_die("");
542    }
543    if (data_out)
544    {
545       data = strdup_or_die("");
546    }
547
548    /* Main loop.  Loop while we need more data & it's not EOF. */
549
550    while ((contflag || is_empty)
551        && (JB_ERR_OK == (rval = simple_read_line(fp, &linebuf, newline))))
552    {
553       if (line_number)
554       {
555          (*line_number)++;
556       }
557       if (raw)
558       {
559          string_append(&raw,linebuf);
560          if (string_append(&raw,NEWLINE(*newline)))
561          {
562             freez(prefix);
563             freez(data);
564             free(linebuf);
565             return JB_ERR_MEMORY;
566          }
567       }
568
569       /* Line continuation? Trim escape and set flag. */
570       p = linebuf + strlen(linebuf) - 1;
571       contflag = ((*linebuf != '\0') && (*p == '\\'));
572       if (contflag)
573       {
574          *p = '\0';
575       }
576
577       /* Trim leading spaces if we're at the start of the line */
578       linestart = linebuf;
579       assert(NULL != data);
580       if (*data == '\0')
581       {
582          /* Trim leading spaces */
583          while (*linestart && isspace((int)(unsigned char)*linestart))
584          {
585             linestart++;
586          }
587       }
588
589       /* Handle comment characters. */
590       p = linestart;
591       while ((p = strchr(p, '#')) != NULL)
592       {
593          /* Found a comment char.. */
594          if ((p != linebuf) && (*(p-1) == '\\'))
595          {
596             /* ..and it's escaped, left-shift the line over the escape. */
597             char *q = p - 1;
598             while ((*q = *(q + 1)) != '\0')
599             {
600                q++;
601             }
602             /* Now scan from just after the "#". */
603          }
604          else
605          {
606             /* Real comment.  Save it... */
607             if (p == linestart)
608             {
609                /* Special case:  Line only contains a comment, so all the
610                 * previous whitespace is considered part of the comment.
611                 * Undo the whitespace skipping, if any.
612                 */
613                linestart = linebuf;
614                p = linestart;
615             }
616             if (prefix)
617             {
618                string_append(&prefix,p);
619                if (string_append(&prefix, NEWLINE(*newline)))
620                {
621                   freez(raw);
622                   freez(data);
623                   free(linebuf);
624                   return JB_ERR_MEMORY;
625                }
626             }
627
628             /* ... and chop off the rest of the line */
629             *p = '\0';
630          }
631       } /* END while (there's a # character) */
632
633       /* Write to the buffer */
634       if (*linestart)
635       {
636          is_empty = 0;
637          if (string_append(&data, linestart))
638          {
639             freez(raw);
640             freez(prefix);
641             free(linebuf);
642             return JB_ERR_MEMORY;
643          }
644       }
645
646       free(linebuf);
647    } /* END while(we need more data) */
648
649    /* Handle simple_read_line() errors - ignore EOF */
650    if ((rval != JB_ERR_OK) && (rval != JB_ERR_FILE))
651    {
652       freez(raw);
653       freez(prefix);
654       freez(data);
655       return rval;
656    }
657
658    if (raw ? (*raw == '\0') : is_empty)
659    {
660       /* EOF and no data there.  (Definition of "data" depends on whether
661        * the caller cares about "raw" or just "data").
662        */
663
664       freez(raw);
665       freez(prefix);
666       freez(data);
667
668       return JB_ERR_FILE;
669    }
670    else
671    {
672       /* Got at least some data */
673
674       /* Remove trailing whitespace */
675       chomp(data);
676
677       if (raw_out)
678       {
679          *raw_out    = raw;
680       }
681       else
682       {
683          freez(raw);
684       }
685       if (prefix_out)
686       {
687          *prefix_out = prefix;
688       }
689       else
690       {
691          freez(prefix);
692       }
693       if (data_out)
694       {
695          *data_out   = data;
696       }
697       else
698       {
699          freez(data);
700       }
701       return JB_ERR_OK;
702    }
703 }
704
705
706 /*********************************************************************
707  *
708  * Function    :  read_config_line
709  *
710  * Description :  Read a single non-empty line from a file and return
711  *                it.  Trims comments, leading and trailing whitespace
712  *                and respects escaping of newline and comment char.
713  *
714  * Parameters  :
715  *          1  :  fp = File to read from
716  *          2  :  linenum = linenumber in file
717  *          3  :  buf = Pointer to a pointer to set to the data buffer.
718  *
719  * Returns     :  NULL on EOF or error
720  *                Otherwise, returns buf.
721  *
722  *********************************************************************/
723 char *read_config_line(FILE *fp, unsigned long *linenum, char **buf)
724 {
725    jb_err err;
726    err = edit_read_line(fp, NULL, NULL, buf, NULL, linenum);
727    if (err)
728    {
729       if (err == JB_ERR_MEMORY)
730       {
731          log_error(LOG_LEVEL_FATAL, "Out of memory loading a config file");
732       }
733       *buf = NULL;
734    }
735    return *buf;
736 }
737
738
739 #ifdef FEATURE_TRUST
740 /*********************************************************************
741  *
742  * Function    :  unload_trustfile
743  *
744  * Description :  Unloads a trustfile.
745  *
746  * Parameters  :
747  *          1  :  f = the data structure associated with the trustfile.
748  *
749  * Returns     :  N/A
750  *
751  *********************************************************************/
752 static void unload_trustfile(void *f)
753 {
754    struct block_spec *cur = (struct block_spec *)f;
755    struct block_spec *next;
756
757    while (cur != NULL)
758    {
759       next = cur->next;
760
761       free_pattern_spec(cur->url);
762       free(cur);
763
764       cur = next;
765    }
766
767 }
768
769
770 #ifdef FEATURE_GRACEFUL_TERMINATION
771 /*********************************************************************
772  *
773  * Function    :  unload_current_trust_file
774  *
775  * Description :  Unloads current trust file - reset to state at
776  *                beginning of program.
777  *
778  * Parameters  :  None
779  *
780  * Returns     :  N/A
781  *
782  *********************************************************************/
783 void unload_current_trust_file(void)
784 {
785    if (current_trustfile)
786    {
787       current_trustfile->unloader = unload_trustfile;
788       current_trustfile = NULL;
789    }
790 }
791 #endif /* FEATURE_GRACEFUL_TERMINATION */
792
793
794 /*********************************************************************
795  *
796  * Function    :  load_trustfile
797  *
798  * Description :  Read and parse a trustfile and add to files list.
799  *
800  * Parameters  :
801  *          1  :  csp = Current client state (buffers, headers, etc...)
802  *
803  * Returns     :  0 => Ok, everything else is an error.
804  *
805  *********************************************************************/
806 int load_trustfile(struct client_state *csp)
807 {
808    FILE *fp;
809
810    struct block_spec *b, *bl;
811    struct pattern_spec **tl;
812
813    char *buf = NULL;
814    int reject, trusted;
815    struct file_list *fs;
816    unsigned long linenum = 0;
817    int trusted_referrers = 0;
818
819    if (!check_file_changed(current_trustfile, csp->config->trustfile, &fs))
820    {
821       /* No need to load */
822       csp->tlist = current_trustfile;
823       return(0);
824    }
825    if (!fs)
826    {
827       goto load_trustfile_error;
828    }
829
830    fs->f = bl = zalloc_or_die(sizeof(*bl));
831
832    if ((fp = fopen(csp->config->trustfile, "r")) == NULL)
833    {
834       goto load_trustfile_error;
835    }
836    log_error(LOG_LEVEL_INFO, "Loading trust file: %s", csp->config->trustfile);
837
838    tl = csp->config->trust_list;
839
840    while (read_config_line(fp, &linenum, &buf) != NULL)
841    {
842       trusted = 0;
843       reject  = 1;
844
845       if (*buf == '+')
846       {
847          trusted = 1;
848          *buf = '~';
849       }
850
851       if (*buf == '~')
852       {
853          char *p;
854          char *q;
855
856          reject = 0;
857          p = buf;
858          q = p+1;
859          while ((*p++ = *q++) != '\0')
860          {
861             /* nop */
862          }
863       }
864
865       /* skip blank lines */
866       if (*buf == '\0')
867       {
868          freez(buf);
869          continue;
870       }
871
872       /* allocate a new node */
873       b = zalloc_or_die(sizeof(*b));
874
875       /* add it to the list */
876       b->next  = bl->next;
877       bl->next = b;
878
879       b->reject = reject;
880
881       /* Save the URL pattern */
882       if (create_pattern_spec(b->url, buf))
883       {
884          fclose(fp);
885          goto load_trustfile_error;
886       }
887
888       /*
889        * save a pointer to URL's spec in the list of trusted URL's, too
890        */
891       if (trusted)
892       {
893          if (++trusted_referrers < MAX_TRUSTED_REFERRERS)
894          {
895             *tl++ = b->url;
896          }
897       }
898       freez(buf);
899    }
900
901    if (trusted_referrers >= MAX_TRUSTED_REFERRERS)
902    {
903       /*
904        * FIXME: ... after Privoxy 3.0.4 is out.
905        */
906        log_error(LOG_LEVEL_ERROR, "Too many trusted referrers. Current limit is %d, you are using %d.\n"
907           "  Additional trusted referrers are treated like ordinary trusted URLs.\n"
908           "  (You can increase this limit by changing MAX_TRUSTED_REFERRERS in project.h and recompiling).",
909           MAX_TRUSTED_REFERRERS, trusted_referrers);
910    }
911
912    *tl = NULL;
913
914    fclose(fp);
915
916    /* the old one is now obsolete */
917    if (current_trustfile)
918    {
919       current_trustfile->unloader = unload_trustfile;
920    }
921
922    fs->next    = files->next;
923    files->next = fs;
924    current_trustfile = fs;
925    csp->tlist = fs;
926
927    return(0);
928
929 load_trustfile_error:
930    log_error(LOG_LEVEL_FATAL, "can't load trustfile '%s': %E",
931       csp->config->trustfile);
932    freez(buf);
933    return(-1);
934
935 }
936 #endif /* def FEATURE_TRUST */
937
938
939 /*********************************************************************
940  *
941  * Function    :  unload_re_filterfile
942  *
943  * Description :  Unload the re_filter list by freeing all chained
944  *                re_filterfile specs and their data.
945  *
946  * Parameters  :
947  *          1  :  f = the data structure associated with the filterfile.
948  *
949  * Returns     :  N/A
950  *
951  *********************************************************************/
952 static void unload_re_filterfile(void *f)
953 {
954    struct re_filterfile_spec *a, *b = (struct re_filterfile_spec *)f;
955
956    while (b != NULL)
957    {
958       a = b->next;
959
960       destroy_list(b->patterns);
961       pcrs_free_joblist(b->joblist);
962       freez(b->name);
963       freez(b->description);
964       freez(b);
965
966       b = a;
967    }
968
969    return;
970 }
971
972 /*********************************************************************
973  *
974  * Function    :  unload_forward_spec
975  *
976  * Description :  Unload the forward spec settings by freeing all
977  *                memory referenced by members and the memory for
978  *                the spec itself.
979  *
980  * Parameters  :
981  *          1  :  fwd = the forward spec.
982  *
983  * Returns     :  N/A
984  *
985  *********************************************************************/
986 void unload_forward_spec(struct forward_spec *fwd)
987 {
988    free_pattern_spec(fwd->url);
989    freez(fwd->gateway_host);
990    freez(fwd->forward_host);
991    free(fwd);
992
993    return;
994 }
995
996
997 #ifdef FEATURE_GRACEFUL_TERMINATION
998 /*********************************************************************
999  *
1000  * Function    :  unload_current_re_filterfile
1001  *
1002  * Description :  Unloads current re_filter file - reset to state at
1003  *                beginning of program.
1004  *
1005  * Parameters  :  None
1006  *
1007  * Returns     :  N/A
1008  *
1009  *********************************************************************/
1010 void unload_current_re_filterfile(void)
1011 {
1012    int i;
1013
1014    for (i = 0; i < MAX_AF_FILES; i++)
1015    {
1016       if (current_re_filterfile[i])
1017       {
1018          current_re_filterfile[i]->unloader = unload_re_filterfile;
1019          current_re_filterfile[i] = NULL;
1020       }
1021    }
1022 }
1023 #endif
1024
1025
1026 /*********************************************************************
1027  *
1028  * Function    :  load_re_filterfiles
1029  *
1030  * Description :  Loads all the filterfiles.
1031  *                Generate a chained list of re_filterfile_spec's from
1032  *                the "FILTER: " blocks, compiling all their substitutions
1033  *                into chained lists of pcrs_job structs.
1034  *
1035  * Parameters  :
1036  *          1  :  csp = Current client state (buffers, headers, etc...)
1037  *
1038  * Returns     :  0 => Ok, everything else is an error.
1039  *
1040  *********************************************************************/
1041 int load_re_filterfiles(struct client_state *csp)
1042 {
1043    int i;
1044    int result;
1045
1046    for (i = 0; i < MAX_AF_FILES; i++)
1047    {
1048       if (csp->config->re_filterfile[i])
1049       {
1050          result = load_one_re_filterfile(csp, i);
1051          if (result)
1052          {
1053             return result;
1054          }
1055       }
1056       else if (current_re_filterfile[i])
1057       {
1058          current_re_filterfile[i]->unloader = unload_re_filterfile;
1059          current_re_filterfile[i] = NULL;
1060       }
1061    }
1062
1063    return 0;
1064 }
1065
1066
1067 /*********************************************************************
1068  *
1069  * Function    :  load_one_re_filterfile
1070  *
1071  * Description :  Load a re_filterfile.
1072  *                Generate a chained list of re_filterfile_spec's from
1073  *                the "FILTER: " blocks, compiling all their substitutions
1074  *                into chained lists of pcrs_job structs.
1075  *
1076  * Parameters  :
1077  *          1  :  csp = Current client state (buffers, headers, etc...)
1078  *
1079  * Returns     :  0 => Ok, everything else is an error.
1080  *
1081  *********************************************************************/
1082 int load_one_re_filterfile(struct client_state *csp, int fileid)
1083 {
1084    FILE *fp;
1085
1086    struct re_filterfile_spec *new_bl, *bl = NULL;
1087    struct file_list *fs;
1088
1089    char *buf = NULL;
1090    int error;
1091    unsigned long linenum = 0;
1092    pcrs_job *dummy, *lastjob = NULL;
1093
1094    /*
1095     * No need to reload if unchanged
1096     */
1097    if (!check_file_changed(current_re_filterfile[fileid], csp->config->re_filterfile[fileid], &fs))
1098    {
1099       csp->rlist[fileid] = current_re_filterfile[fileid];
1100       return(0);
1101    }
1102    if (!fs)
1103    {
1104       goto load_re_filterfile_error;
1105    }
1106
1107    /*
1108     * Open the file or fail
1109     */
1110    if ((fp = fopen(csp->config->re_filterfile[fileid], "r")) == NULL)
1111    {
1112       goto load_re_filterfile_error;
1113    }
1114
1115    log_error(LOG_LEVEL_INFO, "Loading filter file: %s", csp->config->re_filterfile[fileid]);
1116
1117    /*
1118     * Read line by line
1119     */
1120    while (read_config_line(fp, &linenum, &buf) != NULL)
1121    {
1122       enum filter_type new_filter = FT_INVALID_FILTER;
1123
1124       if (strncmp(buf, "FILTER:", 7) == 0)
1125       {
1126          new_filter = FT_CONTENT_FILTER;
1127       }
1128       else if (strncmp(buf, "SERVER-HEADER-FILTER:", 21) == 0)
1129       {
1130          new_filter = FT_SERVER_HEADER_FILTER;
1131       }
1132       else if (strncmp(buf, "CLIENT-HEADER-FILTER:", 21) == 0)
1133       {
1134          new_filter = FT_CLIENT_HEADER_FILTER;
1135       }
1136       else if (strncmp(buf, "CLIENT-HEADER-TAGGER:", 21) == 0)
1137       {
1138          new_filter = FT_CLIENT_HEADER_TAGGER;
1139       }
1140       else if (strncmp(buf, "SERVER-HEADER-TAGGER:", 21) == 0)
1141       {
1142          new_filter = FT_SERVER_HEADER_TAGGER;
1143       }
1144 #ifdef FEATURE_EXTERNAL_FILTERS
1145       else if (strncmp(buf, "EXTERNAL-FILTER:", 16) == 0)
1146       {
1147          new_filter = FT_EXTERNAL_CONTENT_FILTER;
1148       }
1149 #endif
1150
1151       /*
1152        * If this is the head of a new filter block, make it a
1153        * re_filterfile spec of its own and chain it to the list:
1154        */
1155       if (new_filter != FT_INVALID_FILTER)
1156       {
1157          new_bl = zalloc_or_die(sizeof(*bl));
1158          if (new_filter == FT_CONTENT_FILTER)
1159          {
1160             new_bl->name = chomp(buf + 7);
1161          }
1162 #ifdef FEATURE_EXTERNAL_FILTERS
1163          else if (new_filter == FT_EXTERNAL_CONTENT_FILTER)
1164          {
1165             new_bl->name = chomp(buf + 16);
1166          }
1167 #endif
1168          else
1169          {
1170             new_bl->name = chomp(buf + 21);
1171          }
1172          new_bl->type = new_filter;
1173
1174          /*
1175           * If a filter description is available,
1176           * encode it to HTML and save it.
1177           */
1178          if (NULL != (new_bl->description = strpbrk(new_bl->name, " \t")))
1179          {
1180             *new_bl->description++ = '\0';
1181             new_bl->description = html_encode(chomp(new_bl->description));
1182             if (NULL == new_bl->description)
1183             {
1184                new_bl->description = strdup_or_die("Out of memory while "
1185                   "encoding filter description to HTML");
1186             }
1187          }
1188          else
1189          {
1190             new_bl->description = strdup_or_die("No description available");
1191          }
1192
1193          new_bl->name = strdup_or_die(chomp(new_bl->name));
1194
1195          /*
1196           * If this is the first filter block, chain it
1197           * to the file_list rather than its (nonexistant)
1198           * predecessor
1199           */
1200          if (fs->f == NULL)
1201          {
1202             fs->f = new_bl;
1203          }
1204          else
1205          {
1206             assert(NULL != bl);
1207             bl->next = new_bl;
1208          }
1209          bl = new_bl;
1210
1211          log_error(LOG_LEVEL_RE_FILTER, "Reading in filter \"%s\" (\"%s\")", bl->name, bl->description);
1212
1213          freez(buf);
1214          continue;
1215       }
1216
1217 #ifdef FEATURE_EXTERNAL_FILTERS
1218       if ((bl != NULL) && (bl->type == FT_EXTERNAL_CONTENT_FILTER))
1219       {
1220          /* Save the code as "pattern", but do not compile anything. */
1221          if (bl->patterns->first != NULL)
1222          {
1223             log_error(LOG_LEVEL_FATAL, "External filter '%s' contains several jobss. "
1224                "Did you forget to escape a line break?",
1225                bl->name);
1226          }
1227          error = enlist(bl->patterns, buf);
1228          if (JB_ERR_MEMORY == error)
1229          {
1230             log_error(LOG_LEVEL_FATAL,
1231                "Out of memory while enlisting external filter code \'%s\' for filter %s.",
1232                buf, bl->name);
1233          }
1234          freez(buf);
1235          continue;
1236       }
1237 #endif
1238       if (bl != NULL)
1239       {
1240          /*
1241           * Save the expression, make it a pcrs_job
1242           * and chain it into the current filter's joblist
1243           */
1244          error = enlist(bl->patterns, buf);
1245          if (JB_ERR_MEMORY == error)
1246          {
1247             log_error(LOG_LEVEL_FATAL,
1248                "Out of memory while enlisting re_filter job \'%s\' for filter %s.", buf, bl->name);
1249          }
1250          assert(JB_ERR_OK == error);
1251
1252          if (pcrs_job_is_dynamic(buf))
1253          {
1254             /*
1255              * Dynamic pattern that might contain variables
1256              * and has to be recompiled for every request
1257              */
1258             if (bl->joblist != NULL)
1259             {
1260                 pcrs_free_joblist(bl->joblist);
1261                 bl->joblist = NULL;
1262             }
1263             bl->dynamic = 1;
1264             log_error(LOG_LEVEL_RE_FILTER,
1265                "Adding dynamic re_filter job \'%s\' to filter %s succeeded.", buf, bl->name);
1266             freez(buf);
1267             continue;
1268          }
1269          else if (bl->dynamic)
1270          {
1271             /*
1272              * A previous job was dynamic and as we
1273              * recompile the whole filter anyway, it
1274              * makes no sense to compile this job now.
1275              */
1276             log_error(LOG_LEVEL_RE_FILTER,
1277                "Adding static re_filter job \'%s\' to dynamic filter %s succeeded.", buf, bl->name);
1278             freez(buf);
1279             continue;
1280          }
1281
1282          if ((dummy = pcrs_compile_command(buf, &error)) == NULL)
1283          {
1284             log_error(LOG_LEVEL_ERROR,
1285                "Adding re_filter job \'%s\' to filter %s failed: %s",
1286                buf, bl->name, pcrs_strerror(error));
1287             freez(buf);
1288             continue;
1289          }
1290          else
1291          {
1292             if (bl->joblist == NULL)
1293             {
1294                bl->joblist = dummy;
1295             }
1296             else if (NULL != lastjob)
1297             {
1298                lastjob->next = dummy;
1299             }
1300             lastjob = dummy;
1301             log_error(LOG_LEVEL_RE_FILTER, "Adding re_filter job \'%s\' to filter %s succeeded.", buf, bl->name);
1302          }
1303       }
1304       else
1305       {
1306          log_error(LOG_LEVEL_ERROR, "Ignoring job %s outside filter block in %s, line %d",
1307             buf, csp->config->re_filterfile[fileid], linenum);
1308       }
1309       freez(buf);
1310    }
1311
1312    fclose(fp);
1313
1314    /*
1315     * Schedule the now-obsolete old data for unloading
1316     */
1317    if (NULL != current_re_filterfile[fileid])
1318    {
1319       current_re_filterfile[fileid]->unloader = unload_re_filterfile;
1320    }
1321
1322    /*
1323     * Chain this file into the global list of loaded files
1324     */
1325    fs->next    = files->next;
1326    files->next = fs;
1327    current_re_filterfile[fileid] = fs;
1328    csp->rlist[fileid] = fs;
1329
1330    return(0);
1331
1332 load_re_filterfile_error:
1333    log_error(LOG_LEVEL_FATAL, "can't load re_filterfile '%s': %E",
1334              csp->config->re_filterfile[fileid]);
1335    return(-1);
1336
1337 }
1338
1339
1340 /*********************************************************************
1341  *
1342  * Function    :  add_loader
1343  *
1344  * Description :  Called from `load_config'.  Called once for each input
1345  *                file found in config.
1346  *
1347  * Parameters  :
1348  *          1  :  loader = pointer to a function that can parse and load
1349  *                the appropriate config file.
1350  *          2  :  config = The configuration_spec to add the loader to.
1351  *
1352  * Returns     :  N/A
1353  *
1354  *********************************************************************/
1355 void add_loader(int (*loader)(struct client_state *),
1356                 struct configuration_spec * config)
1357 {
1358    int i;
1359
1360    for (i = 0; i < NLOADERS; i++)
1361    {
1362       if (config->loaders[i] == NULL)
1363       {
1364          config->loaders[i] = loader;
1365          break;
1366       }
1367    }
1368
1369 }
1370
1371
1372 /*********************************************************************
1373  *
1374  * Function    :  run_loader
1375  *
1376  * Description :  Called from `load_config' and `listen_loop'.  This
1377  *                function keeps the "csp" current with any file mods
1378  *                since the last loop.  If a file is unchanged, the
1379  *                loader functions do NOT reload the file.
1380  *
1381  * Parameters  :
1382  *          1  :  csp = Current client state (buffers, headers, etc...)
1383  *                      Must be non-null.  Reads: "csp->config"
1384  *                      Writes: various data members.
1385  *
1386  * Returns     :  0 => Ok, everything else is an error.
1387  *
1388  *********************************************************************/
1389 int run_loader(struct client_state *csp)
1390 {
1391    int ret = 0;
1392    int i;
1393
1394    for (i = 0; i < NLOADERS; i++)
1395    {
1396       if (csp->config->loaders[i] == NULL)
1397       {
1398          break;
1399       }
1400       ret |= (csp->config->loaders[i])(csp);
1401    }
1402    return(ret);
1403
1404 }
1405
1406 /*********************************************************************
1407  *
1408  * Function    :  file_has_been_modified
1409  *
1410  * Description :  Helper function to check if a file has been changed
1411  *
1412  * Parameters  :
1413  *          1  : filename = The name of the file to check
1414  *          2  : last_known_modification = The time of the last known
1415  *                                         modification
1416  *
1417  * Returns     :  TRUE if the file has been changed,
1418  *                FALSE otherwise.
1419  *
1420  *********************************************************************/
1421 static int file_has_been_modified(const char *filename, time_t last_know_modification)
1422 {
1423    struct stat statbuf[1];
1424
1425    if (stat(filename, statbuf) < 0)
1426    {
1427       /* Error, probably file not found which counts as change. */
1428       return 1;
1429    }
1430
1431    return (last_know_modification != statbuf->st_mtime);
1432 }
1433
1434
1435 /*********************************************************************
1436  *
1437  * Function    :  any_loaded_file_changed
1438  *
1439  * Description :  Helper function to check if any loaded file has been
1440  *                changed since the time it has been loaded.
1441  *
1442  *                XXX: Should we cache the return value for x seconds?
1443  *
1444  * Parameters  :
1445  *          1  : files_to_check = List of files to check
1446  *
1447  * Returns     : TRUE if any file has been changed,
1448  *               FALSE otherwise.
1449  *
1450  *********************************************************************/
1451 int any_loaded_file_changed(const struct client_state *csp)
1452 {
1453    const struct file_list *file_to_check = csp->config->config_file_list;
1454    int i;
1455
1456    if (file_has_been_modified(file_to_check->filename, file_to_check->lastmodified))
1457    {
1458       return TRUE;
1459    }
1460
1461    for (i = 0; i < MAX_AF_FILES; i++)
1462    {
1463       if (csp->actions_list[i])
1464       {
1465          file_to_check = csp->actions_list[i];
1466          if (file_has_been_modified(file_to_check->filename, file_to_check->lastmodified))
1467          {
1468             return TRUE;
1469          }
1470       }
1471    }
1472
1473    for (i = 0; i < MAX_AF_FILES; i++)
1474    {
1475       if (csp->rlist[i])
1476       {
1477          file_to_check = csp->rlist[i];
1478          if (file_has_been_modified(file_to_check->filename, file_to_check->lastmodified))
1479          {
1480             return TRUE;
1481          }
1482       }
1483    }
1484
1485 #ifdef FEATURE_TRUST
1486    if (csp->tlist)
1487    {
1488       if (file_has_been_modified(csp->tlist->filename, csp->tlist->lastmodified))
1489       {
1490          return TRUE;
1491       }
1492    }
1493 #endif /* def FEATURE_TRUST */
1494
1495    return FALSE;
1496 }
1497
1498
1499 /*
1500   Local Variables:
1501   tab-width: 3
1502   end:
1503 */