1 const char loaders_rcs[] = "$Id: loaders.c,v 1.1 2001/05/13 21:57:06 administrator Exp $";
2 /*********************************************************************
4 * File : $Source: /home/administrator/cvs/ijb/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.
39 *********************************************************************/
46 #include <sys/types.h>
68 #ifndef SPLIT_PROXY_ARGS
71 #endif /* ndef SPLIT_PROXY_ARGS */
73 const char loaders_h_rcs[] = LOADERS_H_VERSION;
75 /* Fix a problem with Solaris. There should be no effect on other
77 * Solaris's isspace() is a macro which uses it's argument directly
78 * as an array index. Therefore we need to make sure that high-bit
79 * characters generate +ve values, and ideally we also want to make
80 * the argument match the declared parameter type of "int".
82 #define ijb_isspace(__X) isspace((int)(unsigned char)(__X))
86 static int (*loaders[NLOADERS])(struct client_state *);
90 * Currently active files.
91 * These are also entered in the main linked list of files.
93 static struct file_list *current_blockfile = NULL;
94 static struct file_list *current_cookiefile = NULL;
95 static struct file_list *current_forwardfile = NULL;
98 static struct file_list *current_aclfile = NULL;
99 #endif /* def ACL_FILES */
101 #ifdef USE_IMAGE_LIST
102 static struct file_list *current_imagefile = NULL;
103 #endif /* def USE_IMAGE_LIST */
106 static struct file_list * current_popupfile = NULL;
107 #endif /* def KILLPOPUPS */
110 static struct file_list *current_trustfile = NULL;
111 #endif /* def TRUST_FILES */
114 static struct file_list *current_re_filterfile = NULL;
115 #endif /* def PCRS */
118 /*********************************************************************
122 * Description : Basically a mark and sweep garbage collector, it is run
123 * (by the parent thread) every once in a while to reclaim memory.
125 * It uses a mark and sweep strategy:
126 * 1) mark all files as inactive
128 * 2) check with each client:
129 * if it is active, mark its files as active
130 * if it is inactive, free its resources
132 * 3) free the resources of all of the files that
133 * are still marked as inactive (and are obsolete).
135 * N.B. files that are not obsolete don't have an unloader defined.
141 *********************************************************************/
144 struct file_list *fl, *nfl;
145 struct client_state *csp, *ncsp;
147 /* clear all of the file's active flags */
148 for ( fl = files->next; NULL != fl; fl = fl->next )
153 for (csp = clients; csp && (ncsp = csp->next) ; csp = csp->next)
157 /* mark this client's files as active */
159 if (ncsp->blist) /* block files */
161 ncsp->blist->active = 1;
164 if (ncsp->clist) /* cookie files */
166 ncsp->clist->active = 1;
169 /* FIXME: These were left out of the "10" release. Should they be here? */
170 if (ncsp->flist) /* forward files */
172 ncsp->flist->active = 1;
176 if (ncsp->alist) /* acl files */
178 ncsp->alist->active = 1;
180 #endif /* def ACL_FILES */
182 #ifdef USE_IMAGE_LIST
183 if (ncsp->ilist) /* image files */
185 ncsp->ilist->active = 1;
187 #endif /* def USE_IMAGE_LIST */
190 if (ncsp->plist) /* killpopup files */
192 ncsp->plist->active = 1;
194 #endif /* def KILLPOPUPS */
197 if (ncsp->rlist) /* perl re files */
199 ncsp->rlist->active = 1;
201 #endif /* def PCRS */
204 if (ncsp->tlist) /* trust files */
206 ncsp->tlist->active = 1;
208 #endif /* def TRUST_FILES */
213 /* this client one is not active, release its resources */
214 csp->next = ncsp->next;
216 freez(ncsp->ip_addr_str);
217 freez(ncsp->referrer);
218 freez(ncsp->x_forwarded);
219 freez(ncsp->ip_addr_str);
220 freez(ncsp->iob->buf);
222 free_http_request(ncsp->http);
224 destroy_list(ncsp->headers);
225 destroy_list(ncsp->cookie_list);
233 #endif /* def STATISTICS */
239 for (fl = files; fl && (nfl = fl->next) ; fl = fl->next)
241 if ( ( 0 == nfl->active ) && ( NULL != nfl->unloader ) )
243 fl->next = nfl->next;
245 (nfl->unloader)(nfl->f);
247 #ifndef SPLIT_PROXY_ARGS
248 freez(nfl->proxy_args);
249 #endif /* ndef SPLIT_PROXY_ARGS */
251 freez(nfl->filename);
260 /*********************************************************************
262 * Function : unload_url
264 * Description : Called from the "unloaders". Freez the url
265 * structure elements.
268 * 1 : url = pointer to a url_spec structure.
272 *********************************************************************/
273 static void unload_url(struct url_spec *url)
275 if (url == NULL) return;
294 /*********************************************************************
296 * Function : unload_aclfile
298 * Description : Unloads an aclfile.
301 * 1 : f = the data structure associated with the aclfile.
305 *********************************************************************/
306 static void unload_aclfile(void *f)
308 struct access_control_list *b = (struct access_control_list *)f;
309 if (b == NULL) return;
311 unload_aclfile(b->next);
316 #endif /* def ACL_FILES */
318 /*********************************************************************
320 * Function : unload_blockfile
322 * Description : Unloads a blockfile.
325 * 1 : f = the data structure associated with the blockfile.
329 *********************************************************************/
330 static void unload_blockfile(void *f)
332 struct block_spec *b = (struct block_spec *)f;
333 if (b == NULL) return;
335 unload_blockfile(b->next);
344 #ifdef USE_IMAGE_LIST
345 /*********************************************************************
347 * Function : unload_imagefile
349 * Description : Unloads an imagefile.
352 * 1 : f = the data structure associated with the imagefile.
356 *********************************************************************/
357 static void unload_imagefile(void *f)
359 struct block_spec *b = (struct block_spec *)f;
360 if (b == NULL) return;
362 unload_imagefile(b->next);
369 #endif /* def USE_IMAGE_LIST */
372 /*********************************************************************
374 * Function : unload_cookiefile
376 * Description : Unloads a cookiefile.
379 * 1 : f = the data structure associated with the cookiefile.
383 *********************************************************************/
384 static void unload_cookiefile(void *f)
386 struct cookie_spec *b = (struct cookie_spec *)f;
387 if (b == NULL) return;
389 unload_cookiefile(b->next);
399 /*********************************************************************
401 * Function : unload_trustfile
403 * Description : Unloads a trustfile.
406 * 1 : f = the data structure associated with the trustfile.
410 *********************************************************************/
411 static void unload_trustfile(void *f)
413 struct block_spec *b = (struct block_spec *)f;
414 if (b == NULL) return;
416 unload_trustfile(b->next);
423 #endif /* def TRUST_FILES */
426 /*********************************************************************
428 * Function : unload_forwardfile
430 * Description : Unloads a forwardfile.
433 * 1 : f = the data structure associated with the forwardfile.
437 *********************************************************************/
438 static void unload_forwardfile(void *f)
440 struct forward_spec *b = (struct forward_spec *)f;
441 if (b == NULL) return;
443 unload_forwardfile(b->next);
447 freez(b->gw->gateway_host);
448 freez(b->gw->forward_host);
456 /*********************************************************************
458 * Function : unload_re_filterfile
460 * Description : Unload the re_filter list.
463 * 1 : f = the data structure associated with the filterfile.
467 *********************************************************************/
468 static void unload_re_filterfile(void *f)
471 struct re_filterfile_spec *b = (struct re_filterfile_spec *)f;
473 if (b == NULL) return;
475 destroy_list(b->patterns);
477 joblist = b->joblist;
478 while ( NULL != (joblist = pcrs_free_job(joblist)) ) {}
483 #endif /* def PCRS */
487 /*********************************************************************
489 * Function : unload_popupfile
491 * Description : Free the lists of blocked, and allowed popup sites.
494 * 1 : csp = Current client state (buffers, headers, etc...)
498 *********************************************************************/
499 static void unload_popupfile(void * b)
501 struct popup_settings * data = (struct popup_settings *) b;
502 struct popup_blocklist * cur = NULL;
503 struct popup_blocklist * temp= NULL;
505 /* Free the blocked list. */
510 freez (cur->host_name);
514 data->blocked = NULL;
516 /* Free the allowed list. */
521 freez (cur->host_name);
525 data->allowed = NULL;
528 #endif /* def KILLPOPUPS */
531 /*********************************************************************
533 * Function : check_file_changed
535 * Description : Helper function to check if a file needs reloading.
536 * If "current" is still current, return it. Otherwise
537 * allocates a new (zeroed) "struct file_list", fills
538 * in the disk file name and timestamp, and returns it.
541 * 1 : current = The file_list currently being used - will
542 * be checked to see if it is out of date.
543 * May be NULL (which is treated as out of
545 * 2 : filename = Name of file to check.
546 * 3 : newfl = New file list. [Output only]
547 * This will be set to NULL, OR a struct
548 * file_list newly allocated on the
549 * heap, with the filename and lastmodified
550 * fields filled, standard header giving file
551 * name in proxy_args, and all others zeroed.
552 * (proxy_args is only filled in if
553 * SPLIT_PROXY_ARGS and !suppress_blocklists).
555 * Returns : If file unchanged: 0 (and sets newfl == NULL)
556 * If file changed: 1 and sets newfl != NULL
557 * On error: 1 and sets newfl == NULL
559 *********************************************************************/
560 static int check_file_changed(const struct file_list * current,
561 const char * filename,
562 struct file_list ** newfl)
564 struct file_list *fs;
565 struct stat statbuf[1];
569 if (stat(filename, statbuf) < 0)
571 /* Error, probably file not found. */
576 && (current->lastmodified == statbuf->st_mtime)
577 && (0 == strcmp(current->filename, filename)))
582 fs = (struct file_list *)zalloc(sizeof(struct file_list));
586 /* Out of memory error */
590 fs->filename = strdup(filename);
591 fs->lastmodified = statbuf->st_mtime;
593 if (fs->filename == NULL)
595 /* Out of memory error */
600 #ifndef SPLIT_PROXY_ARGS
601 if (!suppress_blocklists)
603 char * p = html_encode(filename);
606 fs->proxy_args = strsav(fs->proxy_args, "<h2>The file `");
\r
607 fs->proxy_args = strsav(fs->proxy_args, p);
\r
608 fs->proxy_args = strsav(fs->proxy_args,
\r
609 "' contains the following patterns</h2>\n");
\r
612 fs->proxy_args = strsav(fs->proxy_args, "<pre>");
614 #endif /* ndef SPLIT_PROXY_ARGS */
621 /*********************************************************************
623 * Function : read_config_line
625 * Description : Read a single non-empty line from a file and return
626 * it. Trims comments, leading and trailing whitespace.
627 * Also wites the file to fs->proxy_args.
630 * 1 : buf = Buffer to use.
631 * 2 : buflen = Size of buffer in bytes.
632 * 3 : fp = File to read from
633 * 4 : fs = File will be written to fs->proxy_args. May
634 * be NULL to disable this feature.
636 * Returns : NULL on EOF or error
637 * Otherwise, returns buf.
639 *********************************************************************/
640 char *read_config_line(char *buf, int buflen, FILE *fp, struct file_list *fs)
643 char linebuf[BUFSIZ];
645 while (fgets(linebuf, sizeof(linebuf), fp))
647 #ifndef SPLIT_PROXY_ARGS
648 if (fs && !suppress_blocklists)
650 char *html_line = html_encode(linebuf);
651 if (html_line != NULL)
653 fs->proxy_args = strsav(fs->proxy_args, html_line);
656 fs->proxy_args = strsav(fs->proxy_args, "<br>");
658 #endif /* ndef SPLIT_PROXY_ARGS */
660 /* Trim off newline and any comment */
661 if ((p = strpbrk(linebuf, "\r\n#")) != NULL)
666 /* Trim leading whitespace */
668 while (*p && ijb_isspace(*p))
675 /* There is something other than whitespace on the line. */
677 /* Move the data to the start of buf */
680 /* strcpy that can cope with overlap. */
682 while ((*q++ = *p++) != '\0')
688 /* Trim trailing whitespace */
689 p = linebuf + strlen(linebuf) - 1;
692 * Note: the (p >= retval) below is paranoia, it's not really needed.
693 * When p == retval then ijb_isspace(*p) will be false and we'll drop
696 while ((p >= linebuf) && ijb_isspace(*p))
702 /* More paranoia. This if statement is always true. */
705 strcpy(buf, linebuf);
717 /*********************************************************************
719 * Function : load_aclfile
721 * Description : Read and parse an aclfile and add to files list.
724 * 1 : csp = Current client state (buffers, headers, etc...)
726 * Returns : 0 => Ok, everything else is an error.
728 *********************************************************************/
729 int load_aclfile(struct client_state *csp)
732 char buf[BUFSIZ], *v[3], *p;
734 struct access_control_list *a, *bl;
735 struct file_list *fs;
737 if (!check_file_changed(current_aclfile, aclfile, &fs))
739 /* No need to load */
742 csp->alist = current_aclfile;
748 goto load_aclfile_error;
751 fs->f = bl = (struct access_control_list *)zalloc(sizeof(*bl));
756 goto load_aclfile_error;
759 fp = fopen(aclfile, "r");
763 goto load_aclfile_error;
766 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
768 i = ssplit(buf, " \t", v, SZ(v), 1, 1);
770 /* allocate a new node */
771 a = (struct access_control_list *) zalloc(sizeof(*a));
779 goto load_aclfile_error;
782 /* add it to the list */
789 if (acl_addr(v[2], a->dst) < 0)
791 goto load_aclfile_error;
796 if (acl_addr(v[1], a->src) < 0)
798 goto load_aclfile_error;
802 if (strcmpic(p, "permit") == 0)
804 a->action = ACL_PERMIT;
808 if (strcmpic(p, "deny") == 0)
810 a->action = ACL_DENY;
816 goto load_aclfile_error;
822 #ifndef SPLIT_PROXY_ARGS
823 if (!suppress_blocklists)
825 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
827 #endif /* ndef SPLIT_PROXY_ARGS */
831 current_aclfile->unloader = unload_aclfile;
834 fs->next = files->next;
836 current_aclfile = fs;
846 log_error(LOG_LEVEL_ERROR, "can't load access control list %s: %E", aclfile);
850 #endif /* def ACL_FILES */
853 /*********************************************************************
855 * Function : load_blockfile
857 * Description : Read and parse a blockfile and add to files list.
860 * 1 : csp = Current client state (buffers, headers, etc...)
862 * Returns : 0 => Ok, everything else is an error.
864 *********************************************************************/
865 int load_blockfile(struct client_state *csp)
869 struct block_spec *b, *bl;
870 char buf[BUFSIZ], *p, *q;
872 struct file_list *fs;
873 struct url_spec url[1];
875 if (!check_file_changed(current_blockfile, blockfile, &fs))
877 /* No need to load */
880 csp->blist = current_blockfile;
886 goto load_blockfile_error;
889 fs->f = bl = (struct block_spec *) zalloc(sizeof(*bl));
892 goto load_blockfile_error;
895 if ((fp = fopen(blockfile, "r")) == NULL)
897 goto load_blockfile_error;
900 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
909 while ((*p++ = *q++))
915 /* skip lines containing only ~ */
921 /* allocate a new node */
922 if (((b = zalloc(sizeof(*b))) == NULL)
924 || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
929 goto load_blockfile_error;
932 /* add it to the list */
936 /* save a copy of the orignal specification */
937 if ((b->url->spec = strdup(buf)) == NULL)
940 goto load_blockfile_error;
945 if ((p = strchr(buf, '/')))
947 b->url->path = strdup(p);
948 b->url->pathlen = strlen(b->url->path);
962 sprintf(rebuf, "^(%s)", b->url->path);
964 errcode = regcomp(b->url->preg, rebuf,
965 (REG_EXTENDED|REG_NOSUB|REG_ICASE));
971 b->url->preg, buf, sizeof(buf));
975 log_error(LOG_LEVEL_ERROR, "error compiling %s: %s\n",
978 goto load_blockfile_error;
986 if ((p = strchr(buf, ':')) == NULL)
998 if ((b->url->domain = strdup(buf)) == NULL)
1001 goto load_blockfile_error;
1004 /* split domain into components */
1005 *url = dsplit(b->url->domain);
1006 b->url->dbuf = url->dbuf;
1007 b->url->dcnt = url->dcnt;
1008 b->url->dvec = url->dvec;
1013 #ifndef SPLIT_PROXY_ARGS
1014 if (!suppress_blocklists)
1016 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1018 #endif /* ndef SPLIT_PROXY_ARGS */
1020 /* the old one is now obsolete */
1021 if (current_blockfile)
1023 current_blockfile->unloader = unload_blockfile;
1026 fs->next = files->next;
1028 current_blockfile = fs;
1037 load_blockfile_error:
1038 log_error(LOG_LEVEL_ERROR, "can't load blockfile '%s': %E", blockfile);
1044 #ifdef USE_IMAGE_LIST
1045 /*********************************************************************
1047 * Function : load_imagefile
1049 * Description : Read and parse an imagefile and add to files list.
1052 * 1 : csp = Current client state (buffers, headers, etc...)
1054 * Returns : 0 => Ok, everything else is an error.
1056 *********************************************************************/
1057 int load_imagefile(struct client_state *csp)
1061 struct block_spec *b, *bl;
1062 char buf[BUFSIZ], *p, *q;
1064 struct file_list *fs;
1065 struct url_spec url[1];
1067 if (!check_file_changed(current_imagefile, imagefile, &fs))
1069 /* No need to load */
1072 csp->ilist = current_imagefile;
1078 goto load_imagefile_error;
1081 fs->f = bl = (struct block_spec *)zalloc(sizeof(*bl));
1084 goto load_imagefile_error;
1087 if ((fp = fopen(imagefile, "r")) == NULL)
1089 goto load_imagefile_error;
1092 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1101 while ((*p++ = *q++))
1107 /* skip lines containing only ~ */
1113 /* allocate a new node */
1114 if (((b = zalloc(sizeof(*b))) == NULL)
1116 || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
1121 goto load_imagefile_error;
1124 /* add it to the list */
1128 /* save a copy of the orignal specification */
1129 if ((b->url->spec = strdup(buf)) == NULL)
1132 goto load_imagefile_error;
1137 if ((p = strchr(buf, '/')))
1139 b->url->path = strdup(p);
1140 b->url->pathlen = strlen(b->url->path);
1145 b->url->path = NULL;
1146 b->url->pathlen = 0;
1154 sprintf(rebuf, "^(%s)", b->url->path);
1156 errcode = regcomp(b->url->preg, rebuf,
1157 (REG_EXTENDED|REG_NOSUB|REG_ICASE));
1163 b->url->preg, buf, sizeof(buf));
1167 log_error(LOG_LEVEL_ERROR, "error compiling %s: %s",
1170 goto load_imagefile_error;
1175 freez(b->url->preg);
1178 if ((p = strchr(buf, ':')) == NULL)
1188 b->url->port = port;
1190 if ((b->url->domain = strdup(buf)) == NULL)
1193 goto load_imagefile_error;
1196 /* split domain into components */
1197 *url = dsplit(b->url->domain);
1198 b->url->dbuf = url->dbuf;
1199 b->url->dcnt = url->dcnt;
1200 b->url->dvec = url->dvec;
1202 #ifndef SPLIT_PROXY_ARGS
1203 if (!suppress_blocklists)
1204 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1205 #endif /* ndef SPLIT_PROXY_ARGS */
1209 #ifndef SPLIT_PROXY_ARGS
1210 if (!suppress_blocklists)
1212 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1214 #endif /* ndef SPLIT_PROXY_ARGS */
1216 /* the old one is now obsolete */
1217 if (current_imagefile)
1219 current_imagefile->unloader = unload_imagefile;
1222 fs->next = files->next;
1224 current_imagefile = fs;
1233 load_imagefile_error:
1234 log_error(LOG_LEVEL_ERROR, "can't load imagefile '%s': %E", imagefile);
1238 #endif /* def USE_IMAGE_LIST */
1241 /*********************************************************************
1243 * Function : load_cookiefile
1245 * Description : Read and parse a cookiefile and add to files list.
1248 * 1 : csp = Current client state (buffers, headers, etc...)
1250 * Returns : 0 => Ok, everything else is an error.
1252 *********************************************************************/
1253 int load_cookiefile(struct client_state *csp)
1257 struct cookie_spec *b, *bl;
1258 char buf[BUFSIZ], *p, *q;
1259 int port, user_cookie, server_cookie;
1260 struct file_list *fs;
1261 struct url_spec url[1];
1263 if (!check_file_changed(current_cookiefile, cookiefile, &fs))
1265 /* No need to load */
1268 csp->clist = current_cookiefile;
1274 goto load_cookie_error;
1277 fs->f = bl = (struct cookie_spec *)zalloc(sizeof(*bl));
1280 goto load_cookie_error;
1283 if ((fp = fopen(cookiefile, "r")) == NULL)
1285 goto load_cookie_error;
1288 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1319 * Elide any of the "special" chars from the
1320 * front of the pattern
1323 if (p > q) while ((*q++ = *p++))
1328 /* skip lines containing only "special" chars */
1334 /* allocate a new node */
1335 if (((b = zalloc(sizeof(*b))) == NULL)
1337 || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
1342 goto load_cookie_error;
1345 /* add it to the list */
1349 /* save a copy of the orignal specification */
1350 if ((b->url->spec = strdup(buf)) == NULL)
1353 goto load_cookie_error;
1356 b->send_user_cookie = user_cookie;
1357 b->accept_server_cookie = server_cookie;
1359 if ((p = strchr(buf, '/')))
1361 b->url->path = strdup(p);
1362 b->url->pathlen = strlen(b->url->path);
1367 b->url->path = NULL;
1368 b->url->pathlen = 0;
1376 sprintf(rebuf, "^(%s)", b->url->path);
1378 errcode = regcomp(b->url->preg, rebuf,
1379 (REG_EXTENDED|REG_NOSUB|REG_ICASE));
1384 b->url->preg, buf, sizeof(buf));
1388 log_error(LOG_LEVEL_ERROR, "error compiling %s: %s",
1391 goto load_cookie_error;
1396 freez(b->url->preg);
1399 if ((p = strchr(buf, ':')) == NULL)
1409 b->url->port = port;
1411 if ((b->url->domain = strdup(buf)) == NULL)
1414 goto load_cookie_error;
1417 /* split domain into components */
1419 *url = dsplit(b->url->domain);
1420 b->url->dbuf = url->dbuf;
1421 b->url->dcnt = url->dcnt;
1422 b->url->dvec = url->dvec;
1427 #ifndef SPLIT_PROXY_ARGS
1428 if (!suppress_blocklists)
1430 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1432 #endif /* ndef SPLIT_PROXY_ARGS */
1434 /* the old one is now obsolete */
1435 if (current_cookiefile)
1437 current_cookiefile->unloader = unload_cookiefile;
1440 fs->next = files->next;
1442 current_cookiefile = fs;
1452 log_error(LOG_LEVEL_ERROR, "can't load cookiefile '%s': %E", cookiefile);
1459 /*********************************************************************
1461 * Function : load_trustfile
1463 * Description : Read and parse a trustfile and add to files list.
1466 * 1 : csp = Current client state (buffers, headers, etc...)
1468 * Returns : 0 => Ok, everything else is an error.
1470 *********************************************************************/
1471 int load_trustfile(struct client_state *csp)
1475 struct block_spec *b, *bl;
1476 struct url_spec **tl;
1478 char buf[BUFSIZ], *p, *q;
1479 int port, reject, trusted;
1480 struct file_list *fs;
1481 struct url_spec url[1];
1483 if (!check_file_changed(current_trustfile, trustfile, &fs))
1485 /* No need to load */
1488 csp->tlist = current_trustfile;
1494 goto load_trustfile_error;
1497 fs->f = bl = (struct block_spec *)zalloc(sizeof(*bl));
1500 goto load_trustfile_error;
1503 if ((fp = fopen(trustfile, "r")) == NULL)
1505 goto load_trustfile_error;
1510 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1526 while ((*p++ = *q++))
1532 /* skip blank lines */
1538 /* allocate a new node */
1539 if (((b = zalloc(sizeof(*b))) == NULL)
1541 || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
1546 goto load_trustfile_error;
1549 /* add it to the list */
1553 /* save a copy of the orignal specification */
1554 if ((b->url->spec = strdup(buf)) == NULL)
1557 goto load_trustfile_error;
1562 if ((p = strchr(buf, '/')))
1564 b->url->path = strdup(p);
1565 b->url->pathlen = strlen(b->url->path);
1570 b->url->path = NULL;
1571 b->url->pathlen = 0;
1579 sprintf(rebuf, "^(%s)", b->url->path);
1581 errcode = regcomp(b->url->preg, rebuf,
1582 (REG_EXTENDED|REG_NOSUB|REG_ICASE));
1588 b->url->preg, buf, sizeof(buf));
1592 log_error(LOG_LEVEL_ERROR, "error compiling %s: %s",
1595 goto load_trustfile_error;
1600 freez(b->url->preg);
1603 if ((p = strchr(buf, ':')) == NULL)
1613 b->url->port = port;
1615 if ((b->url->domain = strdup(buf)) == NULL)
1618 goto load_trustfile_error;
1621 /* split domain into components */
1622 *url = dsplit(b->url->domain);
1623 b->url->dbuf = url->dbuf;
1624 b->url->dcnt = url->dcnt;
1625 b->url->dvec = url->dvec;
1628 * save a pointer to URL's spec in the list of trusted URL's, too
1640 #ifndef SPLIT_PROXY_ARGS
1641 if (!suppress_blocklists)
1643 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1645 #endif /* ndef SPLIT_PROXY_ARGS */
1647 /* the old one is now obsolete */
1648 if (current_trustfile)
1650 current_trustfile->unloader = unload_trustfile;
1653 fs->next = files->next;
1655 current_trustfile = fs;
1664 load_trustfile_error:
1665 log_error(LOG_LEVEL_ERROR, "can't load trustfile '%s': %E", trustfile);
1669 #endif /* def TRUST_FILES */
1672 /*********************************************************************
1674 * Function : load_forwardfile
1676 * Description : Read and parse a forwardfile and add to files list.
1679 * 1 : csp = Current client state (buffers, headers, etc...)
1681 * Returns : 0 => Ok, everything else is an error.
1683 *********************************************************************/
1684 int load_forwardfile(struct client_state *csp)
1688 struct forward_spec *b, *bl;
1689 char buf[BUFSIZ], *p, *q, *tmp;
1691 int port, n, reject;
1692 struct file_list *fs;
1693 const struct gateway *gw;
1694 struct url_spec url[1];
1696 if (!check_file_changed(current_forwardfile, forwardfile, &fs))
1698 /* No need to load */
1701 csp->flist = current_forwardfile;
1707 goto load_forwardfile_error;
1710 fs->f = bl = (struct forward_spec *)zalloc(sizeof(*bl));
1712 if ((fs == NULL) || (bl == NULL))
1714 goto load_forwardfile_error;
1717 if ((fp = fopen(forwardfile, "r")) == NULL)
1719 goto load_forwardfile_error;
1724 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1730 n = ssplit(tmp, " \t", vec, SZ(vec), 1, 1);
1734 log_error(LOG_LEVEL_ERROR, "error in forwardfile: %s", buf);
1738 strcpy(buf, vec[0]);
1747 while ((*p++ = *q++))
1753 /* skip lines containing only ~ */
1759 /* allocate a new node */
1760 if (((b = zalloc(sizeof(*b))) == NULL)
1762 || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
1767 goto load_forwardfile_error;
1770 /* add it to the list */
1774 /* save a copy of the orignal specification */
1775 if ((b->url->spec = strdup(buf)) == NULL)
1778 goto load_forwardfile_error;
1783 if ((p = strchr(buf, '/')))
1785 b->url->path = strdup(p);
1786 b->url->pathlen = strlen(b->url->path);
1791 b->url->path = NULL;
1792 b->url->pathlen = 0;
1800 sprintf(rebuf, "^(%s)", b->url->path);
1802 errcode = regcomp(b->url->preg, rebuf,
1803 (REG_EXTENDED|REG_NOSUB|REG_ICASE));
1807 size_t errlen = regerror(errcode, b->url->preg, buf, sizeof(buf));
1811 log_error(LOG_LEVEL_ERROR, "error compiling %s: %s",
1814 goto load_forwardfile_error;
1819 freez(b->url->preg);
1822 if ((p = strchr(buf, ':')) == NULL)
1832 b->url->port = port;
1834 if ((b->url->domain = strdup(buf)) == NULL)
1837 goto load_forwardfile_error;
1840 /* split domain into components */
1841 *url = dsplit(b->url->domain);
1842 b->url->dbuf = url->dbuf;
1843 b->url->dcnt = url->dcnt;
1844 b->url->dvec = url->dvec;
1846 /* now parse the gateway specs */
1850 for (gw = gateways; gw->name; gw++)
1852 if (strcmp(gw->name, p) == 0)
1858 if (gw->name == NULL)
1860 goto load_forwardfile_error;
1863 /* save this as the gateway type */
1866 /* now parse the gateway host[:port] spec */
1869 if (strcmp(p, ".") != 0)
1871 b->gw->gateway_host = strdup(p);
1873 if ((p = strchr(b->gw->gateway_host, ':')))
1876 b->gw->gateway_port = atoi(p);
1879 if (b->gw->gateway_port <= 0)
1881 goto load_forwardfile_error;
1885 /* now parse the forwarding spec */
1888 if (strcmp(p, ".") != 0)
1890 b->gw->forward_host = strdup(p);
1892 if ((p = strchr(b->gw->forward_host, ':')))
1895 b->gw->forward_port = atoi(p);
1898 if (b->gw->forward_port <= 0)
1900 b->gw->forward_port = 8000;
1909 #ifndef SPLIT_PROXY_ARGS
1910 if (!suppress_blocklists)
1912 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
1914 #endif /* ndef SPLIT_PROXY_ARGS */
1916 /* the old one is now obsolete */
1917 if (current_forwardfile)
1919 current_forwardfile->unloader = unload_forwardfile;
1922 fs->next = files->next;
1924 current_forwardfile = fs;
1933 load_forwardfile_error:
1934 log_error(LOG_LEVEL_ERROR, "can't load forwardfile '%s': %E", forwardfile);
1941 /*********************************************************************
1943 * Function : load_re_filterfile
1945 * Description : Load the re_filterfile. Each non-comment, non-empty
1946 * line is instantly added to the joblist, which is
1947 * a chained list of pcrs_job structs.
1950 * 1 : csp = Current client state (buffers, headers, etc...)
1952 * Returns : 0 => Ok, everything else is an error.
1954 *********************************************************************/
1955 int load_re_filterfile(struct client_state *csp)
1959 struct re_filterfile_spec *bl;
1960 struct file_list *fs;
1966 #ifndef SPLIT_PROXY_ARGS
1968 #endif /* ndef SPLIT_PROXY_ARGS */
1969 if (!check_file_changed(current_re_filterfile, re_filterfile, &fs))
1971 /* No need to load */
1974 csp->rlist = current_re_filterfile;
1980 goto load_re_filterfile_error;
1983 fs->f = bl = (struct re_filterfile_spec *)zalloc(sizeof(*bl));
1986 goto load_re_filterfile_error;
1989 /* Open the file or fail */
1990 if ((fp = fopen(re_filterfile, "r")) == NULL)
1992 goto load_re_filterfile_error;
1995 /* Read line by line */
1996 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
1998 enlist( bl->patterns, buf );
2000 /* We have a meaningful line -> make it a job */
2001 if ((dummy = pcrs_make_job(buf, &error)) == NULL)
2003 log_error(LOG_LEVEL_REF,
2004 "Adding re_filter job %s failed with error %d.", buf, error);
2009 dummy->next = bl->joblist;
2010 bl->joblist = dummy;
2011 log_error(LOG_LEVEL_REF, "Adding re_filter job %s succeeded.", buf);
2017 #ifndef SPLIT_PROXY_ARGS
2018 if (!suppress_blocklists)
2020 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
2022 #endif /* ndef SPLIT_PROXY_ARGS */
2024 /* the old one is now obsolete */
2025 if ( NULL != current_re_filterfile )
2027 current_re_filterfile->unloader = unload_re_filterfile;
2030 fs->next = files->next;
2032 current_re_filterfile = fs;
2041 load_re_filterfile_error:
2042 log_error(LOG_LEVEL_ERROR, "can't load re_filterfile '%s': %E", re_filterfile);
2046 #endif /* def PCRS */
2050 /*********************************************************************
2052 * Function : load_popupfile
2054 * Description : Load, and parse the popup blocklist.
2057 * 1 : csp = Current client state (buffers, headers, etc...)
2059 * Returns : 0 => success, else there was an error.
2061 *********************************************************************/
2062 int load_popupfile(struct client_state *csp)
2065 char buf[BUFSIZ], *p, *q;
2066 struct popup_blocklist *entry = NULL;
2067 struct popup_settings * data;
2068 struct file_list *fs;
2072 if (!check_file_changed(current_popupfile, popupfile, &fs))
2074 /* No need to load */
2077 csp->plist = current_popupfile;
2083 goto load_popupfile_error;
2086 fs->f = data = (struct popup_settings *)zalloc(sizeof(*data));
2089 goto load_popupfile_error;
2092 if ((fp = fopen(popupfile, "r")) == NULL)
2094 goto load_popupfile_error;
2097 while (read_config_line(buf, sizeof(buf), fp, fs) != NULL)
2099 entry = (struct popup_blocklist*)zalloc(sizeof(struct popup_blocklist));
2103 goto load_popupfile_error;
2106 /* Handle allowed hosts. */
2109 /* Rememeber: skip the tilde */
2110 entry->host_name = strdup( buf + 1 );
2111 if (!entry->host_name)
2114 goto load_popupfile_error;
2117 entry->next = data->allowed;
2118 data->allowed = entry;
2123 entry->host_name = strdup( buf );
2124 if (!entry->host_name)
2127 goto load_popupfile_error;
2130 entry->next = data->blocked;
2131 data->blocked = entry;
2137 #ifndef SPLIT_PROXY_ARGS
2138 if (!suppress_blocklists)
2140 fs->proxy_args = strsav(fs->proxy_args, "</pre>");
2142 #endif /* ndef SPLIT_PROXY_ARGS */
2144 /* the old one is now obsolete */
2145 if ( NULL != current_popupfile )
2147 current_popupfile->unloader = unload_popupfile;
2150 fs->next = files->next;
2152 current_popupfile = fs;
2161 load_popupfile_error:
2162 log_error(LOG_LEVEL_ERROR, "can't load popupfile '%s': %E", popupfile);
2166 #endif /* def KILLPOPUPS */
2170 /*********************************************************************
2172 * Function : add_loader
2174 * Description : Called from `load_config'. Called once for each input
2175 * file found in config.
2178 * 1 : loader = pointer to a function that can parse and load
2179 * the appropriate config file.
2183 *********************************************************************/
2184 void add_loader(int (*loader)(struct client_state *))
2188 for (i=0; i < NLOADERS; i++)
2190 if (loaders[i] == NULL)
2192 loaders[i] = loader;
2200 /*********************************************************************
2202 * Function : run_loader
2204 * Description : Called from `load_config' and `listen_loop'. This
2205 * function keeps the "csp" current with any file mods
2206 * since the last loop. If a file is unchanged, the
2207 * loader functions do NOT reload the file.
2210 * 1 : csp = Current client state (buffers, headers, etc...)
2212 * Returns : 0 => Ok, everything else is an error.
2214 *********************************************************************/
2215 int run_loader(struct client_state *csp)
2220 for (i=0; i < NLOADERS; i++)
2222 if (loaders[i] == NULL)
2226 ret |= (loaders[i])(csp);
2233 /*********************************************************************
2235 * Function : remove_all_loaders
2237 * Description : Remove all loaders from the list.
2243 *********************************************************************/
2244 void remove_all_loaders(void)
2246 memset( loaders, 0, sizeof( loaders ) );