Let the msn filter hide elements with the id 's_notf_div'.
[privoxy.git] / cgi.c
diff --git a/cgi.c b/cgi.c
index 526381f..0583f88 100644 (file)
--- a/cgi.c
+++ b/cgi.c
@@ -1,4 +1,4 @@
-const char cgi_rcs[] = "$Id: cgi.c,v 1.124 2009/06/12 11:03:03 fabiankeil Exp $";
+const char cgi_rcs[] = "$Id: cgi.c,v 1.130 2011/04/19 13:00:47 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/cgi.c,v $
@@ -49,6 +49,10 @@ const char cgi_rcs[] = "$Id: cgi.c,v 1.124 2009/06/12 11:03:03 fabiankeil Exp $"
 #include <limits.h>
 #include <assert.h>
 
+#ifdef FEATURE_COMPRESSION
+#include <zlib.h>
+#endif
+
 #include "project.h"
 #include "cgi.h"
 #include "list.h"
@@ -553,7 +557,7 @@ static struct http_response *dispatch_known_cgi(struct client_state * csp,
          if (!err)
          {
             /* It worked */
-            rsp->reason = RSP_REASON_CGI_CALL;
+            rsp->crunch_reason = CGI_CALL;
             return finish_http_response(csp, rsp);
          }
          else
@@ -876,7 +880,7 @@ struct http_response *error_response(struct client_state *csp,
    if (!strcmp(templatename, "no-such-domain"))
    {
       rsp->status = strdup("404 No such domain");
-      rsp->reason = RSP_REASON_NO_SUCH_DOMAIN;
+      rsp->crunch_reason = NO_SUCH_DOMAIN;
    }
    else if (!strcmp(templatename, "forwarding-failed"))
    {
@@ -938,22 +942,22 @@ struct http_response *error_response(struct client_state *csp,
       }
 
       rsp->status = strdup("503 Forwarding failure");
-      rsp->reason = RSP_REASON_FORWARDING_FAILED;
+      rsp->crunch_reason = FORWARDING_FAILED;
    }
    else if (!strcmp(templatename, "connect-failed"))
    {
       rsp->status = strdup("503 Connect failed");
-      rsp->reason = RSP_REASON_CONNECT_FAILED;
+      rsp->crunch_reason = CONNECT_FAILED;
    }
    else if (!strcmp(templatename, "connection-timeout"))
    {
       rsp->status = strdup("504 Connection timeout");
-      rsp->reason = RSP_REASON_CONNECTION_TIMEOUT;
+      rsp->crunch_reason = CONNECTION_TIMEOUT;
    }
    else if (!strcmp(templatename, "no-server-data"))
    {
       rsp->status = strdup("502 No data received from server or forwarder");
-      rsp->reason = RSP_REASON_NO_SERVER_DATA;
+      rsp->crunch_reason = NO_SERVER_DATA;
    }
 
    if (rsp->status == NULL)
@@ -1053,7 +1057,7 @@ void cgi_init_error_messages(void)
       strlen(cgi_error_memory_response->head);
    cgi_error_memory_response->content_length =
       strlen(cgi_error_memory_response->body);
-   cgi_error_memory_response->reason = RSP_REASON_OUT_OF_MEMORY;
+   cgi_error_memory_response->crunch_reason = OUT_OF_MEMORY;
 }
 
 
@@ -1224,7 +1228,7 @@ jb_err cgi_error_unknown(const struct client_state *csp,
    rsp->content_length = 0;
    rsp->head_length = 0;
    rsp->is_static = 0;
-   rsp->reason = RSP_REASON_INTERNAL_ERROR;
+   rsp->crunch_reason = INTERNAL_ERROR;
 
    snprintf(errnumbuf, sizeof(errnumbuf), "%d", error_to_report);
 
@@ -1362,7 +1366,7 @@ char *add_help_link(const char *item,
    string_join  (&result, string_toupper(item));
    string_append(&result, "\">");
    string_append(&result, item);
-   string_append(&result, "</a> ");
+   string_append(&result, "</a>");
 
    return result;
 }
@@ -1479,6 +1483,59 @@ static void get_locale_time(char *buf, size_t buffer_size)
 
 }
 
+
+#ifdef FEATURE_COMPRESSION
+/*********************************************************************
+ *
+ * Function    :  compress_buffer
+ *
+ * Description :  Compresses the content of a buffer with zlib's deflate
+ *                Allocates a new buffer for the result, free'ing it is
+ *                up to the caller.
+ *
+ *                XXX: We should add a config option for the
+ *                     compression level.
+ *
+ *
+ * Parameters  :
+ *          1  :  buffer = buffer whose content should be compressed
+ *          2  :  buffer_length = length of the buffer
+ *
+ * Returns     :  NULL on error, otherwise a pointer to the compressed
+ *                content of the input buffer.
+ *
+ *********************************************************************/
+char *compress_buffer(char *buffer, size_t *buffer_length)
+{
+   char *compressed_buffer;
+   size_t new_length = *buffer_length;
+
+   compressed_buffer = malloc(new_length);
+   if (NULL == compressed_buffer)
+   {
+      log_error(LOG_LEVEL_FATAL,
+         "Out of memory allocation compression buffer.");
+   }
+
+   if (Z_OK != compress2((Bytef *)compressed_buffer, &new_length,
+         (Bytef *)buffer, *buffer_length, Z_DEFAULT_COMPRESSION))
+   {
+      log_error(LOG_LEVEL_ERROR, "Error in compress2()");
+      freez(compressed_buffer);
+      return NULL;
+   }
+
+   log_error(LOG_LEVEL_RE_FILTER,
+      "Compressed content from %d to %d bytes.", *buffer_length, new_length);
+
+   *buffer_length = new_length;
+
+   return compressed_buffer;
+
+}
+#endif
+
+
 /*********************************************************************
  *
  * Function    :  finish_http_response
@@ -1524,6 +1581,23 @@ struct http_response *finish_http_response(const struct client_state *csp, struc
    {
       rsp->content_length = rsp->body ? strlen(rsp->body) : 0;
    }
+
+#ifdef FEATURE_COMPRESSION
+   if (!err && (csp->flags & CSP_FLAG_CLIENT_SUPPORTS_DEFLATE)
+      && (rsp->content_length > LOWER_LENGTH_LIMIT_FOR_COMRPESSION))
+   {
+      char *compressed_content;
+
+      compressed_content = compress_buffer(rsp->body, &rsp->content_length);
+      if (NULL != compressed_content)
+      {
+         freez(rsp->body);
+         rsp->body = compressed_content;
+      }
+      err = enlist_unique_header(rsp->headers, "Content-Encoding", "deflate");
+   }
+#endif
+
    if (!err)
    {
       snprintf(buf, sizeof(buf), "Content-Length: %d", (int)rsp->content_length);
@@ -1636,13 +1710,10 @@ struct http_response *finish_http_response(const struct client_state *csp, struc
       if (!err) err = enlist_unique_header(rsp->headers, "Pragma", "no-cache");
    }
 
-   /*
-    * Quoting RFC 2616:
-    *
-    * HTTP/1.1 applications that do not support persistent connections MUST
-    * include the "close" connection option in every message.
-    */
-   if (!err) err = enlist_unique_header(rsp->headers, "Connection", "close");
+   if (!err && !(csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE))
+   {
+      err = enlist_unique_header(rsp->headers, "Connection", "close");
+   }
 
    /* 
     * Write the head
@@ -1865,7 +1936,7 @@ jb_err template_load(const struct client_state *csp, char **template_ptr,
  *                HTML template by replacing @name@ with value using
  *                pcrs, for each item in the output map.
  *
- *                Note that a leading '$' charachter in the export map's
+ *                Note that a leading '$' character in the export map's
  *                values will be stripped and toggle on backreference
  *                interpretation.
  *