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