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