Add #95: Support a non-standard client header in CONNECT requests that contains the...
[privoxy.git] / loadcfg.c
index 6f39e17..235281b 100644 (file)
--- a/loadcfg.c
+++ b/loadcfg.c
@@ -1,4 +1,4 @@
-const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.113 2011/07/08 13:27:31 fabiankeil Exp $";
+const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.117 2011/07/08 13:30:08 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/loadcfg.c,v $
@@ -140,6 +140,7 @@ static struct file_list *current_configfile = NULL;
 #define hash_default_server_timeout      2530089913ul /* "default-server-timeout" */
 #define hash_deny_access                 1227333715ul /* "deny-access" */
 #define hash_enable_edit_actions         2517097536ul /* "enable-edit-actions" */
+#define hash_enable_compression          3943696946ul /* "enable-compression" */
 #define hash_enable_remote_toggle        2979744683ul /* "enable-remote-toggle" */
 #define hash_enable_remote_http_toggle    110543988ul /* "enable-remote-http-toggle" */
 #define hash_enforce_blocks              1862427469ul /* "enforce-blocks" */
@@ -228,7 +229,10 @@ static void unload_configfile (void * data)
    freez(config->templdir);
    freez(config->hostname);
 
-   freez(config->haddr);
+   for (i = 0; i < MAX_LISTENING_SOCKETS; i++)
+   {
+      freez(config->haddr[i]);
+   }
    freez(config->logfile);
 
    for (i = 0; i < MAX_AF_FILES; i++)
