Addressed bug #719435
[privoxy.git] / loadcfg.c
1 const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.48.2.3 2003/03/11 11:53:59 oes Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/Attic/loadcfg.c,v $
5  *
6  * Purpose     :  Loads settings from the configuration file into
7  *                global variables.  This file contains both the
8  *                routine to load the configuration and the global
9  *                variables it writes to.
10  *
11  * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
12  *                Privoxy team. http://www.privoxy.org/
13  *
14  *                Based on the Internet Junkbuster originally written
15  *                by and Copyright (C) 1997 Anonymous Coders and
16  *                Junkbusters Corporation.  http://www.junkbusters.com
17  *
18  *                This program is free software; you can redistribute it
19  *                and/or modify it under the terms of the GNU General
20  *                Public License as published by the Free Software
21  *                Foundation; either version 2 of the License, or (at
22  *                your option) any later version.
23  *
24  *                This program is distributed in the hope that it will
25  *                be useful, but WITHOUT ANY WARRANTY; without even the
26  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
27  *                PARTICULAR PURPOSE.  See the GNU General Public
28  *                License for more details.
29  *
30  *                The GNU General Public License should be included with
31  *                this file.  If not, you can view it at
32  *                http://www.gnu.org/copyleft/gpl.html
33  *                or write to the Free Software Foundation, Inc., 59
34  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
35  *
36  * Revisions   :
37  *    $Log: loadcfg.c,v $
38  *    Revision 1.48.2.3  2003/03/11 11:53:59  oes
39  *    Cosmetic: Renamed cryptic variable
40  *
41  *    Revision 1.48.2.2  2002/11/12 16:28:20  oes
42  *    Move unrelated variable declaration out of #ifdef FEATURE_ACL; fixes bug #636655
43  *
44  *    Revision 1.48.2.1  2002/08/21 17:58:05  oes
45  *    Temp kludge to let user and default action file be edited through win32 GUI (FR 592080)
46  *
47  *    Revision 1.48  2002/05/14 21:30:38  oes
48  *    savearg now uses own linking code instead of (now special-cased) add_help_link
49  *
50  *    Revision 1.47  2002/05/12 21:36:29  jongfoster
51  *    Correcting function comments
52  *
53  *    Revision 1.46  2002/04/26 12:55:14  oes
54  *     - New option "user-manual", defaults to our site
55  *       via project.h #define
56  *     - savearg now embeds option names in help links
57  *
58  *    Revision 1.45  2002/04/24 02:11:54  oes
59  *    Jon's multiple AF patch: Allow up to MAX_ACTION_FILES actionsfile options
60  *
61  *    Revision 1.44  2002/04/08 20:37:13  swa
62  *    fixed JB spelling
63  *
64  *    Revision 1.43  2002/04/08 20:36:50  swa
65  *    fixed JB spelling
66  *
67  *    Revision 1.42  2002/04/05 15:50:15  oes
68  *    fix for invalid HTML proxy_args
69  *
70  *    Revision 1.41  2002/03/31 17:19:00  jongfoster
71  *    Win32 only: Enabling STRICT to fix a VC++ compile warning.
72  *
73  *    Revision 1.40  2002/03/26 22:29:55  swa
74  *    we have a new homepage!
75  *
76  *    Revision 1.39  2002/03/24 13:25:43  swa
77  *    name change related issues
78  *
79  *    Revision 1.38  2002/03/24 13:05:48  jongfoster
80  *    Renaming re_filterfile to filterfile
81  *
82  *    Revision 1.37  2002/03/16 23:54:06  jongfoster
83  *    Adding graceful termination feature, to help look for memory leaks.
84  *    If you enable this (which, by design, has to be done by hand
85  *    editing config.h) and then go to http://i.j.b/die, then the program
86  *    will exit cleanly after the *next* request.  It should free all the
87  *    memory that was used.
88  *
89  *    Revision 1.36  2002/03/13 00:27:05  jongfoster
90  *    Killing warnings
91  *
92  *    Revision 1.35  2002/03/07 03:52:44  oes
93  *    Set logging to tty for --no-daemon mode
94  *
95  *    Revision 1.34  2002/03/06 23:14:35  jongfoster
96  *    Trivial cosmetic changes to make function comments easier to find.
97  *
98  *    Revision 1.33  2002/03/05 04:52:42  oes
99  *    Deleted non-errlog debugging code
100  *
101  *    Revision 1.32  2002/03/04 18:24:53  oes
102  *    Re-enabled output of unknown config directive hash
103  *
104  *    Revision 1.31  2002/03/03 15:07:20  oes
105  *    Re-enabled automatic config reloading
106  *
107  *    Revision 1.30  2002/01/22 23:31:43  jongfoster
108  *    Replacing strsav() with string_append()
109  *
110  *    Revision 1.29  2002/01/17 21:02:30  jongfoster
111  *    Moving all our URL and URL pattern parsing code to urlmatch.c.
112  *
113  *    Renaming free_url to free_url_spec, since it frees a struct url_spec.
114  *
115  *    Revision 1.28  2001/12/30 14:07:32  steudten
116  *    - Add signal handling (unix)
117  *    - Add SIGHUP handler (unix)
118  *    - Add creation of pidfile (unix)
119  *    - Add action 'top' in rc file (RH)
120  *    - Add entry 'SIGNALS' to manpage
121  *    - Add exit message to logfile (unix)
122  *
123  *    Revision 1.27  2001/11/07 00:02:13  steudten
124  *    Add line number in error output for lineparsing for
125  *    actionsfile and configfile.
126  *    Special handling for CLF added.
127  *
128  *    Revision 1.26  2001/11/05 21:41:43  steudten
129  *    Add changes to be a real daemon just for unix os.
130  *    (change cwd to /, detach from controlling tty, set
131  *    process group and session leader to the own process.
132  *    Add DBG() Macro.
133  *    Add some fatal-error log message for failed malloc().
134  *    Add '-d' if compiled with 'configure --with-debug' to
135  *    enable debug output.
136  *
137  *    Revision 1.25  2001/10/25 03:40:48  david__schmidt
138  *    Change in porting tactics: OS/2's EMX porting layer doesn't allow multiple
139  *    threads to call select() simultaneously.  So, it's time to do a real, live,
140  *    native OS/2 port.  See defines for __EMX__ (the porting layer) vs. __OS2__
141  *    (native). Both versions will work, but using __OS2__ offers multi-threading.
142  *
143  *    Revision 1.24  2001/10/23 21:40:30  jongfoster
144  *    Added support for enable-edit-actions and enable-remote-toggle config
145  *    file options.
146  *
147  *    Revision 1.23  2001/10/07 15:36:00  oes
148  *    Introduced new config option "buffer-limit"
149  *
150  *    Revision 1.22  2001/09/22 16:36:59  jongfoster
151  *    Removing unused parameter fs from read_config_line()
152  *
153  *    Revision 1.21  2001/09/16 17:10:43  jongfoster
154  *    Moving function savearg() here, since it was the only thing left in
155  *    showargs.c.
156  *
157  *    Revision 1.20  2001/07/30 22:08:36  jongfoster
158  *    Tidying up #defines:
159  *    - All feature #defines are now of the form FEATURE_xxx
160  *    - Permanently turned off WIN_GUI_EDIT
161  *    - Permanently turned on WEBDAV and SPLIT_PROXY_ARGS
162  *
163  *    Revision 1.19  2001/07/15 17:45:16  jongfoster
164  *    Removing some unused #includes
165  *
166  *    Revision 1.18  2001/07/13 14:01:14  oes
167  *     - Removed all #ifdef PCRS
168  *     - Removed vim-settings
169  *
170  *    Revision 1.17  2001/06/29 13:31:03  oes
171  *    - Improved comments
172  *    - Fixed (actionsfile) and sorted hashes
173  *    - Introduced admin_address and proxy-info-url
174  *      as config parameters
175  *    - Renamed config->proxy_args_invocation (which didn't have
176  *      the invocation but the options!) to config->proxy_args
177  *    - Various adaptions
178  *    - Removed logentry from cancelled commit
179  *
180  *    Revision 1.16  2001/06/09 10:55:28  jongfoster
181  *    Changing BUFSIZ ==> BUFFER_SIZE
182  *
183  *    Revision 1.15  2001/06/07 23:13:40  jongfoster
184  *    Merging ACL and forward files into config file.
185  *    Cosmetic: Sorting config file options alphabetically.
186  *    Cosmetic: Adding brief syntax comments to config file options.
187  *
188  *    Revision 1.14  2001/06/07 14:46:25  joergs
189  *    Missing make_path() added for re_filterfile.
190  *
191  *    Revision 1.13  2001/06/05 22:33:54  jongfoster
192  *
193  *    Fixed minor memory leak.
194  *    Also now uses make_path to prepend the pathnames.
195  *
196  *    Revision 1.12  2001/06/05 20:04:09  jongfoster
197  *    Now uses _snprintf() in place of snprintf() under Win32.
198  *
199  *    Revision 1.11  2001/06/04 18:31:58  swa
200  *    files are now prefixed with either `confdir' or `logdir'.
201  *    `make redhat-dist' replaces both entries confdir and logdir
202  *    with redhat values
203  *
204  *    Revision 1.10  2001/06/03 19:11:54  oes
205  *    introduced confdir option
206  *
207  *    Revision 1.9  2001/06/01 20:06:24  jongfoster
208  *    Removed support for "tinygif" option - moved to actions file.
209  *
210  *    Revision 1.8  2001/05/31 21:27:13  jongfoster
211  *    Removed many options from the config file and into the
212  *    "actions" file: add_forwarded, suppress_vanilla_wafer,
213  *    wafer, add_header, user_agent, referer, from
214  *    Also globally replaced "permission" with "action".
215  *
216  *    Revision 1.7  2001/05/29 09:50:24  jongfoster
217  *    Unified blocklist/imagelist/permissionslist.
218  *    File format is still under discussion, but the internal changes
219  *    are (mostly) done.
220  *
221  *    Also modified interceptor behaviour:
222  *    - We now intercept all URLs beginning with one of the following
223  *      prefixes (and *only* these prefixes):
224  *        * http://i.j.b/
225  *        * http://ijbswa.sf.net/config/
226  *        * http://ijbswa.sourceforge.net/config/
227  *    - New interceptors "home page" - go to http://i.j.b/ to see it.
228  *    - Internal changes so that intercepted and fast redirect pages
229  *      are not replaced with an image.
230  *    - Interceptors now have the option to send a binary page direct
231  *      to the client. (i.e. ijb-send-banner uses this)
232  *    - Implemented show-url-info interceptor.  (Which is why I needed
233  *      the above interceptors changes - a typical URL is
234  *      "http://i.j.b/show-url-info?url=www.somesite.com/banner.gif".
235  *      The previous mechanism would not have intercepted that, and
236  *      if it had been intercepted then it then it would have replaced
237  *      it with an image.)
238  *
239  *    Revision 1.6  2001/05/26 00:28:36  jongfoster
240  *    Automatic reloading of config file.
241  *    Removed obsolete SIGHUP support (Unix) and Reload menu option (Win32).
242  *    Most of the global variables have been moved to a new
243  *    struct configuration_spec, accessed through csp->config->globalname
244  *    Most of the globals remaining are used by the Win32 GUI.
245  *
246  *    Revision 1.5  2001/05/25 22:34:30  jongfoster
247  *    Hard tabs->Spaces
248  *
249  *    Revision 1.4  2001/05/22 18:46:04  oes
250  *
251  *    - Enabled filtering banners by size rather than URL
252  *      by adding patterns that replace all standard banner
253  *      sizes with the "Junkbuster" gif to the re_filterfile
254  *
255  *    - Enabled filtering WebBugs by providing a pattern
256  *      which kills all 1x1 images
257  *
258  *    - Added support for PCRE_UNGREEDY behaviour to pcrs,
259  *      which is selected by the (nonstandard and therefore
260  *      capital) letter 'U' in the option string.
261  *      It causes the quantifiers to be ungreedy by default.
262  *      Appending a ? turns back to greedy (!).
263  *
264  *    - Added a new interceptor ijb-send-banner, which
265  *      sends back the "Junkbuster" gif. Without imagelist or
266  *      MSIE detection support, or if tinygif = 1, or the
267  *      URL isn't recognized as an imageurl, a lame HTML
268  *      explanation is sent instead.
269  *
270  *    - Added new feature, which permits blocking remote
271  *      script redirects and firing back a local redirect
272  *      to the browser.
273  *      The feature is conditionally compiled, i.e. it
274  *      can be disabled with --disable-fast-redirects,
275  *      plus it must be activated by a "fast-redirects"
276  *      line in the config file, has its own log level
277  *      and of course wants to be displayed by show-proxy-args
278  *      Note: Boy, all the #ifdefs in 1001 locations and
279  *      all the fumbling with configure.in and acconfig.h
280  *      were *way* more work than the feature itself :-(
281  *
282  *    - Because a generic redirect template was needed for
283  *      this, tinygif = 3 now uses the same.
284  *
285  *    - Moved GIFs, and other static HTTP response templates
286  *      to project.h
287  *
288  *    - Some minor fixes
289  *
290  *    - Removed some >400 CRs again (Jon, you really worked
291  *      a lot! ;-)
292  *
293  *    Revision 1.3  2001/05/20 01:21:20  jongfoster
294  *    Version 2.9.4 checkin.
295  *    - Merged popupfile and cookiefile, and added control over PCRS
296  *      filtering, in new "permissionsfile".
297  *    - Implemented LOG_LEVEL_FATAL, so that if there is a configuration
298  *      file error you now get a message box (in the Win32 GUI) rather
299  *      than the program exiting with no explanation.
300  *    - Made killpopup use the PCRS MIME-type checking and HTTP-header
301  *      skipping.
302  *    - Removed tabs from "config"
303  *    - Moved duplicated url parsing code in "loaders.c" to a new funcition.
304  *    - Bumped up version number.
305  *
306  *    Revision 1.2  2001/05/17 23:01:01  oes
307  *     - Cleaned CRLF's from the sources and related files
308  *
309  *    Revision 1.1.1.1  2001/05/15 13:58:58  oes
310  *    Initial import of version 2.9.3 source tree
311  *
312  *
313  *********************************************************************/
314 \f
315
316 #include "config.h"
317
318 #include <stdio.h>
319 #include <sys/types.h>
320 #include <stdlib.h>
321 #include <string.h>
322 #include <signal.h>
323 #include <fcntl.h>
324 #include <errno.h>
325 #include <ctype.h>
326 #include <assert.h>
327
328 #ifdef _WIN32
329
330 # ifndef STRICT
331 #  define STRICT
332 # endif
333 # include <windows.h>
334
335 # include "win32.h"
336 # ifndef _WIN_CONSOLE
337 #  include "w32log.h"
338 # endif /* ndef _WIN_CONSOLE */
339
340 /* VC++ has "_snprintf", not "snprintf" */
341 #define snprintf _snprintf
342
343 #else /* ifndef _WIN32 */
344
345 #ifndef __OS2__
346 # include <unistd.h>
347 # include <sys/wait.h>
348 #endif
349 # include <sys/time.h>
350 # include <sys/stat.h>
351 # include <signal.h>
352
353 #endif
354
355 #include "loadcfg.h"
356 #include "list.h"
357 #include "jcc.h"
358 #include "filters.h"
359 #include "loaders.h"
360 #include "miscutil.h"
361 #include "errlog.h"
362 #include "ssplit.h"
363 #include "encode.h"
364 #include "urlmatch.h"
365 #include "cgi.h"
366
367 const char loadcfg_h_rcs[] = LOADCFG_H_VERSION;
368
369 /*
370  * Fix a problem with Solaris.  There should be no effect on other
371  * platforms.
372  * Solaris's isspace() is a macro which uses it's argument directly
373  * as an array index.  Therefore we need to make sure that high-bit
374  * characters generate +ve values, and ideally we also want to make
375  * the argument match the declared parameter type of "int".
376  */
377 #define ijb_isupper(__X) isupper((int)(unsigned char)(__X))
378 #define ijb_tolower(__X) tolower((int)(unsigned char)(__X))
379
380 #ifdef FEATURE_TOGGLE
381 /* Privoxy is enabled by default. */
382 int global_toggle_state = 1;
383 #endif /* def FEATURE_TOGGLE */
384
385 /* The filename of the configfile */
386 const char *configfile  = NULL;
387
388 /*
389  * CGI functions will later need access to the invocation args,
390  * so we will make argc and argv global.
391  */
392 int Argc = 0;
393 const char **Argv = NULL;
394
395 static struct file_list *current_configfile = NULL;
396
397
398 /*
399  * This takes the "cryptic" hash of each keyword and aliases them to
400  * something a little more readable.  This also makes changing the
401  * hash values easier if they should change or the hash algorthm changes.
402  * Use the included "hash" program to find out what the hash will be
403  * for any string supplied on the command line.  (Or just put it in the
404  * config file and read the number from the error message in the log).
405  *
406  * Please keep this list sorted alphabetically (but with the Windows
407  * console and GUI specific options last).
408  */
409
410 #define hash_actions_file              1196306641ul /* "actionsfile" */
411 #define hash_admin_address             4112573064ul /* "admin-address" */
412 #define hash_buffer_limit              1881726070ul /* "buffer-limit */
413 #define hash_confdir                      1978389ul /* "confdir" */
414 #define hash_debug                          78263ul /* "debug" */
415 #define hash_deny_access               1227333715ul /* "deny-access" */
416 #define hash_enable_edit_actions       2517097536ul /* "enable-edit-actions" */
417 #define hash_enable_remote_toggle      2979744683ul /* "enable-remote-toggle" */
418 #define hash_filterfile                 250887266ul /* "filterfile" */
419 #define hash_forward                      2029845ul /* "forward" */
420 #define hash_forward_socks4            3963965521ul /* "forward-socks4" */
421 #define hash_forward_socks4a           2639958518ul /* "forward-socks4a" */
422 #define hash_jarfile                      2046641ul /* "jarfile" */
423 #define hash_listen_address            1255650842ul /* "listen-address" */
424 #define hash_logdir                        422889ul /* "logdir" */
425 #define hash_logfile                      2114766ul /* "logfile" */
426 #define hash_permit_access             3587953268ul /* "permit-access" */
427 #define hash_proxy_info_url            3903079059ul /* "proxy-info-url" */
428 #define hash_single_threaded           4250084780ul /* "single-threaded" */
429 #define hash_suppress_blocklists       1948693308ul /* "suppress-blocklists" */
430 #define hash_toggle                        447966ul /* "toggle" */
431 #define hash_trust_info_url             430331967ul /* "trust-info-url" */
432 #define hash_trustfile                   56494766ul /* "trustfile" */
433 #define hash_usermanual                1416668518ul /* "user-manual" */
434 #define hash_activity_animation        1817904738ul /* "activity-animation" */
435 #define hash_close_button_minimizes    3651284693ul /* "close-button-minimizes" */
436 #define hash_hide_console              2048809870ul /* "hide-console" */
437 #define hash_log_buffer_size           2918070425ul /* "log-buffer-size" */
438 #define hash_log_font_name             2866730124ul /* "log-font-name" */
439 #define hash_log_font_size             2866731014ul /* "log-font-size" */
440 #define hash_log_highlight_messages    4032101240ul /* "log-highlight-messages" */
441 #define hash_log_max_lines             2868344173ul /* "log-max-lines" */
442 #define hash_log_messages              2291744899ul /* "log-messages" */
443 #define hash_show_on_task_bar           215410365ul /* "show-on-task-bar" */
444
445
446 static void savearg(char *command, char *argument, struct configuration_spec * config);
447
448 /*********************************************************************
449  *
450  * Function    :  unload_configfile
451  *
452  * Description :  Free the config structure and all components.
453  *
454  * Parameters  :
455  *          1  :  data: struct configuration_spec to unload
456  *
457  * Returns     :  N/A
458  *
459  *********************************************************************/
460 void unload_configfile (void * data)
461 {
462    struct configuration_spec * config = (struct configuration_spec *)data;
463    struct forward_spec *cur_fwd = config->forward;
464    int i;
465
466 #ifdef FEATURE_ACL
467    struct access_control_list *cur_acl = config->acl;
468
469    while (cur_acl != NULL)
470    {
471       struct access_control_list * next_acl = cur_acl->next;
472       free(cur_acl);
473       cur_acl = next_acl;
474    }
475    config->acl = NULL;
476 #endif /* def FEATURE_ACL */
477
478    while (cur_fwd != NULL)
479    {
480       struct forward_spec * next_fwd = cur_fwd->next;
481       free_url_spec(cur_fwd->url);
482
483       freez(cur_fwd->gateway_host);
484       freez(cur_fwd->forward_host);
485       free(cur_fwd);
486       cur_fwd = next_fwd;
487    }
488    config->forward = NULL;
489
490 #ifdef FEATURE_COOKIE_JAR
491    if ( NULL != config->jar )
492    {
493       fclose( config->jar );
494       config->jar = NULL;
495    }
496 #endif /* def FEATURE_COOKIE_JAR */
497
498    freez(config->confdir);
499    freez(config->logdir);
500
501    freez(config->haddr);
502    freez(config->logfile);
503
504    for (i = 0; i < MAX_ACTION_FILES; i++)
505    {
506       freez(config->actions_file_short[i]);
507       freez(config->actions_file[i]);
508    }
509
510    freez(config->admin_address);
511    freez(config->proxy_info_url);
512    freez(config->proxy_args);
513    freez(config->usermanual);
514
515 #ifdef FEATURE_COOKIE_JAR
516    freez(config->jarfile);
517 #endif /* def FEATURE_COOKIE_JAR */
518
519    freez(config->re_filterfile);
520
521 }
522
523
524 #ifdef FEATURE_GRACEFUL_TERMINATION
525 /*********************************************************************
526  *
527  * Function    :  unload_current_config_file
528  *
529  * Description :  Unloads current config file - reset to state at
530  *                beginning of program.
531  *
532  * Parameters  :  None
533  *
534  * Returns     :  N/A
535  *
536  *********************************************************************/
537 void unload_current_config_file(void)
538 {
539    if (current_configfile)
540    {
541       current_configfile->unloader = unload_configfile;
542       current_configfile = NULL;
543    }
544 }
545 #endif
546
547
548 /*********************************************************************
549  *
550  * Function    :  load_config
551  *
552  * Description :  Load the config file and all parameters.
553  *
554  * Parameters  :  None
555  *
556  * Returns     :  The configuration_spec, or NULL on error.
557  *
558  *********************************************************************/
559 struct configuration_spec * load_config(void)
560 {
561    char buf[BUFFER_SIZE];
562    char *p, *q;
563    FILE *configfp = NULL;
564    struct configuration_spec * config = NULL;
565    struct client_state * fake_csp;
566    struct file_list *fs;
567    unsigned long linenum = 0;
568    int i;
569
570    if ( !check_file_changed(current_configfile, configfile, &fs))
571    {
572       /* No need to load */
573       return ((struct configuration_spec *)current_configfile->f);
574    }
575    if (!fs)
576    {
577       log_error(LOG_LEVEL_FATAL, "can't check configuration file '%s':  %E",
578                 configfile);
579    }
580
581    log_error(LOG_LEVEL_INFO, "loading configuration file '%s':", configfile);
582
583 #ifdef FEATURE_TOGGLE
584    global_toggle_state      = 1;
585 #endif /* def FEATURE_TOGGLE */
586
587    fs->f = config = (struct configuration_spec *)zalloc(sizeof(*config));
588
589    if (config==NULL)
590    {
591       freez(fs->filename);
592       freez(fs);
593       log_error(LOG_LEVEL_FATAL, "can't allocate memory for configuration");
594       /* Never get here - LOG_LEVEL_FATAL causes program exit */
595    }
596
597    /*
598     * This is backwards from how it's usually done.
599     * Following the usual pattern, "fs" would be stored in a member
600     * variable in "csp", and then we'd access "config" from "fs->f",
601     * using a cast.  However, "config" is used so often that a
602     * cast each time would be very ugly, and the extra indirection
603     * would waste CPU cycles.  Therefore we store "config" in
604     * "csp->config", and "fs" in "csp->config->config_file_list".
605     */
606    config->config_file_list = fs;
607
608    /*
609     * Set to defaults
610     */
611    config->multi_threaded    = 1;
612    config->hport             = HADDR_PORT;
613    config->buffer_limit      = 4096 * 1024;
614    config->usermanual        = strdup(USER_MANUAL_URL);
615    config->proxy_args        = strdup("");
616
617    if ((configfp = fopen(configfile, "r")) == NULL)
618    {
619       log_error(LOG_LEVEL_FATAL, "can't open configuration file '%s':  %E",
620               configfile);
621       /* Never get here - LOG_LEVEL_FATAL causes program exit */
622    }
623
624    while (read_config_line(buf, sizeof(buf), configfp, &linenum) != NULL)
625    {
626       char cmd[BUFFER_SIZE];
627       char arg[BUFFER_SIZE];
628       char tmp[BUFFER_SIZE];
629 #ifdef FEATURE_ACL
630       struct access_control_list *cur_acl;
631 #endif /* def FEATURE_ACL */
632       struct forward_spec *cur_fwd;
633       int vec_count;
634       char *vec[3];
635
636       strcpy(tmp, buf);
637
638       /* Copy command (i.e. up to space or tab) into cmd */
639       p = buf;
640       q = cmd;
641       while (*p && (*p != ' ') && (*p != '\t'))
642       {
643          *q++ = *p++;
644       }
645       *q = '\0';
646
647       /* Skip over the whitespace in buf */
648       while (*p && ((*p == ' ') || (*p == '\t')))
649       {
650          p++;
651       }
652
653       /* Copy the argument into arg */
654       strcpy(arg, p);
655
656       /* Should never happen, but check this anyway */
657       if (*cmd == '\0')
658       {
659          continue;
660       }
661
662       /* Make sure the command field is lower case */
663       for (p=cmd; *p; p++)
664       {
665          if (ijb_isupper(*p))
666          {
667             *p = ijb_tolower(*p);
668          }
669       }
670
671       /* Save the argument for show-proxy-args */
672       savearg(cmd, arg, config);
673
674
675       switch( hash_string( cmd ) )
676       {
677 /* *************************************************************************
678  * actionsfile actions-file-name
679  * In confdir by default
680  * *************************************************************************/
681          case hash_actions_file :
682             i = 0;
683             while ((i < MAX_ACTION_FILES) && (NULL != config->actions_file[i]))
684             {
685                i++;
686             }
687
688             if (i >= MAX_ACTION_FILES)
689             {
690                log_error(LOG_LEVEL_FATAL, "Too many 'actionsfile' directives in config file - limit is %d.\n"
691                   "(You can increase this limit by changing MAX_ACTION_FILES in project.h and recompiling).",
692                   MAX_ACTION_FILES);
693             }
694             config->actions_file_short[i] = strdup(arg);
695             p = malloc(strlen(arg) + sizeof(".action"));
696             if (p == NULL)
697             {
698                log_error(LOG_LEVEL_FATAL, "Out of memory");
699             }
700             strcpy(p, arg);
701             strcat(p, ".action");
702             config->actions_file[i] = make_path(config->confdir, p);
703             free(p);
704             continue;
705
706 /* *************************************************************************
707  * admin-address email-address
708  * *************************************************************************/
709          case hash_admin_address :
710             freez(config->admin_address);
711             config->admin_address = strdup(arg);
712             continue;
713
714 /* *************************************************************************
715  * buffer-limit n
716  * *************************************************************************/
717          case hash_buffer_limit :
718             config->buffer_limit = (size_t) 1024 * atoi(arg);
719             continue;
720
721 /* *************************************************************************
722  * confdir directory-name
723  * *************************************************************************/
724          case hash_confdir :
725             freez(config->confdir);
726             config->confdir = make_path( NULL, arg);
727             continue;
728
729 /* *************************************************************************
730  * debug n
731  * Specifies debug level, multiple values are ORed together.
732  * *************************************************************************/
733          case hash_debug :
734             config->debug |= atoi(arg);
735             continue;
736
737 /* *************************************************************************
738  * deny-access source-ip[/significant-bits] [dest-ip[/significant-bits]]
739  * *************************************************************************/
740 #ifdef FEATURE_ACL
741          case hash_deny_access:
742             vec_count = ssplit(arg, " \t", vec, SZ(vec), 1, 1);
743
744             if ((vec_count != 1) && (vec_count != 2))
745             {
746                log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for "
747                      "deny-access directive in configuration file.");
748                string_append(&config->proxy_args,
749                   "<br>\nWARNING: Wrong number of parameters for "
750                   "deny-access directive in configuration file.<br><br>\n");
751                continue;
752             }
753
754             /* allocate a new node */
755             cur_acl = (struct access_control_list *) zalloc(sizeof(*cur_acl));
756
757             if (cur_acl == NULL)
758             {
759                log_error(LOG_LEVEL_FATAL, "can't allocate memory for configuration");
760                /* Never get here - LOG_LEVEL_FATAL causes program exit */
761                continue;
762             }
763             cur_acl->action = ACL_DENY;
764
765             if (acl_addr(vec[0], cur_acl->src) < 0)
766             {
767                log_error(LOG_LEVEL_ERROR, "Invalid source IP for deny-access "
768                      "directive in configuration file: \"%s\"", vec[0]);
769                string_append(&config->proxy_args,
770                   "<br>\nWARNING: Invalid source IP for deny-access directive"
771                   " in configuration file: \"");
772                string_append(&config->proxy_args,
773                   vec[0]);
774                string_append(&config->proxy_args,
775                   "\"<br><br>\n");
776                freez(cur_acl);
777                continue;
778             }
779             if (vec_count == 2)
780             {
781                if (acl_addr(vec[1], cur_acl->dst) < 0)
782                {
783                   log_error(LOG_LEVEL_ERROR, "Invalid destination IP for deny-access "
784                         "directive in configuration file: \"%s\"", vec[0]);
785                   string_append(&config->proxy_args,
786                      "<br>\nWARNING: Invalid destination IP for deny-access directive"
787                      " in configuration file: \"");
788                   string_append(&config->proxy_args,
789                      vec[0]);
790                   string_append(&config->proxy_args,
791                      "\"<br><br>\n");
792                   freez(cur_acl);
793                   continue;
794                }
795             }
796
797             /*
798              * Add it to the list.  Note we reverse the list to get the
799              * behaviour the user expects.  With both the ACL and
800              * actions file, the last match wins.  However, the internal
801              * implementations are different:  The actions file is stored
802              * in the same order as the file, and scanned completely.
803              * With the ACL, we reverse the order as we load it, then
804              * when we scan it we stop as soon as we get a match.
805              */
806             cur_acl->next  = config->acl;
807             config->acl = cur_acl;
808
809             continue;
810 #endif /* def FEATURE_ACL */
811
812 /* *************************************************************************
813  * enable-edit-actions 0|1
814  * *************************************************************************/
815 #ifdef FEATURE_CGI_EDIT_ACTIONS
816          case hash_enable_edit_actions:
817             if ((*arg != '\0') && (0 != atoi(arg)))
818             {
819                config->feature_flags |= RUNTIME_FEATURE_CGI_EDIT_ACTIONS;
820             }
821             else
822             {
823                config->feature_flags &= ~RUNTIME_FEATURE_CGI_EDIT_ACTIONS;
824             }
825             continue;
826 #endif /* def FEATURE_CGI_EDIT_ACTIONS */
827
828 /* *************************************************************************
829  * enable-remote-toggle 0|1
830  * *************************************************************************/
831 #ifdef FEATURE_CGI_EDIT_ACTIONS
832          case hash_enable_remote_toggle:
833             if ((*arg != '\0') && (0 != atoi(arg)))
834             {
835                config->feature_flags |= RUNTIME_FEATURE_CGI_TOGGLE;
836             }
837             else
838             {
839                config->feature_flags &= ~RUNTIME_FEATURE_CGI_TOGGLE;
840             }
841             continue;
842 #endif /* def FEATURE_CGI_EDIT_ACTIONS */
843
844 /* *************************************************************************
845  * filterfile file-name
846  * In confdir by default.
847  * *************************************************************************/
848          case hash_filterfile :
849             if(config->re_filterfile)
850             {
851                log_error(LOG_LEVEL_ERROR, "Ignoring extraneous directive 'filterfile %s' "
852                   "in line %lu in configuration file (%s).", arg, linenum, configfile);
853                string_append(&config->proxy_args, 
854                   " <b><font color=\"red\">WARNING: extraneous directive, ignored</font></b>");
855                continue;
856             }
857             config->re_filterfile = make_path(config->confdir, arg);
858             continue;
859
860 /* *************************************************************************
861  * forward url-pattern (.|http-proxy-host[:port])
862  * *************************************************************************/
863          case hash_forward:
864             vec_count = ssplit(arg, " \t", vec, SZ(vec), 1, 1);
865
866             if (vec_count != 2)
867             {
868                log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for forward "
869                      "directive in configuration file.");
870                string_append(&config->proxy_args,
871                   "<br>\nWARNING: Wrong number of parameters for "
872                   "forward directive in configuration file.");
873                continue;
874             }
875
876             /* allocate a new node */
877             cur_fwd = zalloc(sizeof(*cur_fwd));
878             if (cur_fwd == NULL)
879             {
880                log_error(LOG_LEVEL_FATAL, "can't allocate memory for configuration");
881                /* Never get here - LOG_LEVEL_FATAL causes program exit */
882                continue;
883             }
884
885             cur_fwd->type = SOCKS_NONE;
886
887             /* Save the URL pattern */
888             if (create_url_spec(cur_fwd->url, vec[0]))
889             {
890                log_error(LOG_LEVEL_ERROR, "Bad URL specifier for forward "
891                      "directive in configuration file.");
892                string_append(&config->proxy_args,
893                   "<br>\nWARNING: Bad URL specifier for "
894                   "forward directive in configuration file.");
895                continue;
896             }
897
898             /* Parse the parent HTTP proxy host:port */
899             p = vec[1];
900
901             if (strcmp(p, ".") != 0)
902             {
903                cur_fwd->forward_host = strdup(p);
904
905                if (NULL != (p = strchr(cur_fwd->forward_host, ':')))
906                {
907                   *p++ = '\0';
908                   cur_fwd->forward_port = atoi(p);
909                }
910
911                if (cur_fwd->forward_port <= 0)
912                {
913                   cur_fwd->forward_port = 8000;
914                }
915             }
916
917             /* Add to list. */
918             cur_fwd->next = config->forward;
919             config->forward = cur_fwd;
920
921             continue;
922
923 /* *************************************************************************
924  * forward-socks4 url-pattern socks-proxy[:port] (.|http-proxy[:port])
925  * *************************************************************************/
926          case hash_forward_socks4:
927             vec_count = ssplit(arg, " \t", vec, SZ(vec), 1, 1);
928
929             if (vec_count != 3)
930             {
931                log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for "
932                      "forward-socks4 directive in configuration file.");
933                string_append(&config->proxy_args,
934                   "<br>\nWARNING: Wrong number of parameters for "
935                   "forward-socks4 directive in configuration file.");
936                continue;
937             }
938
939             /* allocate a new node */
940             cur_fwd = zalloc(sizeof(*cur_fwd));
941             if (cur_fwd == NULL)
942             {
943                log_error(LOG_LEVEL_FATAL, "can't allocate memory for configuration");
944                /* Never get here - LOG_LEVEL_FATAL causes program exit */
945                continue;
946             }
947
948             cur_fwd->type = SOCKS_4;
949
950             /* Save the URL pattern */
951             if (create_url_spec(cur_fwd->url, vec[0]))
952             {
953                log_error(LOG_LEVEL_ERROR, "Bad URL specifier for forward-socks4 "
954                      "directive in configuration file.");
955                string_append(&config->proxy_args,
956                   "<br>\nWARNING: Bad URL specifier for "
957                   "forward-socks4 directive in configuration file.");
958                continue;
959             }
960
961             /* Parse the SOCKS proxy host[:port] */
962             p = vec[1];
963
964             if (strcmp(p, ".") != 0)
965             {
966                cur_fwd->gateway_host = strdup(p);
967
968                if (NULL != (p = strchr(cur_fwd->gateway_host, ':')))
969                {
970                   *p++ = '\0';
971                   cur_fwd->gateway_port = atoi(p);
972                }
973                if (cur_fwd->gateway_port <= 0)
974                {
975                   cur_fwd->gateway_port = 1080;
976                }
977             }
978
979             /* Parse the parent HTTP proxy host[:port] */
980             p = vec[2];
981
982             if (strcmp(p, ".") != 0)
983             {
984                cur_fwd->forward_host = strdup(p);
985
986                if (NULL != (p = strchr(cur_fwd->forward_host, ':')))
987                {
988                   *p++ = '\0';
989                   cur_fwd->forward_port = atoi(p);
990                }
991
992                if (cur_fwd->forward_port <= 0)
993                {
994                   cur_fwd->forward_port = 8000;
995                }
996             }
997
998             /* Add to list. */
999             cur_fwd->next = config->forward;
1000             config->forward = cur_fwd;
1001
1002             continue;
1003
1004 /* *************************************************************************
1005  * forward-socks4a url-pattern socks-proxy[:port] (.|http-proxy[:port])
1006  * *************************************************************************/
1007          case hash_forward_socks4a:
1008             vec_count = ssplit(arg, " \t", vec, SZ(vec), 1, 1);
1009
1010             if (vec_count != 3)
1011             {
1012                log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for "
1013                      "forward-socks4a directive in configuration file.");
1014                string_append(&config->proxy_args,
1015                   "<br>\nWARNING: Wrong number of parameters for "
1016                   "forward-socks4a directive in configuration file.");
1017                continue;
1018             }
1019
1020             /* allocate a new node */
1021             cur_fwd = zalloc(sizeof(*cur_fwd));
1022             if (cur_fwd == NULL)
1023             {
1024                log_error(LOG_LEVEL_FATAL, "can't allocate memory for configuration");
1025                /* Never get here - LOG_LEVEL_FATAL causes program exit */
1026                continue;
1027             }
1028
1029             cur_fwd->type = SOCKS_4A;
1030
1031             /* Save the URL pattern */
1032             if (create_url_spec(cur_fwd->url, vec[0]))
1033             {
1034                log_error(LOG_LEVEL_ERROR, "Bad URL specifier for forward-socks4a "
1035                      "directive in configuration file.");
1036                string_append(&config->proxy_args,
1037                   "<br>\nWARNING: Bad URL specifier for "
1038                   "forward-socks4a directive in configuration file.");
1039                continue;
1040             }
1041
1042             /* Parse the SOCKS proxy host[:port] */
1043             p = vec[1];
1044
1045             cur_fwd->gateway_host = strdup(p);
1046
1047             if (NULL != (p = strchr(cur_fwd->gateway_host, ':')))
1048             {
1049                *p++ = '\0';
1050                cur_fwd->gateway_port = atoi(p);
1051             }
1052             if (cur_fwd->gateway_port <= 0)
1053             {
1054                cur_fwd->gateway_port = 1080;
1055             }
1056
1057             /* Parse the parent HTTP proxy host[:port] */
1058             p = vec[2];
1059
1060             if (strcmp(p, ".") != 0)
1061             {
1062                cur_fwd->forward_host = strdup(p);
1063
1064                if (NULL != (p = strchr(cur_fwd->forward_host, ':')))
1065                {
1066                   *p++ = '\0';
1067                   cur_fwd->forward_port = atoi(p);
1068                }
1069
1070                if (cur_fwd->forward_port <= 0)
1071                {
1072                   cur_fwd->forward_port = 8000;
1073                }
1074             }
1075
1076             /* Add to list. */
1077             cur_fwd->next = config->forward;
1078             config->forward = cur_fwd;
1079
1080             continue;
1081
1082 /* *************************************************************************
1083  * jarfile jar-file-name
1084  * In logdir by default
1085  * *************************************************************************/
1086 #ifdef FEATURE_COOKIE_JAR
1087          case hash_jarfile :
1088             freez(config->jarfile);
1089             config->jarfile = make_path(config->logdir, arg);
1090             continue;
1091 #endif /* def FEATURE_COOKIE_JAR */
1092
1093 /* *************************************************************************
1094  * listen-address [ip][:port]
1095  * *************************************************************************/
1096          case hash_listen_address :
1097             freez(config->haddr);
1098             config->haddr = strdup(arg);
1099             continue;
1100
1101 /* *************************************************************************
1102  * logdir directory-name
1103  * *************************************************************************/
1104          case hash_logdir :
1105             freez(config->logdir);
1106             config->logdir = make_path(NULL, arg);
1107             continue;
1108
1109 /* *************************************************************************
1110  * logfile log-file-name
1111  * In logdir by default
1112  * *************************************************************************/
1113          case hash_logfile :
1114             freez(config->logfile);
1115             config->logfile = no_daemon ? NULL : make_path(config->logdir, arg);
1116             continue;
1117
1118 /* *************************************************************************
1119  * permit-access source-ip[/significant-bits] [dest-ip[/significant-bits]]
1120  * *************************************************************************/
1121 #ifdef FEATURE_ACL
1122          case hash_permit_access:
1123             vec_count = ssplit(arg, " \t", vec, SZ(vec), 1, 1);
1124
1125             if ((vec_count != 1) && (vec_count != 2))
1126             {
1127                log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for "
1128                      "permit-access directive in configuration file.");
1129                string_append(&config->proxy_args,
1130                   "<br>\nWARNING: Wrong number of parameters for "
1131                   "permit-access directive in configuration file.<br><br>\n");
1132
1133                continue;
1134             }
1135
1136             /* allocate a new node */
1137             cur_acl = (struct access_control_list *) zalloc(sizeof(*cur_acl));
1138
1139             if (cur_acl == NULL)
1140             {
1141                log_error(LOG_LEVEL_FATAL, "can't allocate memory for configuration");
1142                /* Never get here - LOG_LEVEL_FATAL causes program exit */
1143                continue;
1144             }
1145             cur_acl->action = ACL_PERMIT;
1146
1147             if (acl_addr(vec[0], cur_acl->src) < 0)
1148             {
1149                log_error(LOG_LEVEL_ERROR, "Invalid source IP for permit-access "
1150                      "directive in configuration file: \"%s\"", vec[0]);
1151                string_append(&config->proxy_args,
1152                   "<br>\nWARNING: Invalid source IP for permit-access directive"
1153                   " in configuration file: \"");
1154                string_append(&config->proxy_args,
1155                   vec[0]);
1156                string_append(&config->proxy_args,
1157                   "\"<br><br>\n");
1158                freez(cur_acl);
1159                continue;
1160             }
1161             if (vec_count == 2)
1162             {
1163                if (acl_addr(vec[1], cur_acl->dst) < 0)
1164                {
1165                   log_error(LOG_LEVEL_ERROR, "Invalid destination IP for "
1166                         "permit-access directive in configuration file: \"%s\"",
1167                         vec[0]);
1168                   string_append(&config->proxy_args,
1169                      "<br>\nWARNING: Invalid destination IP for permit-access directive"
1170                      " in configuration file: \"");
1171                   string_append(&config->proxy_args,
1172                      vec[0]);
1173                   string_append(&config->proxy_args,
1174                      "\"<br><br>\n");
1175                   freez(cur_acl);
1176                   continue;
1177                }
1178             }
1179
1180             /*
1181              * Add it to the list.  Note we reverse the list to get the
1182              * behaviour the user expects.  With both the ACL and
1183              * actions file, the last match wins.  However, the internal
1184              * implementations are different:  The actions file is stored
1185              * in the same order as the file, and scanned completely.
1186              * With the ACL, we reverse the order as we load it, then
1187              * when we scan it we stop as soon as we get a match.
1188              */
1189             cur_acl->next  = config->acl;
1190             config->acl = cur_acl;
1191
1192             continue;
1193 #endif /* def FEATURE_ACL */
1194
1195 /* *************************************************************************
1196  * proxy-info-url url
1197  * *************************************************************************/
1198          case hash_proxy_info_url :
1199             freez(config->proxy_info_url);
1200             config->proxy_info_url = strdup(arg);
1201             continue;
1202
1203 /* *************************************************************************
1204  * single-threaded
1205  * *************************************************************************/
1206          case hash_single_threaded :
1207             config->multi_threaded = 0;
1208             continue;
1209
1210 /* *************************************************************************
1211  * toggle (0|1)
1212  * *************************************************************************/
1213 #ifdef FEATURE_TOGGLE
1214          case hash_toggle :
1215             global_toggle_state = atoi(arg);
1216             continue;
1217 #endif /* def FEATURE_TOGGLE */
1218
1219 /* *************************************************************************
1220  * trust-info-url url
1221  * *************************************************************************/
1222 #ifdef FEATURE_TRUST
1223          case hash_trust_info_url :
1224             enlist(config->trust_info, arg);
1225             continue;
1226 #endif /* def FEATURE_TRUST */
1227
1228 /* *************************************************************************
1229  * trustfile filename
1230  * (In confdir by default.)
1231  * *************************************************************************/
1232 #ifdef FEATURE_TRUST
1233          case hash_trustfile :
1234             freez(config->trustfile);
1235             config->trustfile = make_path(config->confdir, arg);
1236             continue;
1237 #endif /* def FEATURE_TRUST */
1238
1239 /* *************************************************************************
1240  * usermanual url
1241  * *************************************************************************/
1242          case hash_usermanual :
1243             freez(config->usermanual);
1244             config->usermanual = strdup(arg);
1245             continue;
1246
1247 /* *************************************************************************
1248  * Win32 Console options:
1249  * *************************************************************************/
1250
1251 /* *************************************************************************
1252  * hide-console
1253  * *************************************************************************/
1254 #ifdef _WIN_CONSOLE
1255          case hash_hide_console :
1256             hideConsole = 1;
1257             continue;
1258 #endif /*def _WIN_CONSOLE*/
1259
1260
1261 /* *************************************************************************
1262  * Win32 GUI options:
1263  * *************************************************************************/
1264
1265 #if defined(_WIN32) && ! defined(_WIN_CONSOLE)
1266 /* *************************************************************************
1267  * activity-animation (0|1)
1268  * *************************************************************************/
1269          case hash_activity_animation :
1270             g_bShowActivityAnimation = atoi(arg);
1271             continue;
1272
1273 /* *************************************************************************
1274  *  close-button-minimizes (0|1)
1275  * *************************************************************************/
1276          case hash_close_button_minimizes :
1277             g_bCloseHidesWindow = atoi(arg);
1278             continue;
1279
1280 /* *************************************************************************
1281  * log-buffer-size (0|1)
1282  * *************************************************************************/
1283          case hash_log_buffer_size :
1284             g_bLimitBufferSize = atoi(arg);
1285             continue;
1286
1287 /* *************************************************************************
1288  * log-font-name fontnane
1289  * *************************************************************************/
1290          case hash_log_font_name :
1291             strcpy( g_szFontFaceName, arg );
1292             continue;
1293
1294 /* *************************************************************************
1295  * log-font-size n
1296  * *************************************************************************/
1297          case hash_log_font_size :
1298             g_nFontSize = atoi(arg);
1299             continue;
1300
1301 /* *************************************************************************
1302  * log-highlight-messages (0|1)
1303  * *************************************************************************/
1304          case hash_log_highlight_messages :
1305             g_bHighlightMessages = atoi(arg);
1306             continue;
1307
1308 /* *************************************************************************
1309  * log-max-lines n
1310  * *************************************************************************/
1311          case hash_log_max_lines :
1312             g_nMaxBufferLines = atoi(arg);
1313             continue;
1314
1315 /* *************************************************************************
1316  * log-messages (0|1)
1317  * *************************************************************************/
1318          case hash_log_messages :
1319             g_bLogMessages = atoi(arg);
1320             continue;
1321
1322 /* *************************************************************************
1323  * show-on-task-bar (0|1)
1324  * *************************************************************************/
1325          case hash_show_on_task_bar :
1326             g_bShowOnTaskBar = atoi(arg);
1327             continue;
1328
1329 #endif /* defined(_WIN32) && ! defined(_WIN_CONSOLE) */
1330
1331
1332 /* *************************************************************************
1333  * Warnings about unsupported features
1334  * *************************************************************************/
1335 #ifndef FEATURE_ACL
1336          case hash_deny_access:
1337 #endif /* ndef FEATURE_ACL */
1338 #ifndef FEATURE_CGI_EDIT_ACTIONS
1339          case hash_enable_edit_actions:
1340          case hash_enable_remote_toggle:
1341 #endif /* def FEATURE_CGI_EDIT_ACTIONS */
1342 #ifndef FEATURE_COOKIE_JAR
1343          case hash_jarfile :
1344 #endif /* ndef FEATURE_COOKIE_JAR */
1345 #ifndef FEATURE_ACL
1346          case hash_permit_access:
1347 #endif /* ndef FEATURE_ACL */
1348 #ifndef FEATURE_TOGGLE
1349          case hash_toggle :
1350 #endif /* ndef FEATURE_TOGGLE */
1351 #ifndef FEATURE_TRUST
1352          case hash_trustfile :
1353          case hash_trust_info_url :
1354 #endif /* ndef FEATURE_TRUST */
1355
1356 #ifndef _WIN_CONSOLE
1357          case hash_hide_console :
1358 #endif /* ndef _WIN_CONSOLE */
1359
1360 #if defined(_WIN_CONSOLE) || ! defined(_WIN32)
1361          case hash_activity_animation :
1362          case hash_close_button_minimizes :
1363          case hash_log_buffer_size :
1364          case hash_log_font_name :
1365          case hash_log_font_size :
1366          case hash_log_highlight_messages :
1367          case hash_log_max_lines :
1368          case hash_log_messages :
1369          case hash_show_on_task_bar :
1370 #endif /* defined(_WIN_CONSOLE) || ! defined(_WIN32) */
1371             /* These warnings are annoying - so hide them. -- Jon */
1372             /* log_error(LOG_LEVEL_INFO, "Unsupported directive \"%s\" ignored.", cmd); */
1373             continue;
1374
1375 /* *************************************************************************/
1376          default :
1377 /* *************************************************************************/
1378             /*
1379              * I decided that I liked this better as a warning than an
1380              * error.  To change back to an error, just change log level
1381              * to LOG_LEVEL_FATAL.
1382              */
1383             log_error(LOG_LEVEL_ERROR, "Ignoring unrecognized directive '%s' (%luul) in line %lu "
1384                   "in configuration file (%s).",  buf, hash_string(cmd), linenum, configfile);
1385             string_append(&config->proxy_args,
1386                " <b><font color=\"red\">WARNING: unrecognized directive, ignored</font></b>");
1387             continue;
1388
1389 /* *************************************************************************/
1390       } /* end switch( hash_string(cmd) ) */
1391    } /* end while ( read_config_line(...) ) */
1392
1393    fclose(configfp);
1394
1395    if (NULL == config->proxy_args)
1396    {
1397       log_error(LOG_LEVEL_FATAL, "Out of memory loading config - insufficient memory for config->proxy_args");
1398    }
1399
1400    init_error_log(Argv[0], config->logfile, config->debug);
1401
1402    if (config->actions_file[0])
1403    {
1404       add_loader(load_actions_file, config);
1405    }
1406
1407    if (config->re_filterfile)
1408    {
1409       add_loader(load_re_filterfile, config);
1410    }
1411
1412 #ifdef FEATURE_TRUST
1413    if (config->trustfile)
1414    {
1415       add_loader(load_trustfile, config);
1416    }
1417 #endif /* def FEATURE_TRUST */
1418
1419 #ifdef FEATURE_COOKIE_JAR
1420    if ( NULL != config->jarfile )
1421    {
1422       if ( NULL == (config->jar = fopen(config->jarfile, "a")) )
1423       {
1424          log_error(LOG_LEVEL_FATAL, "can't open jarfile '%s': %E", config->jarfile);
1425          /* Never get here - LOG_LEVEL_FATAL causes program exit */
1426       }
1427       setbuf(config->jar, NULL);
1428    }
1429 #endif /* def FEATURE_COOKIE_JAR */
1430
1431    if ( NULL == config->haddr )
1432    {
1433       config->haddr = strdup( HADDR_DEFAULT );
1434    }
1435
1436    if ( NULL != config->haddr )
1437    {
1438       if (NULL != (p = strchr(config->haddr, ':')))
1439       {
1440          *p++ = '\0';
1441          if (*p)
1442          {
1443             config->hport = atoi(p);
1444          }
1445       }
1446
1447       if (config->hport <= 0)
1448       {
1449          *--p = ':';
1450          log_error(LOG_LEVEL_FATAL, "invalid bind port spec %s", config->haddr);
1451          /* Never get here - LOG_LEVEL_FATAL causes program exit */
1452       }
1453       if (*config->haddr == '\0')
1454       {
1455          config->haddr = NULL;
1456       }
1457    }
1458
1459    /*
1460     * Want to run all the loaders once now.
1461     *
1462     * Need to set up a fake csp, so they can get to the config.
1463     */
1464    fake_csp = (struct client_state *) zalloc (sizeof(*fake_csp));
1465    fake_csp->config = config;
1466
1467    if (run_loader(fake_csp))
1468    {
1469       freez(fake_csp);
1470       log_error(LOG_LEVEL_FATAL, "A loader failed while loading config file. Exiting.");
1471       /* Never get here - LOG_LEVEL_FATAL causes program exit */
1472    }
1473    freez(fake_csp);
1474
1475 /* FIXME: this is a kludge for win32 */
1476 #if defined(_WIN32) && !defined (_WIN_CONSOLE)
1477
1478    g_default_actions_file  = config->actions_file[1]; /* FIXME Hope this is default.action */
1479    g_user_actions_file = config->actions_file[2]; /* FIXME Hope this is user.action */
1480    g_re_filterfile    = config->re_filterfile;
1481
1482 #ifdef FEATURE_TRUST
1483    g_trustfile        = config->trustfile;
1484 #endif /* def FEATURE_TRUST */
1485
1486
1487 #endif /* defined(_WIN32) && !defined (_WIN_CONSOLE) */
1488 /* FIXME: end kludge */
1489
1490
1491    config->need_bind = 1;
1492
1493    if (current_configfile)
1494    {
1495       struct configuration_spec * oldcfg = (struct configuration_spec *)
1496                                            current_configfile->f;
1497       /*
1498        * Check if config->haddr,hport == oldcfg->haddr,hport
1499        *
1500        * The following could be written more compactly as a single,
1501        * (unreadably long) if statement.
1502        */
1503       config->need_bind = 0;
1504       if (config->hport != oldcfg->hport)
1505       {
1506          config->need_bind = 1;
1507       }
1508       else if (config->haddr == NULL)
1509       {
1510          if (oldcfg->haddr != NULL)
1511          {
1512             config->need_bind = 1;
1513          }
1514       }
1515       else if (oldcfg->haddr == NULL)
1516       {
1517          config->need_bind = 1;
1518       }
1519       else if (0 != strcmp(config->haddr, oldcfg->haddr))
1520       {
1521          config->need_bind = 1;
1522       }
1523
1524       current_configfile->unloader = unload_configfile;
1525    }
1526
1527    fs->next = files->next;
1528    files->next = fs;
1529
1530    current_configfile = fs;
1531
1532    return (config);
1533 }
1534
1535
1536 /*********************************************************************
1537  *
1538  * Function    :  savearg
1539  *
1540  * Description :  Called from `load_config'.  It saves each non-empty
1541  *                and non-comment line from config into
1542  *                config->proxy_args.  This is used to create the
1543  *                show-proxy-args page.  On error, frees
1544  *                config->proxy_args and sets it to NULL
1545  *
1546  * Parameters  :
1547  *          1  :  command = config setting that was found
1548  *          2  :  argument = the setting's argument (if any)
1549  *          3  :  config = Configuration to save into.
1550  *
1551  * Returns     :  N/A
1552  *
1553  *********************************************************************/
1554 static void savearg(char *command, char *argument, struct configuration_spec * config)
1555 {
1556    char * buf;
1557    char * s;
1558
1559    assert(command);
1560    assert(*command);
1561    assert(argument);
1562
1563    /*
1564     * Add config option name embedded in
1565     * link to it's section in the user-manual
1566     */
1567    buf = strdup("\n<br><a href=\"");
1568    string_append(&buf, config->usermanual);
1569    string_append(&buf, CONFIG_HELP_PREFIX);
1570    string_join  (&buf, string_toupper(command));
1571    string_append(&buf, "\">");
1572    string_append(&buf, command);
1573    string_append(&buf, "</a> ");
1574
1575    if (NULL == buf)
1576    {
1577       freez(config->proxy_args);
1578       return;
1579    }
1580
1581    if ( (NULL != argument) && ('\0' != *argument) )
1582    {
1583       s = html_encode(argument);
1584       if (NULL == s)
1585       {
1586          freez(buf);
1587          freez(config->proxy_args);
1588          return;
1589       }
1590
1591       if (strncmpic(argument, "http://", 7) == 0)
1592       {
1593          string_append(&buf, "<a href=\"");
1594          string_append(&buf, s);
1595          string_append(&buf, "\">");
1596          string_join  (&buf, s);
1597          string_append(&buf, "</a>");
1598       }
1599       else
1600       {
1601          string_join  (&buf, s);
1602       }
1603    }
1604
1605    string_join(&config->proxy_args, buf);
1606 }
1607
1608
1609 /*
1610   Local Variables:
1611   tab-width: 3
1612   end:
1613 */