+ }
+#ifdef HAVE_RFC2553
+ else
+ {
+ cur_acl->wildcard_dst = 1;
+ }
+#endif /* def HAVE_RFC2553 */
+
+ /*
+ * Add it to the list. Note we reverse the list to get the
+ * behaviour the user expects. With both the ACL and
+ * actions file, the last match wins. However, the internal
+ * implementations are different: The actions file is stored
+ * in the same order as the file, and scanned completely.
+ * With the ACL, we reverse the order as we load it, then
+ * when we scan it we stop as soon as we get a match.
+ */
+ cur_acl->next = config->acl;
+ config->acl = cur_acl;
+
+ break;
+#endif /* def FEATURE_ACL */
+
+#if defined(FEATURE_ACCEPT_FILTER) && defined(SO_ACCEPTFILTER)
+/* *************************************************************************
+ * enable-accept-filter 0|1
+ * *************************************************************************/
+ case hash_enable_accept_filter :
+ config->enable_accept_filter = parse_toggle_state(cmd, arg);
+ break;
+#endif /* defined(FEATURE_ACCEPT_FILTER) && defined(SO_ACCEPTFILTER) */
+
+/* *************************************************************************
+ * enable-edit-actions 0|1
+ * *************************************************************************/
+#ifdef FEATURE_CGI_EDIT_ACTIONS
+ case hash_enable_edit_actions:
+ if (parse_toggle_state(cmd, arg) == 1)
+ {
+ config->feature_flags |= RUNTIME_FEATURE_CGI_EDIT_ACTIONS;
+ }
+ else
+ {
+ config->feature_flags &= ~RUNTIME_FEATURE_CGI_EDIT_ACTIONS;
+ }
+ 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-proxy-authentication-forwarding 0|1
+ * *************************************************************************/
+ case hash_enable_proxy_authentication_forwarding:
+ if (parse_toggle_state(cmd, arg) == 1)
+ {
+ config->feature_flags |= RUNTIME_FEATURE_FORWARD_PROXY_AUTHENTICATION_HEADERS;
+ }
+ else
+ {
+ config->feature_flags &= ~RUNTIME_FEATURE_FORWARD_PROXY_AUTHENTICATION_HEADERS;
+ }
+ break;
+
+/* *************************************************************************
+ * enable-remote-toggle 0|1
+ * *************************************************************************/
+#ifdef FEATURE_TOGGLE
+ case hash_enable_remote_toggle:
+ if (parse_toggle_state(cmd, arg) == 1)
+ {
+ config->feature_flags |= RUNTIME_FEATURE_CGI_TOGGLE;
+ }
+ else
+ {
+ config->feature_flags &= ~RUNTIME_FEATURE_CGI_TOGGLE;
+ }
+ break;
+#endif /* def FEATURE_TOGGLE */
+
+/* *************************************************************************
+ * enable-remote-http-toggle 0|1
+ * *************************************************************************/
+ case hash_enable_remote_http_toggle:
+ if (parse_toggle_state(cmd, arg) == 1)
+ {
+ config->feature_flags |= RUNTIME_FEATURE_HTTP_TOGGLE;
+ }
+ else
+ {
+ config->feature_flags &= ~RUNTIME_FEATURE_HTTP_TOGGLE;
+ }
+ break;
+
+/* *************************************************************************
+ * enforce-blocks 0|1
+ * *************************************************************************/
+ case hash_enforce_blocks:
+#ifdef FEATURE_FORCE_LOAD
+ if (parse_toggle_state(cmd, arg) == 1)
+ {
+ config->feature_flags |= RUNTIME_FEATURE_ENFORCE_BLOCKS;
+ }
+ else
+ {
+ config->feature_flags &= ~RUNTIME_FEATURE_ENFORCE_BLOCKS;
+ }
+#else
+ log_error(LOG_LEVEL_ERROR, "Ignoring directive 'enforce-blocks'. "
+ "FEATURE_FORCE_LOAD is disabled, blocks will always be enforced.");
+#endif /* def FEATURE_FORCE_LOAD */
+ break;
+
+/* *************************************************************************
+ * filterfile file-name
+ * In confdir by default.
+ * *************************************************************************/
+ case hash_filterfile :
+ i = 0;
+ while ((i < MAX_AF_FILES) && (NULL != config->re_filterfile[i]))
+ {
+ i++;
+ }
+
+ if (i >= MAX_AF_FILES)
+ {
+ log_error(LOG_LEVEL_FATAL, "Too many 'filterfile' directives in config file - limit is %d.\n"
+ "(You can increase this limit by changing MAX_AF_FILES in project.h and recompiling).",
+ MAX_AF_FILES);
+ }
+ config->re_filterfile_short[i] = strdup_or_die(arg);
+ config->re_filterfile[i] = make_path(config->confdir, arg);
+
+ break;
+
+/* *************************************************************************
+ * forward url-pattern (.|http-proxy-host[:port])
+ * *************************************************************************/
+ case hash_forward:
+ strlcpy(tmp, arg, sizeof(tmp));
+ vec_count = ssplit(tmp, " \t", vec, SZ(vec));
+
+ if (vec_count != 2)
+ {
+ log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for forward "
+ "directive in configuration file.");
+ string_append(&config->proxy_args,
+ "<br>\nWARNING: Wrong number of parameters for "
+ "forward directive in configuration file.");
+ break;
+ }
+
+ /* allocate a new node */
+ cur_fwd = zalloc_or_die(sizeof(*cur_fwd));
+ cur_fwd->type = SOCKS_NONE;
+
+ /* Save the URL pattern */
+ if (create_pattern_spec(cur_fwd->url, vec[0]))
+ {
+ log_error(LOG_LEVEL_ERROR, "Bad URL specifier for forward "
+ "directive in configuration file.");
+ string_append(&config->proxy_args,
+ "<br>\nWARNING: Bad URL specifier for "
+ "forward directive in configuration file.");
+ freez(cur_fwd);
+ break;
+ }
+
+ /* Parse the parent HTTP proxy host:port */
+ p = vec[1];
+
+ if (strcmp(p, ".") != 0)
+ {
+ cur_fwd->forward_port = 8000;
+ parse_forwarder_address(p, &cur_fwd->forward_host,
+ &cur_fwd->forward_port);
+ }
+
+ /* Add to list. */
+ cur_fwd->next = config->forward;
+ config->forward = cur_fwd;
+
+ break;
+
+/* *************************************************************************
+ * forward-socks4 url-pattern socks-proxy[:port] (.|http-proxy[:port])
+ * *************************************************************************/
+ case hash_forward_socks4:
+ strlcpy(tmp, arg, sizeof(tmp));
+ vec_count = ssplit(tmp, " \t", vec, SZ(vec));
+
+ if (vec_count != 3)
+ {
+ log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for "
+ "forward-socks4 directive in configuration file.");
+ string_append(&config->proxy_args,
+ "<br>\nWARNING: Wrong number of parameters for "
+ "forward-socks4 directive in configuration file.");
+ break;
+ }
+
+ /* allocate a new node */
+ cur_fwd = zalloc_or_die(sizeof(*cur_fwd));
+ cur_fwd->type = SOCKS_4;
+
+ /* Save the URL pattern */
+ if (create_pattern_spec(cur_fwd->url, vec[0]))
+ {
+ log_error(LOG_LEVEL_ERROR, "Bad URL specifier for forward-socks4 "
+ "directive in configuration file.");
+ string_append(&config->proxy_args,
+ "<br>\nWARNING: Bad URL specifier for "
+ "forward-socks4 directive in configuration file.");
+ freez(cur_fwd);
+ break;
+ }
+
+ /* Parse the SOCKS proxy host[:port] */
+ p = vec[1];
+
+ /* XXX: This check looks like a bug. */
+ if (strcmp(p, ".") != 0)
+ {
+ cur_fwd->gateway_port = 1080;
+ parse_forwarder_address(p, &cur_fwd->gateway_host,
+ &cur_fwd->gateway_port);
+ }
+
+ /* Parse the parent HTTP proxy host[:port] */
+ p = vec[2];
+
+ if (strcmp(p, ".") != 0)
+ {
+ cur_fwd->forward_port = 8000;
+ parse_forwarder_address(p, &cur_fwd->forward_host,
+ &cur_fwd->forward_port);
+ }
+
+ /* Add to list. */
+ cur_fwd->next = config->forward;
+ config->forward = cur_fwd;
+
+ break;
+
+/* *************************************************************************
+ * forward-socks4a url-pattern socks-proxy[:port] (.|http-proxy[:port])
+ * *************************************************************************/
+ case hash_forward_socks4a:
+ case hash_forward_socks5:
+ case hash_forward_socks5t:
+ strlcpy(tmp, arg, sizeof(tmp));
+ vec_count = ssplit(tmp, " \t", vec, SZ(vec));
+
+ if (vec_count != 3)
+ {
+ log_error(LOG_LEVEL_ERROR,
+ "Wrong number of parameters for %s in configuration file.",
+ cmd);
+ string_append(&config->proxy_args,
+ "<br>\nWARNING: Wrong number of parameters for ");
+ string_append(&config->proxy_args, cmd);
+ string_append(&config->proxy_args,
+ "directive in configuration file.");
+ break;
+ }
+
+ /* allocate a new node */
+ cur_fwd = zalloc_or_die(sizeof(*cur_fwd));
+
+ if (directive_hash == hash_forward_socks4a)
+ {
+ cur_fwd->type = SOCKS_4A;
+ }
+ else if (directive_hash == hash_forward_socks5)
+ {
+ cur_fwd->type = SOCKS_5;
+ }
+ else
+ {
+ assert(directive_hash == hash_forward_socks5t);
+ cur_fwd->type = SOCKS_5T;
+ }
+
+ /* Save the URL pattern */
+ if (create_pattern_spec(cur_fwd->url, vec[0]))
+ {
+ log_error(LOG_LEVEL_ERROR,
+ "Bad URL specifier for %s in configuration file.",
+ cmd);
+ string_append(&config->proxy_args,
+ "<br>\nWARNING: Bad URL specifier for ");
+ string_append(&config->proxy_args, cmd);
+ string_append(&config->proxy_args,
+ "directive in configuration file.");
+ freez(cur_fwd);
+ break;
+ }
+
+ /* Parse the SOCKS proxy host[:port] */
+ p = vec[1];
+
+ cur_fwd->gateway_port = 1080;
+ parse_forwarder_address(p, &cur_fwd->gateway_host,
+ &cur_fwd->gateway_port);
+
+ /* Parse the parent HTTP proxy host[:port] */
+ p = vec[2];
+
+ if (strcmp(p, ".") != 0)
+ {
+ cur_fwd->forward_port = 8000;
+ parse_forwarder_address(p, &cur_fwd->forward_host,
+ &cur_fwd->forward_port);
+ }
+
+ /* Add to list. */
+ cur_fwd->next = config->forward;
+ config->forward = cur_fwd;
+
+ break;
+
+/* *************************************************************************
+ * forwarded-connect-retries n
+ * *************************************************************************/
+ case hash_forwarded_connect_retries :
+ config->forwarded_connect_retries = parse_numeric_value(cmd, arg);
+ break;
+
+/* *************************************************************************
+ * handle-as-empty-doc-returns-ok 0|1
+ *
+ * Workaround for firefox hanging on blocked javascript pages.
+ * Block with the "+handle-as-empty-document" flag and set the
+ * "handle-as-empty-doc-returns-ok" run-time config flag so that
+ * Privoxy returns a 200/OK status instead of a 403/Forbidden status
+ * to the browser for blocked pages.
+ ***************************************************************************/
+ case hash_handle_as_empty_returns_ok:
+ if (parse_toggle_state(cmd, arg) == 1)
+ {
+ config->feature_flags |= RUNTIME_FEATURE_EMPTY_DOC_RETURNS_OK;
+ }
+ else
+ {
+ config->feature_flags &= ~RUNTIME_FEATURE_EMPTY_DOC_RETURNS_OK;
+ }
+ break;
+
+/* *************************************************************************
+ * hostname hostname-to-show-on-cgi-pages
+ * *************************************************************************/
+ case hash_hostname :
+ freez(config->hostname);
+ config->hostname = strdup_or_die(arg);
+ break;
+
+/* *************************************************************************
+ * keep-alive-timeout timeout
+ * *************************************************************************/
+#ifdef FEATURE_CONNECTION_KEEP_ALIVE
+ case hash_keep_alive_timeout :
+ {
+ int timeout = parse_numeric_value(cmd, arg);
+ if (0 < timeout)
+ {
+ config->feature_flags |= RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE;
+ config->keep_alive_timeout = (unsigned int)timeout;
+ }
+ else
+ {
+ config->feature_flags &= ~RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE;
+ }
+ break;
+ }
+#endif
+
+/* *************************************************************************
+ * listen-address [ip][:port]
+ * *************************************************************************/
+ case hash_listen_address :
+ 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_or_die(arg);
+ break;
+
+/* *************************************************************************
+ * listen-backlog n
+ * *************************************************************************/
+ case hash_listen_backlog :
+ /*
+ * We don't enfore an upper or lower limit because on
+ * many platforms all values are valid and negative
+ * number mean "use the highest value allowed".
+ */
+ config->listen_backlog = parse_numeric_value(cmd, arg);
+ break;
+
+/* *************************************************************************
+ * logdir directory-name
+ * *************************************************************************/
+ case hash_logdir :
+ freez(config->logdir);
+ config->logdir = make_path(NULL, arg);
+ break;
+
+/* *************************************************************************
+ * logfile log-file-name
+ * In logdir by default
+ * *************************************************************************/
+ case hash_logfile :
+ if (daemon_mode)
+ {
+ logfile = make_path(config->logdir, arg);
+ if (NULL == logfile)