@@ -297,6 +301,7 @@ static int parse_toggle_state(const char *name, const char *value)
 {
    int toggle_state;
    assert(name != NULL);
+   assert(value != NULL);
 
    if ((value == NULL) || (*value == '\0'))
    {
@@ -305,7 +310,11 @@ static int parse_toggle_state(const char *name, const char *value)
 
    toggle_state = atoi(value);
 
-   if ((toggle_state != 0) && (toggle_state != 1))
+   /*
+    * Also check the length as atoi() doesn't mind
+    * garbage after a valid integer, but we do.
+    */
+   if (((toggle_state != 0) && (toggle_state != 1)) || (strlen(value) != 1))
    {
       log_error(LOG_LEVEL_FATAL,
          "Directive %s used with invalid argument '%s'. Use either '0' or '1'.",
@@ -406,6 +415,7 @@ struct configuration_spec * load_config(void)
    config->feature_flags            &= ~RUNTIME_FEATURE_ACCEPT_INTERCEPTED_REQUESTS;
    config->feature_flags            &= ~RUNTIME_FEATURE_EMPTY_DOC_RETURNS_OK;
 #ifdef FEATURE_COMPRESSION
+   config->feature_flags            &= ~RUNTIME_FEATURE_COMPRESSION;
    /*
     * XXX: Run some benchmarks to see if there are better default values.
     */
@@ -500,7 +510,7 @@ struct configuration_spec * load_config(void)
  * accept-intercepted-requests
  * *************************************************************************/
          case hash_accept_intercepted_requests:
-            if (0 != parse_toggle_state(cmd, arg))
+            if (parse_toggle_state(cmd, arg) == 1)
             {
                config->feature_flags |= RUNTIME_FEATURE_ACCEPT_INTERCEPTED_REQUESTS;
             }
@@ -522,7 +532,7 @@ struct configuration_spec * load_config(void)
  * allow-cgi-request-crunching
  * *************************************************************************/
          case hash_allow_cgi_request_crunching:
-            if (0 != parse_toggle_state(cmd, arg))
+            if (parse_toggle_state(cmd, arg) == 1)
             {
                config->feature_flags |= RUNTIME_FEATURE_CGI_CRUNCHING;
             }
@@ -578,7 +588,7 @@ struct configuration_spec * load_config(void)
  * *************************************************************************/
 #ifdef FEATURE_CONNECTION_SHARING
          case hash_connection_sharing :
-            if (0 != parse_toggle_state(cmd, arg))
+            if (parse_toggle_state(cmd, arg) == 1)
             {
                config->feature_flags |= RUNTIME_FEATURE_CONNECTION_SHARING;
             }
@@ -705,7 +715,7 @@ struct configuration_spec * load_config(void)
  * *************************************************************************/
 #ifdef FEATURE_CGI_EDIT_ACTIONS
          case hash_enable_edit_actions:
-            if (0 != parse_toggle_state(cmd, arg))
+            if (parse_toggle_state(cmd, arg) == 1)
             {
                config->feature_flags |= RUNTIME_FEATURE_CGI_EDIT_ACTIONS;
             }
@@ -716,12 +726,29 @@ struct configuration_spec * load_config(void)
             break;
 #endif /* def FEATURE_CGI_EDIT_ACTIONS */
 
+/* *************************************************************************
+ * enable-compression 0|1
+ * *************************************************************************/
+#ifdef FEATURE_COMPRESSION
+         case hash_enable_compression:
+            if (parse_toggle_state(cmd, arg) == 1)
+            {
+               config->feature_flags |= RUNTIME_FEATURE_COMPRESSION;
+            }
+            else
+            {
+               config->feature_flags &= ~RUNTIME_FEATURE_COMPRESSION;
+            }
+            break;
+#endif /* def FEATURE_COMPRESSION */
+
+
 /* *************************************************************************
  * enable-remote-toggle 0|1
  * *************************************************************************/
 #ifdef FEATURE_TOGGLE
          case hash_enable_remote_toggle:
-            if (0 != parse_toggle_state(cmd, arg))
+            if (parse_toggle_state(cmd, arg) == 1)
             {
                config->feature_flags |= RUNTIME_FEATURE_CGI_TOGGLE;
             }
@@ -736,7 +763,7 @@ struct configuration_spec * load_config(void)
  * enable-remote-http-toggle 0|1
  * *************************************************************************/
          case hash_enable_remote_http_toggle:
-            if (0 != parse_toggle_state(cmd, arg))
+            if (parse_toggle_state(cmd, arg) == 1)
             {
                config->feature_flags |= RUNTIME_FEATURE_HTTP_TOGGLE;
             }
@@ -751,7 +778,7 @@ struct configuration_spec * load_config(void)
  * *************************************************************************/
          case hash_enforce_blocks:
 #ifdef FEATURE_FORCE_LOAD
-            if (0 != parse_toggle_state(cmd, arg))
+            if (parse_toggle_state(cmd, arg) == 1)
             {
                config->feature_flags |= RUNTIME_FEATURE_ENFORCE_BLOCKS;
             }
@@ -995,7 +1022,7 @@ struct configuration_spec * load_config(void)
  *   to the browser for blocked pages.
  ***************************************************************************/
          case hash_handle_as_empty_returns_ok:
-            if (0 != parse_toggle_state(cmd, arg))
+            if (parse_toggle_state(cmd, arg) == 1)
             {
                config->feature_flags |= RUNTIME_FEATURE_EMPTY_DOC_RETURNS_OK;
             }
@@ -1042,8 +1069,23 @@ struct configuration_spec * load_config(void)
  * listen-address [ip][:port]
  * *************************************************************************/
          case hash_listen_address :
-            freez(config->haddr);
-            config->haddr = strdup(arg);
+            i = 0;
+            while ((i < MAX_LISTENING_SOCKETS) && (NULL != config->haddr[i]))
+            {
+               i++;
+            }
+
+            if (i >= MAX_LISTENING_SOCKETS)
+            {
+               log_error(LOG_LEVEL_FATAL, "Too many 'listen-address' directives in config file - limit is %d.\n"
+                  "(You can increase this limit by changing MAX_LISTENING_SOCKETS in project.h and recompiling).",
+                  MAX_LISTENING_SOCKETS);
+            }
+            config->haddr[i] = strdup(arg);
+            if (NULL == config->haddr[i])
+            {
+               log_error(LOG_LEVEL_FATAL, "Out of memory while copying listening address");
+            }
             break;
 
 /* *************************************************************************
@@ -1204,7 +1246,7 @@ struct configuration_spec * load_config(void)
  * split-large-cgi-forms
  * *************************************************************************/
          case hash_split_large_cgi_forms :
-            if (0 != parse_toggle_state(cmd, arg))
+            if (parse_toggle_state(cmd, arg) == 1)
             {
                config->feature_flags |= RUNTIME_FEATURE_SPLIT_LARGE_FORMS;
             }
@@ -1500,39 +1542,45 @@ struct configuration_spec * load_config(void)
    }
 #endif /* def FEATURE_TRUST */
 
-   if ( NULL == config->haddr )
+   if ( NULL == config->haddr[0] )
    {
-      config->haddr = strdup( HADDR_DEFAULT );
+      config->haddr[0] = strdup( HADDR_DEFAULT );
+      if (NULL == config->haddr[0])
+      {
+         log_error(LOG_LEVEL_FATAL, "Out of memory while copying default listening address");
+      }
    }
 
-   if ( NULL != config->haddr )
+   for (i = 0; i < MAX_LISTENING_SOCKETS && NULL != config->haddr[i]; i++)
    {
-      if ((*config->haddr == '[')
-         && (NULL != (p = strchr(config->haddr, ']')))
+      if ((*config->haddr[i] == '[')
+         && (NULL != (p = strchr(config->haddr[i], ']')))
          && (p[1] == ':')
-         && (0 < (config->hport = atoi(p + 2))))
+         && (0 < (config->hport[i] = atoi(p + 2))))
       {
          *p = '\0';
-         memmove((void *)config->haddr, config->haddr + 1,
-            (size_t)(p - config->haddr));
+         memmove((void *)config->haddr[i], config->haddr[i] + 1,
+            (size_t)(p - config->haddr[i]));
       }
-      else if (NULL != (p = strchr(config->haddr, ':'))
-         && (0 < (config->hport = atoi(p + 1))))
+      else if (NULL != (p = strchr(config->haddr[i], ':'))
+         && (0 < (config->hport[i] = atoi(p + 1))))
       {
          *p = '\0';
       }
       else
       {
-         log_error(LOG_LEVEL_FATAL, "invalid bind port spec %s", config->haddr);
+         log_error(LOG_LEVEL_FATAL, "invalid bind port spec %s", config->haddr[i]);
          /* Never get here - LOG_LEVEL_FATAL causes program exit */
       }
-      if (*config->haddr == '\0')
+      if (*config->haddr[i] == '\0')
       {
          /*
-          * Only the port specified. We stored it in config->hport
+          * Only the port specified. We stored it in config->hport[i]
           * and don't need its text representation anymore.
+          * Use config->hport[i] == 0 to iterate listening addresses since
+          * now.
           */
-         freez(config->haddr);
+         freez(config->haddr[i]);
       }
    }
 
@@ -1576,30 +1624,34 @@ struct configuration_spec * load_config(void)
       struct configuration_spec * oldcfg = (struct configuration_spec *)
                                            current_configfile->f;
       /*
-       * Check if config->haddr,hport == oldcfg->haddr,hport
+       * Check if config->haddr[i],hport[i] == oldcfg->haddr[i],hport[i]
        *
        * The following could be written more compactly as a single,
        * (unreadably long) if statement.
        */
       config->need_bind = 0;
-      if (config->hport != oldcfg->hport)
-      {
-         config->need_bind = 1;
-      }
-      else if (config->haddr == NULL)
+
+      for (i = 0; i < MAX_LISTENING_SOCKETS; i++)
       {
-         if (oldcfg->haddr != NULL)
+         if (config->hport[i] != oldcfg->hport[i])
+         {
+            config->need_bind = 1;
+         }
+         else if (config->haddr[i] == NULL)
+         {
+            if (oldcfg->haddr[i] != NULL)
+            {
+               config->need_bind = 1;
+            }
+         }
+         else if (oldcfg->haddr[i] == NULL)
+         {
+            config->need_bind = 1;
+         }
+         else if (0 != strcmp(config->haddr[i], oldcfg->haddr[i]))
          {
             config->need_bind = 1;
          }
-      }
-      else if (oldcfg->haddr == NULL)
-      {
-         config->need_bind = 1;
-      }
-      else if (0 != strcmp(config->haddr, oldcfg->haddr))
-      {
-         config->need_bind = 1;
       }
 
       current_configfile->unloader = unload_configfile;