1 const char loaders_rcs[] = "$Id: loaders.c,v 1.1.1.1 2001/05/15 13:58:59 oes Exp $";
2 /*********************************************************************
4 * File : $Source: /cvsroot/ijbswa/current/loaders.c,v $
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.
11 * Copyright : Written by and Copyright (C) 2001 the SourceForge
12 * IJBSWA team. http://ijbswa.sourceforge.net
14 * Based on the Internet Junkbuster originally written
15 * by and Copyright (C) 1997 Anonymous Coders and
16 * Junkbusters Corporation. http://www.junkbusters.com
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.
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.
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.
38 * Revision 1.1.1.1 2001/05/15 13:58:59 oes
39 * Initial import of version 2.9.3 source tree
42 *********************************************************************/
49 #include <sys/types.h>
71 #ifndef SPLIT_PROXY_ARGS
74 #endif /* ndef SPLIT_PROXY_ARGS */
76 const char loaders_h_rcs[] = LOADERS_H_VERSION;
78 /* Fix a problem with Solaris. There should be no effect on other
80 * Solaris's isspace() is a macro which uses it's argument directly
81 * as an array index. Therefore we need to make sure that high-bit
82 * characters generate +ve values, and ideally we also want to make
83 * the argument match the declared parameter type of "int".
85 #define ijb_isspace(__X) isspace((int)(unsigned char)(__X))
89 static int (*loaders[NLOADERS])(struct client_state *);
93 * Currently active files.
94 * These are also entered in the main linked list of files.
96 static struct file_list *current_blockfile = NULL;
97 static struct file_list *current_cookiefile = NULL;
98 static struct file_list *current_forwardfile = NULL;
101 static struct file_list *current_aclfile = NULL;
102 #endif /* def ACL_FILES */
104 #ifdef USE_IMAGE_LIST
105 static struct file_list *current_imagefile = NULL;
106 #endif /* def USE_IMAGE_LIST */
109 static struct file_list * current_popupfile = NULL;
110 #endif /* def KILLPOPUPS */
113 static struct file_list *current_trustfile = NULL;
114 #endif /* def TRUST_FILES */
117 static struct file_list *current_re_filterfile = NULL;
118 #endif /* def PCRS */
121 /*********************************************************************
125 * Description : Basically a mark and sweep garbage collector, it is run
126 * (by the parent thread) every once in a while to reclaim memory.
128 * It uses a mark and sweep strategy:
129 * 1) mark all files as inactive
131 * 2) check with each client:
132 * if it is active, mark its files as active
133 * if it is inactive, free its resources
135 * 3) free the resources of all of the files that
136 * are still marked as inactive (and are obsolete).
138 * N.B. files that are not obsolete don't have an unloader defined.
144 *********************************************************************/
147 struct file_list *fl, *nfl;
148 struct client_state *csp, *ncsp;
150 /* clear all of the file's active flags */
151 for ( fl = files->next; NULL != fl; fl = fl->next )
156 for (csp = clients; csp && (ncsp = csp->next) ; csp = csp->next)
160 /* mark this client's files as active */
162 if (ncsp->blist) /* block files */
164 ncsp->blist->active = 1;
167 if (ncsp->clist) /* cookie files */
169 ncsp->clist->active = 1;
172 /* FIXME: These were left out of the "10" release. Should they be here? */
173 if (ncsp->flist) /* forward files */
175 ncsp->flist->active = 1;
179 if (ncsp->alist) /* acl files */
181 ncsp->alist->active = 1;
183 #endif /* def ACL_FILES */
185 #ifdef USE_IMAGE_LIST
186 if (ncsp->ilist) /* image files */
188 ncsp->ilist->active = 1;
190 #endif /* def USE_IMAGE_LIST */
193 if (ncsp->plist) /* killpopup files */
195 ncsp->plist->active = 1;
197 #endif /* def KILLPOPUPS */
200 if (ncsp->rlist) /* perl re files */
202 ncsp->rlist->active = 1;
204 #endif /* def PCRS */
207 if (ncsp->tlist) /* trust files */
209 ncsp->tlist->active = 1;
211 #endif /* def TRUST_FILES */
216 /* this client one is not active, release its resources */
217 csp->next = ncsp->next;
219 freez(ncsp->ip_addr_str);
220 freez(ncsp->referrer);
221 freez(ncsp->x_forwarded);
222 freez(ncsp->ip_addr_str);
223 freez(ncsp->iob->buf);
225 free_http_request(ncsp->http);
227 destroy_list(ncsp->headers);
228 destroy_list(ncsp->cookie_list);
236 #endif /* def STATISTICS */
242 for (fl = files; fl && (nfl = fl->next) ; fl = fl->next)
244 if ( ( 0 == nfl->active ) && ( NULL != nfl->unloader ) )
246 fl->next = nfl->next;
248 (nfl->unloader)(nfl->f);
250 #ifndef SPLIT_PROXY_ARGS
251 freez(nfl->proxy_args);
252 #endif /* ndef SPLIT_PROXY_ARGS */
254 freez(nfl->filename);
263 /*********************************************************************
265 * Function : unload_url
267 * Description : Called from the "unloaders". Freez the url
268 * structure elements.
271 * 1 : url = pointer to a url_spec structure.
275 *********************************************************************/
276 static void unload_url(struct url_spec *url)
278 if (url == NULL) return;
297 /*********************************************************************
299 * Function : unload_aclfile
301 * Description : Unloads an aclfile.
304 * 1 : f = the data structure associated with the aclfile.
308 *********************************************************************/
309 static void unload_aclfile(void *f)
311 struct access_control_list *b = (struct access_control_list *)f;
312 if (b == NULL) return;
314 unload_aclfile(b->next);
319 #endif /* def ACL_FILES */
321 /*********************************************************************
323 * Function : unload_blockfile
325 * Description : Unloads a blockfile.
328 * 1 : f = the data structure associated with the blockfile.
332 *********************************************************************/
333 static void unload_blockfile(void *f)
335 struct block_spec *b = (struct block_spec *)f;
336 if (b == NULL) return;
338 unload_blockfile(b->next);
347 #ifdef USE_IMAGE_LIST
348 /*********************************************************************
350 * Function : unload_imagefile
352 * Description : Unloads an imagefile.
355 * 1 : f = the data structure associated with the imagefile.
359 *********************************************************************/
360 static void unload_imagefile(void *f)
362 struct block_spec *b = (struct block_spec *)f;
363 if (b == NULL) return;
365 unload_imagefile(b->next);
372 #endif /* def USE_IMAGE_LIST */
375 /*********************************************************************
377 * Function : unload_cookiefile
379 * Description : Unloads a cookiefile.
382 * 1 : f = the data structure associated with the cookiefile.
386 *********************************************************************/
387 static void unload_cookiefile(void *f)
389 struct cookie_spec *b = (struct cookie_spec *)f;
390 if (b == NULL) return;
392 unload_cookiefile(b->next);
402 /*********************************************************************
404 * Function : unload_trustfile
406 * Description : Unloads a trustfile.
409 * 1 : f = the data structure associated with the trustfile.
413 *********************************************************************/
414 static void unload_trustfile(void *f)
416 struct block_spec *b = (struct block_spec *)f;
417 if (b == NULL) return;
419 unload_trustfile(b->next);
426 #endif /* def TRUST_FILES */
429 /*********************************************************************
431 * Function : unload_forwardfile
433 * Description : Unloads a forwardfile.
436 * 1 : f = the data structure associated with the forwardfile.
440 *********************************************************************/
441 static void unload_forwardfile(void *f)
443 struct forward_spec *b = (struct forward_spec *)f;
444 if (b == NULL) return;
446 unload_forwardfile(b->next);
450 freez(b->gw->gateway_host);
451 freez(b->gw->forward_host);
459 /*********************************************************************
461 * Function : unload_re_filterfile
463 * Description : Unload the re_filter list.
466 * 1 : f = the data structure associated with the filterfile.
470 *********************************************************************/
471 static void unload_re_filterfile(void *f)
474 struct re_filterfile_spec *b = (struct re_filterfile_spec *)f;
476 if (b == NULL) return;
478 destroy_list(b->patterns);
480 joblist = b->joblist;
481 while ( NULL != (joblist = pcrs_free_job(joblist)) ) {}
486 #endif /* def PCRS */
490 /*********************************************************************
492 * Function : unload_popupfile
494 * Description : Free the lists of blocked, and allowed popup sites.
497 * 1 : csp = Current client state (buffers, headers, etc...)
501 *********************************************************************/
502 static void unload_popupfile(void * b)
504 struct popup_settings * data = (struct popup_settings *) b;
505 struct popup_blocklist * cur = NULL;
506 struct popup_blocklist * temp= NULL;
508 /* Free the blocked list. */
513 freez (cur->host_name);
517 data->blocked = NULL;
519 /* Free the allowed list. */
524 freez (cur->host_name);
528 data->allowed = NULL;
531 #endif /* def KILLPOPUPS */
534 /*********************************************************************
536 * Function : check_file_changed
538 * Description : Helper function to check if a file needs reloading.
539 * If "current" is still current, return it. Otherwise
540 * allocates a new (zeroed) "struct file_list", fills
541 * in the disk file name and timestamp, and returns it.
544 * 1 : current = The file_list currently being used - will
545 * be checked to see if it is out of date.
546 * May be NULL (which is treated as out of
548 * 2 : filename = Name of file to check.
549 * 3 : newfl = New file list. [Output only]
550 * This will be set to NULL, OR a struct
551 * file_list newly allocated on the
552 * heap, with the filename and lastmodified
553 * fields filled, standard header giving file
554 * name in proxy_args, and all others zeroed.
555 * (proxy_args is only filled in if
556 * SPLIT_PROXY_ARGS and !suppress_blocklists).
558 * Returns : If file unchanged: 0 (and sets newfl == NULL)
559 * If file changed: 1 and sets newfl != NULL
560 * On error: 1 and sets newfl == NULL
562 *********************************************************************/
563 static int check_file_changed(const struct file_list * current,
564 const char * filename,
565 struct file_list ** newfl)
567 struct file_list *fs;
568 struct stat statbuf[1];
572 if (stat(filename, statbuf) < 0)
574 /* Error, probably file not found. */
579 && (current->lastmodified == statbuf->st_mtime)
580 && (0 == strcmp(current->filename, filename)))
585 fs = (struct file_list *)zalloc(sizeof(struct file_list));
589 /* Out of memory error */
593 fs->filename = strdup(filename);
594 fs->lastmodified = statbuf->st_mtime;
596 if (fs->filename == NULL)
598 /* Out of memory error */
603 #ifndef SPLIT_PROXY_ARGS
604 if (!suppress_blocklists)
606 char * p = html_encode(filename);
609 fs->proxy_args = strsav(fs->proxy_args, "<h2>The file `");
610 fs->proxy_args = strsav(fs->proxy_args, p);
611 fs->proxy_args = strsav(fs->proxy_args,
612 "' contains the following patterns</h2>\n");
615 fs->proxy_args = strsav(fs->proxy_args, "<pre>");
617 #endif /* ndef SPLIT_PROXY_ARGS */
624 /*********************************************************************
626 * Function : read_config_line
628 * Description : Read a single non-empty line from a file and return
629 * it. Trims comments, leading and trailing whitespace.
630 * Also wites the file to fs->proxy_args.
633 * 1 : buf = Buffer to use.
634 * 2 : buflen = Size of buffer in bytes.
635 * 3 : fp = File to read from
636 * 4 : fs = File will be written to fs->proxy_args. May
637 * be NULL to disable this feature.
639 * Returns : NULL on EOF or error
640 * Otherwise, returns buf.
642 *********************************************************************/
643 char *read_config_line(char *buf, int buflen, FILE *fp, struct file_list *fs)
646 char linebuf[BUFSIZ];
648 while (fgets(linebuf, sizeof(linebuf), fp))
650 #ifndef SPLIT_PROXY_ARGS
651 if (fs && !suppress_blocklists)
653 char *html_line = html_encode(linebuf);
654 if (html_line != NULL)
656 fs->proxy_args = strsav(fs->proxy_args, html_line);
659 fs->proxy_args = strsav(fs->proxy_args, "<br>");
661 #endif /* ndef SPLIT_PROXY_ARGS */
663 /* Trim off newline and any comment */
664 if ((p = strpbrk(linebuf, "\r\n#")) != NULL)
669 /* Trim leading whitespace */
671 while (*p && ijb_isspace(*p))
678 /* There is something other than whitespace on the line. */
680 /* Move the data to the start of buf */
683 /* strcpy that can cope with overlap. */
685 while ((*q++ = *p++) != '\0')
691 /* Trim trailing whitespace */
692 p = linebuf + strlen(linebuf) - 1;
695 * Note: the (p >= retval) below is paranoia, it's not really needed.
696 * When p == retval then ijb_isspace(*p) will be false and we'll drop
699 while ((p >= linebuf) && ijb_isspace(*p))
705 /* More paranoia. This if statement is always true. */
708 strcpy(buf, linebuf);
720 /*********************************************************************
722 * Function : load_aclfile
724 * Description : Read and parse an aclfile and add to files list.
727 * 1 : csp = Current client state (buffers, headers, etc...)
729 * Returns : 0 => Ok, everything else is an error.
731 *********************************************************************/
732 int load_aclfile(struct client_state *csp)
735 char buf[BUFSIZ], *v[3], *p;
737 struct access_control_list *a, *bl;
738 struct file_list *fs;
740 if (!check_file_changed(current_aclfile, aclfile, &fs))
742 /* No need to load */
745 csp->alist = current_aclfile;
751 goto load_aclfile_error;
754 fs->f = bl = (struct access_control_list *)zalloc(sizeof(*bl));
759 goto load_aclfile_error;
762 fp = fopen(aclfile, "r");
766 goto load_aclfile_error;
769 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
771 i = ssplit(buf, " \t", v, SZ(v), 1, 1);
773 /* allocate a new node */
774 a = (struct access_control_list *) zalloc(sizeof(*a));
782 goto load_aclfile_error;
785 /* add it to the list */
792 if (acl_addr(v[2], a->dst) < 0)
794 goto load_aclfile_error;
799 if (acl_addr(v[1], a->src) < 0)
801 goto load_aclfile_error;
805 if (strcmpic(p, "permit") == 0)
807 a->action = ACL_PERMIT;
811 if (strcmpic(p, "deny") == 0)
813 a->action = ACL_DENY;
819 goto load_aclfile_error;
825 #ifndef SPLIT_PROXY_ARGS
826 if (!suppress_blocklists)
828 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
830 #endif /* ndef SPLIT_PROXY_ARGS */
834 current_aclfile->unloader = unload_aclfile;
837 fs->next = files->next;
839 current_aclfile = fs;
849 log_error(LOG_LEVEL_ERROR, "can't load access control list %s: %E", aclfile);
853 #endif /* def ACL_FILES */
856 /*********************************************************************
858 * Function : load_blockfile
860 * Description : Read and parse a blockfile and add to files list.
863 * 1 : csp = Current client state (buffers, headers, etc...)
865 * Returns : 0 => Ok, everything else is an error.
867 *********************************************************************/
868 int load_blockfile(struct client_state *csp)
872 struct block_spec *b, *bl;
873 char buf[BUFSIZ], *p, *q;
875 struct file_list *fs;
876 struct url_spec url[1];
878 if (!check_file_changed(current_blockfile, blockfile, &fs))
880 /* No need to load */
883 csp->blist = current_blockfile;
889 goto load_blockfile_error;
892 fs->f = bl = (struct block_spec *) zalloc(sizeof(*bl));
895 goto load_blockfile_error;
898 if ((fp = fopen(blockfile, "r")) == NULL)
900 goto load_blockfile_error;
903 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
912 while ((*p++ = *q++))
918 /* skip lines containing only ~ */
924 /* allocate a new node */
925 if (((b = zalloc(sizeof(*b))) == NULL)
927 || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
932 goto load_blockfile_error;
935 /* add it to the list */
939 /* save a copy of the orignal specification */
940 if ((b->url->spec = strdup(buf)) == NULL)
943 goto load_blockfile_error;
948 if ((p = strchr(buf, '/')))
950 b->url->path = strdup(p);
951 b->url->pathlen = strlen(b->url->path);
965 sprintf(rebuf, "^(%s)", b->url->path);
967 errcode = regcomp(b->url->preg, rebuf,
968 (REG_EXTENDED|REG_NOSUB|REG_ICASE));
974 b->url->preg, buf, sizeof(buf));
978 log_error(LOG_LEVEL_ERROR, "error compiling %s: %s\n",
981 goto load_blockfile_error;
989 if ((p = strchr(buf, ':')) == NULL)
1001 if ((b->url->domain = strdup(buf)) == NULL)
1004 goto load_blockfile_error;
1007 /* split domain into components */
1008 *url = dsplit(b->url->domain);
1009 b->url->dbuf = url->dbuf;
1010 b->url->dcnt = url->dcnt;
1011 b->url->dvec = url->dvec;
1016 #ifndef SPLIT_PROXY_ARGS
1017 if (!suppress_blocklists)
1019 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1021 #endif /* ndef SPLIT_PROXY_ARGS */
1023 /* the old one is now obsolete */
1024 if (current_blockfile)
1026 current_blockfile->unloader = unload_blockfile;
1029 fs->next = files->next;
1031 current_blockfile = fs;
1040 load_blockfile_error:
1041 log_error(LOG_LEVEL_ERROR, "can't load blockfile '%s': %E", blockfile);
1047 #ifdef USE_IMAGE_LIST
1048 /*********************************************************************
1050 * Function : load_imagefile
1052 * Description : Read and parse an imagefile and add to files list.
1055 * 1 : csp = Current client state (buffers, headers, etc...)
1057 * Returns : 0 => Ok, everything else is an error.
1059 *********************************************************************/
1060 int load_imagefile(struct client_state *csp)
1064 struct block_spec *b, *bl;
1065 char buf[BUFSIZ], *p, *q;
1067 struct file_list *fs;
1068 struct url_spec url[1];
1070 if (!check_file_changed(current_imagefile, imagefile, &fs))
1072 /* No need to load */
1075 csp->ilist = current_imagefile;
1081 goto load_imagefile_error;
1084 fs->f = bl = (struct block_spec *)zalloc(sizeof(*bl));
1087 goto load_imagefile_error;
1090 if ((fp = fopen(imagefile, "r")) == NULL)
1092 goto load_imagefile_error;
1095 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1104 while ((*p++ = *q++))
1110 /* skip lines containing only ~ */
1116 /* allocate a new node */
1117 if (((b = zalloc(sizeof(*b))) == NULL)
1119 || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
1124 goto load_imagefile_error;
1127 /* add it to the list */
1131 /* save a copy of the orignal specification */
1132 if ((b->url->spec = strdup(buf)) == NULL)
1135 goto load_imagefile_error;
1140 if ((p = strchr(buf, '/')))
1142 b->url->path = strdup(p);
1143 b->url->pathlen = strlen(b->url->path);
1148 b->url->path = NULL;
1149 b->url->pathlen = 0;
1157 sprintf(rebuf, "^(%s)", b->url->path);
1159 errcode = regcomp(b->url->preg, rebuf,
1160 (REG_EXTENDED|REG_NOSUB|REG_ICASE));
1166 b->url->preg, buf, sizeof(buf));
1170 log_error(LOG_LEVEL_ERROR, "error compiling %s: %s",
1173 goto load_imagefile_error;
1178 freez(b->url->preg);
1181 if ((p = strchr(buf, ':')) == NULL)
1191 b->url->port = port;
1193 if ((b->url->domain = strdup(buf)) == NULL)
1196 goto load_imagefile_error;
1199 /* split domain into components */
1200 *url = dsplit(b->url->domain);
1201 b->url->dbuf = url->dbuf;
1202 b->url->dcnt = url->dcnt;
1203 b->url->dvec = url->dvec;
1205 #ifndef SPLIT_PROXY_ARGS
1206 if (!suppress_blocklists)
1207 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1208 #endif /* ndef SPLIT_PROXY_ARGS */
1212 #ifndef SPLIT_PROXY_ARGS
1213 if (!suppress_blocklists)
1215 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1217 #endif /* ndef SPLIT_PROXY_ARGS */
1219 /* the old one is now obsolete */
1220 if (current_imagefile)
1222 current_imagefile->unloader = unload_imagefile;
1225 fs->next = files->next;
1227 current_imagefile = fs;
1236 load_imagefile_error:
1237 log_error(LOG_LEVEL_ERROR, "can't load imagefile '%s': %E", imagefile);
1241 #endif /* def USE_IMAGE_LIST */
1244 /*********************************************************************
1246 * Function : load_cookiefile
1248 * Description : Read and parse a cookiefile and add to files list.
1251 * 1 : csp = Current client state (buffers, headers, etc...)
1253 * Returns : 0 => Ok, everything else is an error.
1255 *********************************************************************/
1256 int load_cookiefile(struct client_state *csp)
1260 struct cookie_spec *b, *bl;
1261 char buf[BUFSIZ], *p, *q;
1262 int port, user_cookie, server_cookie;
1263 struct file_list *fs;
1264 struct url_spec url[1];
1266 if (!check_file_changed(current_cookiefile, cookiefile, &fs))
1268 /* No need to load */
1271 csp->clist = current_cookiefile;
1277 goto load_cookie_error;
1280 fs->f = bl = (struct cookie_spec *)zalloc(sizeof(*bl));
1283 goto load_cookie_error;
1286 if ((fp = fopen(cookiefile, "r")) == NULL)
1288 goto load_cookie_error;
1291 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1322 * Elide any of the "special" chars from the
1323 * front of the pattern
1326 if (p > q) while ((*q++ = *p++))
1331 /* skip lines containing only "special" chars */
1337 /* allocate a new node */
1338 if (((b = zalloc(sizeof(*b))) == NULL)
1340 || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
1345 goto load_cookie_error;
1348 /* add it to the list */
1352 /* save a copy of the orignal specification */
1353 if ((b->url->spec = strdup(buf)) == NULL)
1356 goto load_cookie_error;
1359 b->send_user_cookie = user_cookie;
1360 b->accept_server_cookie = server_cookie;
1362 if ((p = strchr(buf, '/')))
1364 b->url->path = strdup(p);
1365 b->url->pathlen = strlen(b->url->path);
1370 b->url->path = NULL;
1371 b->url->pathlen = 0;
1379 sprintf(rebuf, "^(%s)", b->url->path);
1381 errcode = regcomp(b->url->preg, rebuf,
1382 (REG_EXTENDED|REG_NOSUB|REG_ICASE));
1387 b->url->preg, buf, sizeof(buf));
1391 log_error(LOG_LEVEL_ERROR, "error compiling %s: %s",
1394 goto load_cookie_error;
1399 freez(b->url->preg);
1402 if ((p = strchr(buf, ':')) == NULL)
1412 b->url->port = port;
1414 if ((b->url->domain = strdup(buf)) == NULL)
1417 goto load_cookie_error;
1420 /* split domain into components */
1422 *url = dsplit(b->url->domain);
1423 b->url->dbuf = url->dbuf;
1424 b->url->dcnt = url->dcnt;
1425 b->url->dvec = url->dvec;
1430 #ifndef SPLIT_PROXY_ARGS
1431 if (!suppress_blocklists)
1433 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1435 #endif /* ndef SPLIT_PROXY_ARGS */
1437 /* the old one is now obsolete */
1438 if (current_cookiefile)
1440 current_cookiefile->unloader = unload_cookiefile;
1443 fs->next = files->next;
1445 current_cookiefile = fs;
1455 log_error(LOG_LEVEL_ERROR, "can't load cookiefile '%s': %E", cookiefile);
1462 /*********************************************************************
1464 * Function : load_trustfile
1466 * Description : Read and parse a trustfile and add to files list.
1469 * 1 : csp = Current client state (buffers, headers, etc...)
1471 * Returns : 0 => Ok, everything else is an error.
1473 *********************************************************************/
1474 int load_trustfile(struct client_state *csp)
1478 struct block_spec *b, *bl;
1479 struct url_spec **tl;
1481 char buf[BUFSIZ], *p, *q;
1482 int port, reject, trusted;
1483 struct file_list *fs;
1484 struct url_spec url[1];
1486 if (!check_file_changed(current_trustfile, trustfile, &fs))
1488 /* No need to load */
1491 csp->tlist = current_trustfile;
1497 goto load_trustfile_error;
1500 fs->f = bl = (struct block_spec *)zalloc(sizeof(*bl));
1503 goto load_trustfile_error;
1506 if ((fp = fopen(trustfile, "r")) == NULL)
1508 goto load_trustfile_error;
1513 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1529 while ((*p++ = *q++))
1535 /* skip blank lines */
1541 /* allocate a new node */
1542 if (((b = zalloc(sizeof(*b))) == NULL)
1544 || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
1549 goto load_trustfile_error;
1552 /* add it to the list */
1556 /* save a copy of the orignal specification */
1557 if ((b->url->spec = strdup(buf)) == NULL)
1560 goto load_trustfile_error;
1565 if ((p = strchr(buf, '/')))
1567 b->url->path = strdup(p);
1568 b->url->pathlen = strlen(b->url->path);
1573 b->url->path = NULL;
1574 b->url->pathlen = 0;
1582 sprintf(rebuf, "^(%s)", b->url->path);
1584 errcode = regcomp(b->url->preg, rebuf,
1585 (REG_EXTENDED|REG_NOSUB|REG_ICASE));
1591 b->url->preg, buf, sizeof(buf));
1595 log_error(LOG_LEVEL_ERROR, "error compiling %s: %s",
1598 goto load_trustfile_error;
1603 freez(b->url->preg);
1606 if ((p = strchr(buf, ':')) == NULL)
1616 b->url->port = port;
1618 if ((b->url->domain = strdup(buf)) == NULL)
1621 goto load_trustfile_error;
1624 /* split domain into components */
1625 *url = dsplit(b->url->domain);
1626 b->url->dbuf = url->dbuf;
1627 b->url->dcnt = url->dcnt;
1628 b->url->dvec = url->dvec;
1631 * save a pointer to URL's spec in the list of trusted URL's, too
1643 #ifndef SPLIT_PROXY_ARGS
1644 if (!suppress_blocklists)
1646 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1648 #endif /* ndef SPLIT_PROXY_ARGS */
1650 /* the old one is now obsolete */
1651 if (current_trustfile)
1653 current_trustfile->unloader = unload_trustfile;
1656 fs->next = files->next;
1658 current_trustfile = fs;
1667 load_trustfile_error:
1668 log_error(LOG_LEVEL_ERROR, "can't load trustfile '%s': %E", trustfile);
1672 #endif /* def TRUST_FILES */
1675 /*********************************************************************
1677 * Function : load_forwardfile
1679 * Description : Read and parse a forwardfile and add to files list.
1682 * 1 : csp = Current client state (buffers, headers, etc...)
1684 * Returns : 0 => Ok, everything else is an error.
1686 *********************************************************************/
1687 int load_forwardfile(struct client_state *csp)
1691 struct forward_spec *b, *bl;
1692 char buf[BUFSIZ], *p, *q, *tmp;
1694 int port, n, reject;
1695 struct file_list *fs;
1696 const struct gateway *gw;
1697 struct url_spec url[1];
1699 if (!check_file_changed(current_forwardfile, forwardfile, &fs))
1701 /* No need to load */
1704 csp->flist = current_forwardfile;
1710 goto load_forwardfile_error;
1713 fs->f = bl = (struct forward_spec *)zalloc(sizeof(*bl));
1715 if ((fs == NULL) || (bl == NULL))
1717 goto load_forwardfile_error;
1720 if ((fp = fopen(forwardfile, "r")) == NULL)
1722 goto load_forwardfile_error;
1727 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1733 n = ssplit(tmp, " \t", vec, SZ(vec), 1, 1);
1737 log_error(LOG_LEVEL_ERROR, "error in forwardfile: %s", buf);
1741 strcpy(buf, vec[0]);
1750 while ((*p++ = *q++))
1756 /* skip lines containing only ~ */
1762 /* allocate a new node */
1763 if (((b = zalloc(sizeof(*b))) == NULL)
1765 || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
1770 goto load_forwardfile_error;
1773 /* add it to the list */
1777 /* save a copy of the orignal specification */
1778 if ((b->url->spec = strdup(buf)) == NULL)
1781 goto load_forwardfile_error;
1786 if ((p = strchr(buf, '/')))
1788 b->url->path = strdup(p);
1789 b->url->pathlen = strlen(b->url->path);
1794 b->url->path = NULL;
1795 b->url->pathlen = 0;
1803 sprintf(rebuf, "^(%s)", b->url->path);
1805 errcode = regcomp(b->url->preg, rebuf,
1806 (REG_EXTENDED|REG_NOSUB|REG_ICASE));
1810 size_t errlen = regerror(errcode, b->url->preg, buf, sizeof(buf));
1814 log_error(LOG_LEVEL_ERROR, "error compiling %s: %s",
1817 goto load_forwardfile_error;
1822 freez(b->url->preg);
1825 if ((p = strchr(buf, ':')) == NULL)
1835 b->url->port = port;
1837 if ((b->url->domain = strdup(buf)) == NULL)
1840 goto load_forwardfile_error;
1843 /* split domain into components */
1844 *url = dsplit(b->url->domain);
1845 b->url->dbuf = url->dbuf;
1846 b->url->dcnt = url->dcnt;
1847 b->url->dvec = url->dvec;
1849 /* now parse the gateway specs */
1853 for (gw = gateways; gw->name; gw++)
1855 if (strcmp(gw->name, p) == 0)
1861 if (gw->name == NULL)
1863 goto load_forwardfile_error;
1866 /* save this as the gateway type */
1869 /* now parse the gateway host[:port] spec */
1872 if (strcmp(p, ".") != 0)
1874 b->gw->gateway_host = strdup(p);
1876 if ((p = strchr(b->gw->gateway_host, ':')))
1879 b->gw->gateway_port = atoi(p);
1882 if (b->gw->gateway_port <= 0)
1884 goto load_forwardfile_error;
1888 /* now parse the forwarding spec */
1891 if (strcmp(p, ".") != 0)
1893 b->gw->forward_host = strdup(p);
1895 if ((p = strchr(b->gw->forward_host, ':')))
1898 b->gw->forward_port = atoi(p);
1901 if (b->gw->forward_port <= 0)
1903 b->gw->forward_port = 8000;
1912 #ifndef SPLIT_PROXY_ARGS
1913 if (!suppress_blocklists)
1915 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1917 #endif /* ndef SPLIT_PROXY_ARGS */
1919 /* the old one is now obsolete */
1920 if (current_forwardfile)
1922 current_forwardfile->unloader = unload_forwardfile;
1925 fs->next = files->next;
1927 current_forwardfile = fs;
1936 load_forwardfile_error:
1937 log_error(LOG_LEVEL_ERROR, "can't load forwardfile '%s': %E", forwardfile);
1944 /*********************************************************************
1946 * Function : load_re_filterfile
1948 * Description : Load the re_filterfile. Each non-comment, non-empty
1949 * line is instantly added to the joblist, which is
1950 * a chained list of pcrs_job structs.
1953 * 1 : csp = Current client state (buffers, headers, etc...)
1955 * Returns : 0 => Ok, everything else is an error.
1957 *********************************************************************/
1958 int load_re_filterfile(struct client_state *csp)
1962 struct re_filterfile_spec *bl;
1963 struct file_list *fs;
1969 #ifndef SPLIT_PROXY_ARGS
1971 #endif /* ndef SPLIT_PROXY_ARGS */
1972 if (!check_file_changed(current_re_filterfile, re_filterfile, &fs))
1974 /* No need to load */
1977 csp->rlist = current_re_filterfile;
1983 goto load_re_filterfile_error;
1986 fs->f = bl = (struct re_filterfile_spec *)zalloc(sizeof(*bl));
1989 goto load_re_filterfile_error;
1992 /* Open the file or fail */
1993 if ((fp = fopen(re_filterfile, "r")) == NULL)
1995 goto load_re_filterfile_error;
1998 /* Read line by line */
1999 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
2001 enlist( bl->patterns, buf );
2003 /* We have a meaningful line -> make it a job */
2004 if ((dummy = pcrs_make_job(buf, &error)) == NULL)
2006 log_error(LOG_LEVEL_REF,
2007 "Adding re_filter job %s failed with error %d.", buf, error);
2012 dummy->next = bl->joblist;
2013 bl->joblist = dummy;
2014 log_error(LOG_LEVEL_REF, "Adding re_filter job %s succeeded.", buf);
2020 #ifndef SPLIT_PROXY_ARGS
2021 if (!suppress_blocklists)
2023 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
2025 #endif /* ndef SPLIT_PROXY_ARGS */
2027 /* the old one is now obsolete */
2028 if ( NULL != current_re_filterfile )
2030 current_re_filterfile->unloader = unload_re_filterfile;
2033 fs->next = files->next;
2035 current_re_filterfile = fs;
2044 load_re_filterfile_error:
2045 log_error(LOG_LEVEL_ERROR, "can't load re_filterfile '%s': %E", re_filterfile);
2049 #endif /* def PCRS */
2053 /*********************************************************************
2055 * Function : load_popupfile
2057 * Description : Load, and parse the popup blocklist.
2060 * 1 : csp = Current client state (buffers, headers, etc...)
2062 * Returns : 0 => success, else there was an error.
2064 *********************************************************************/
2065 int load_popupfile(struct client_state *csp)
2068 char buf[BUFSIZ], *p, *q;
2069 struct popup_blocklist *entry = NULL;
2070 struct popup_settings * data;
2071 struct file_list *fs;
2075 if (!check_file_changed(current_popupfile, popupfile, &fs))
2077 /* No need to load */
2080 csp->plist = current_popupfile;
2086 goto load_popupfile_error;
2089 fs->f = data = (struct popup_settings *)zalloc(sizeof(*data));
2092 goto load_popupfile_error;
2095 if ((fp = fopen(popupfile, "r")) == NULL)
2097 goto load_popupfile_error;
2100 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
2102 entry = (struct popup_blocklist*)zalloc(sizeof(struct popup_blocklist));
2106 goto load_popupfile_error;
2109 /* Handle allowed hosts. */
2112 /* Rememeber: skip the tilde */
2113 entry->host_name = strdup( buf + 1 );
2114 if (!entry->host_name)
2117 goto load_popupfile_error;
2120 entry->next = data->allowed;
2121 data->allowed = entry;
2126 entry->host_name = strdup( buf );
2127 if (!entry->host_name)
2130 goto load_popupfile_error;
2133 entry->next = data->blocked;
2134 data->blocked = entry;
2140 #ifndef SPLIT_PROXY_ARGS
2141 if (!suppress_blocklists)
2143 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
2145 #endif /* ndef SPLIT_PROXY_ARGS */
2147 /* the old one is now obsolete */
2148 if ( NULL != current_popupfile )
2150 current_popupfile->unloader = unload_popupfile;
2153 fs->next = files->next;
2155 current_popupfile = fs;
2164 load_popupfile_error:
2165 log_error(LOG_LEVEL_ERROR, "can't load popupfile '%s': %E", popupfile);
2169 #endif /* def KILLPOPUPS */
2173 /*********************************************************************
2175 * Function : add_loader
2177 * Description : Called from `load_config'. Called once for each input
2178 * file found in config.
2181 * 1 : loader = pointer to a function that can parse and load
2182 * the appropriate config file.
2186 *********************************************************************/
2187 void add_loader(int (*loader)(struct client_state *))
2191 for (i=0; i < NLOADERS; i++)
2193 if (loaders[i] == NULL)
2195 loaders[i] = loader;
2203 /*********************************************************************
2205 * Function : run_loader
2207 * Description : Called from `load_config' and `listen_loop'. This
2208 * function keeps the "csp" current with any file mods
2209 * since the last loop. If a file is unchanged, the
2210 * loader functions do NOT reload the file.
2213 * 1 : csp = Current client state (buffers, headers, etc...)
2215 * Returns : 0 => Ok, everything else is an error.
2217 *********************************************************************/
2218 int run_loader(struct client_state *csp)
2223 for (i=0; i < NLOADERS; i++)
2225 if (loaders[i] == NULL)
2229 ret |= (loaders[i])(csp);
2236 /*********************************************************************
2238 * Function : remove_all_loaders
2240 * Description : Remove all loaders from the list.
2246 *********************************************************************/
2247 void remove_all_loaders(void)
2249 memset( loaders, 0, sizeof( loaders ) );