Set version to 3.0.9.
[privoxy.git] / cgi.c
diff --git a/cgi.c b/cgi.c
index c8b6b00..bd0c8f6 100644 (file)
--- a/cgi.c
+++ b/cgi.c
@@ -1,4 +1,4 @@
-const char cgi_rcs[] = "$Id: cgi.c,v 1.96 2007/03/08 17:41:05 fabiankeil Exp $";
+const char cgi_rcs[] = "$Id: cgi.c,v 1.101 2008/02/03 15:45:06 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/cgi.c,v $
@@ -38,6 +38,22 @@ const char cgi_rcs[] = "$Id: cgi.c,v 1.96 2007/03/08 17:41:05 fabiankeil Exp $";
  *
  * Revisions   :
  *    $Log: cgi.c,v $
+ *    Revision 1.101  2008/02/03 15:45:06  fabiankeil
+ *    Add SOCKS5 support for "Forwarding failure" CGI page.
+ *
+ *    Revision 1.100  2007/10/17 18:40:53  fabiankeil
+ *    - Send CGI pages as HTTP/1.1 unless the client asked for HTTP/1.0.
+ *    - White space fix.
+ *
+ *    Revision 1.99  2007/08/05 13:42:22  fabiankeil
+ *    #1763173 from Stefan Huehner: declare some more functions static.
+ *
+ *    Revision 1.98  2007/05/14 10:33:51  fabiankeil
+ *    - Use strlcpy() and strlcat() instead of strcpy() and strcat().
+ *
+ *    Revision 1.97  2007/04/09 18:11:35  fabiankeil
+ *    Don't mistake VC++'s _snprintf() for a snprintf() replacement.
+ *
  *    Revision 1.96  2007/03/08 17:41:05  fabiankeil
  *    Use sizeof() more often.
  *
@@ -895,7 +911,7 @@ struct http_response *dispatch_cgi(struct client_state *csp)
  * Returns     :  pointer to value (no copy!), or NULL if none found.
  *
  *********************************************************************/
