From: Fabian Keil <fk@fabiankeil.de>
Date: Wed, 21 Aug 2019 17:14:43 +0000 (+0000)
Subject: Add "Cross-origin resource sharing" (CORS) support
X-Git-Tag: v_3_0_30~310
X-Git-Url: http://www.privoxy.org/gitweb/%22data:application/user-manual/static/@default-cgi@toggle?a=commitdiff_plain;h=9fd58c0d;p=privoxy.git

Add "Cross-origin resource sharing" (CORS) support

This allows to access Privoxy's CGI interface via
JavaScript from another domain (white-listed with
the new cors-allowed-origin directive).

Based on a patch by Nedžad Hrnjica.
Sponsored by: Robert Klemme.
---

diff --git a/cgi.c b/cgi.c
index 22601760..c67aed4b 100644
--- a/cgi.c
+++ b/cgi.c
@@ -1585,6 +1585,18 @@ struct http_response *finish_http_response(struct client_state *csp, struct http
       return rsp;
    }
 
+   /*
+    * Add "Cross-origin resource sharing" (CORS) headers if enabled
+    */
+   if (NULL != csp->config->cors_allowed_origin)
+   {
+      enlist_unique_header(rsp->headers, "Access-Control-Allow-Origin",
+         strdup_or_die(csp->config->cors_allowed_origin));
+      enlist_unique_header(rsp->headers, "Access-Control-Allow-Methods", "GET,POST");
+      enlist_unique_header(rsp->headers, "Access-Control-Allow-Headers", "X-Requested-With");
+      enlist_unique_header(rsp->headers, "Access-Control-Max-Age", "86400");
+   }
+
    /*
     * Fill in the HTTP Status, using HTTP/1.1
     * unless the client asked for HTTP/1.0.
diff --git a/loadcfg.c b/loadcfg.c
index eac9206a..88379eb5 100644
--- a/loadcfg.c
+++ b/loadcfg.c
@@ -141,6 +141,7 @@ static struct file_list *current_configfile = NULL;
 #define hash_compression_level           2464423563U /* "compression-level" */
 #define hash_confdir                        1978389U /* "confdir" */
 #define hash_connection_sharing          1348841265U /* "connection-sharing" */
+#define hash_cors_allowed_origin         2769345637U /* "cors-allowed-origin" */
 #define hash_debug                            78263U /* "debug" */
 #define hash_default_server_timeout      2530089913U /* "default-server-timeout" */
 #define hash_deny_access                 1227333715U /* "deny-access" */
@@ -647,6 +648,7 @@ struct configuration_spec * load_config(void)
    config->compression_level         = 1;
 #endif
    config->feature_flags            &= ~RUNTIME_FEATURE_TOLERATE_PIPELINING;
+   config->cors_allowed_origin       = NULL;
 
    configfp = fopen(configfile, "r");
    if (NULL == configfp)
@@ -881,6 +883,18 @@ struct configuration_spec * load_config(void)
             break;
 #endif
 
+/* *************************************************************************
+ * cors-allowed-origin http://www.example.org
+ * *************************************************************************/
+         case hash_cors_allowed_origin :
+            /*
+             * We don't validate the specified referrer as
+             * it's only used for string comparison.
+             */
+            freez(config->cors_allowed_origin);
+            config->cors_allowed_origin = strdup_or_die(arg);
+            break;
+
 /* *************************************************************************
  * debug n
  * Specifies debug level, multiple values are ORed together.
diff --git a/project.h b/project.h
index 779c5c71..78d53ce3 100644
--- a/project.h
+++ b/project.h
@@ -1303,6 +1303,9 @@ struct configuration_spec
    /** The directory for customized CGI templates. */
    const char *templdir;
 
+   /** "Cross-origin resource sharing" (CORS) allowed origin */
+   const char *cors_allowed_origin;
+
 #ifdef FEATURE_EXTERNAL_FILTERS
    /** The template used to create temporary files. */
    const char *temporary_directory;