-char *grep_cgi_referrer(const struct client_state *csp)
+static char *grep_cgi_referrer(const struct client_state *csp)
 {
    struct list_entry *p;
 
@@ -927,7 +943,7 @@ char *grep_cgi_referrer(const struct client_state *csp)
  *                FALSE if the referrer is unsafe or not set.
  *
  *********************************************************************/
-int referrer_is_safe (const struct client_state *csp)
+static int referrer_is_safe(const struct client_state *csp)
 {
    char *referrer;
    const char alternative_prefix[] = "http://" CGI_SITE_1_HOST "/";
@@ -1419,7 +1435,8 @@ struct http_response *error_response(struct client_state *csp,
    }
    else if (!strcmp(templatename, "forwarding-failed"))
    {
-      const struct forward_spec * fwd = forward_url(csp->http, csp);
+      const struct forward_spec *fwd = forward_url(csp, csp->http);
+      char *socks_type = NULL;
       if (fwd == NULL)
       {
          log_error(LOG_LEVEL_FATAL, "gateway spec is NULL. This shouldn't happen!");
@@ -1445,8 +1462,27 @@ struct http_response *error_response(struct client_state *csp,
          csp->error_message = strdup("Failure reason missing. Check the log file for details.");
       }
       if (!err) err = map(exports, "gateway", 1, fwd->gateway_host, 1);
-      if (!err) err = map(exports, "forwarding-type", 1, (fwd->type == SOCKS_4) ?
-                         "socks4-" : "socks4a-", 1);
+
+      /*
+       * XXX: this is almost the same code as in cgi_show_url_info()
+       * and thus should be factored out and shared.
+       */
+      switch (fwd->type)
+      {
+         case SOCKS_4:
+            socks_type = "socks4-";
+            break;
+         case SOCKS_4A:
+            socks_type = "socks4a-";
+            break;
+         case SOCKS_5:
+            socks_type = "socks5-";
+            break;
+         default:
+            log_error(LOG_LEVEL_FATAL, "Unknown socks type: %d.", fwd->type);
+      }
+
+      if (!err) err = map(exports, "forwarding-type", 1, socks_type, 1);
       if (!err) err = map(exports, "error-message", 1, html_encode(csp->error_message), 0);
 
       if (!err) rsp->status = strdup("503 Forwarding failure");
@@ -1635,6 +1671,7 @@ jb_err cgi_error_no_template(struct client_state *csp,
       ").</p>\r\n"
       "</body>\r\n"
       "</html>\r\n";
+   const size_t body_size = strlen(body_prefix) + strlen(template_name) + strlen(body_suffix) + 1;
 
    assert(csp);
    assert(rsp);
@@ -1648,14 +1685,14 @@ jb_err cgi_error_no_template(struct client_state *csp,
    rsp->head_length = 0;
    rsp->is_static = 0;
 
-   rsp->body = malloc(strlen(body_prefix) + strlen(template_name) + strlen(body_suffix) + 1);
+   rsp->body = malloc(body_size);
    if (rsp->body == NULL)
    {
       return JB_ERR_MEMORY;
    }
-   strcpy(rsp->body, body_prefix);
-   strcat(rsp->body, template_name);
-   strcat(rsp->body, body_suffix);
+   strlcpy(rsp->body, body_prefix, body_size);
+   strlcat(rsp->body, template_name, body_size);
+   strlcat(rsp->body, body_suffix, body_size);
 
    rsp->status = strdup(status);
    if (rsp->status == NULL)
@@ -1715,6 +1752,11 @@ jb_err cgi_error_unknown(struct client_state *csp,
       "</body>\r\n"
       "</html>\r\n";
    char errnumbuf[30];
+   /*
+    * Due to sizeof(errnumbuf), body_size will be slightly
+    * bigger than necessary but it doesn't really matter.
+    */
+   const size_t body_size = strlen(body_prefix) + sizeof(errnumbuf) + strlen(body_suffix) + 1;
    assert(csp);
    assert(rsp);
 
@@ -1729,14 +1771,14 @@ jb_err cgi_error_unknown(struct client_state *csp,
 
    snprintf(errnumbuf, sizeof(errnumbuf), "%d", error_to_report);
 
-   rsp->body = malloc(strlen(body_prefix) + strlen(errnumbuf) + strlen(body_suffix) + 1);
+   rsp->body = malloc(body_size);
    if (rsp->body == NULL)
    {
       return JB_ERR_MEMORY;
    }
-   strcpy(rsp->body, body_prefix);
-   strcat(rsp->body, errnumbuf);
-   strcat(rsp->body, body_suffix);
+   strlcpy(rsp->body, body_prefix, body_size);
+   strlcat(rsp->body, errnumbuf,   body_size);
+   strlcat(rsp->body, body_suffix, body_size);
 
    rsp->status = strdup(status);
    if (rsp->status == NULL)
@@ -1973,9 +2015,12 @@ struct http_response *finish_http_response(const struct client_state *csp, struc
    }
 
    /* 
-    * Fill in the HTTP Status
+    * Fill in the HTTP Status, using HTTP/1.1
+    * unless the client asked for HTTP/1.0.
     */
-   snprintf(buf, sizeof(buf), "HTTP/1.0 %s", rsp->status ? rsp->status : "200 OK");
+   snprintf(buf, sizeof(buf), "%s %s",
+      strcmpic(csp->http->ver, "HTTP/1.0") ? "HTTP/1.1" : "HTTP/1.0",
+      rsp->status ? rsp->status : "200 OK");
    err = enlist_first(rsp->headers, buf);
 
    /* 
@@ -2011,12 +2056,12 @@ struct http_response *finish_http_response(const struct client_state *csp, struc
 
    if (strncmpic(rsp->status, "302", 3))
    {
-     /*
-      * If it's not a redirect without any content,
-      * set the Content-Type to text/html if it's
-      * not already specified.
-      */
-     if (!err) err = enlist_unique(rsp->headers, "Content-Type: text/html", 13);
+      /*
+       * If it's not a redirect without any content,
+       * set the Content-Type to text/html if it's
+       * not already specified.
+       */
+      if (!err) err = enlist_unique(rsp->headers, "Content-Type: text/html", 13);
    }
 
    /*