After preventing the client from pipeling, don't signal keep-alive intentions
[privoxy.git] / parsers.c
index 09a12e4..51618b6 100644 (file)
--- a/parsers.c
+++ b/parsers.c
@@ -1,4 +1,4 @@
-const char parsers_rcs[] = "$Id: parsers.c,v 1.246 2012/07/23 12:40:30 fabiankeil Exp $";
+const char parsers_rcs[] = "$Id: parsers.c,v 1.249 2012/09/04 08:33:17 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/parsers.c,v $
@@ -1800,22 +1800,20 @@ static jb_err client_keep_alive(struct client_state *csp, char **header)
  *                Content-Length header.
  *
  * Parameters  :
- *          1  :  header = The Content-Length header.
+ *          1  :  header_value = The Content-Length header value.
  *          2  :  length = Storage to return the value.
  *
  * Returns     :  JB_ERR_OK on success, or
  *                JB_ERR_PARSE if no value is recognized.
  *
  *********************************************************************/
-static jb_err get_content_length(const char *header, unsigned long long *length)
+static jb_err get_content_length(const char *header_value, unsigned long long *length)
 {
-   assert(header[14] == ':');
-
 #ifdef _WIN32
    assert(sizeof(unsigned long long) > 4);
-   if (1 != sscanf(header+14, ": %I64u", length))
+   if (1 != sscanf(header_value, "%I64u", length))
 #else
-   if (1 != sscanf(header+14, ": %llu", length))
+   if (1 != sscanf(header_value, "%llu", length))
 #endif
    {
       return JB_ERR_PARSE;
@@ -1845,10 +1843,12 @@ static jb_err get_content_length(const char *header, unsigned long long *length)
 static jb_err client_save_content_length(struct client_state *csp, char **header)
 {
    unsigned long long content_length = 0;
+   const char *header_value;
 
    assert(*(*header+14) == ':');
 
-   if (JB_ERR_OK != get_content_length(*header, &content_length))
+   header_value = *header + 15;
+   if (JB_ERR_OK != get_content_length(header_value, &content_length))
    {
       log_error(LOG_LEVEL_ERROR, "Crunching invalid header: %s", *header);
       freez(*header);
@@ -1889,7 +1889,8 @@ static jb_err client_connection(struct client_state *csp, char **header)
    if (!strcmpic(*header, connection_close))
    {
 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
-      if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING))
+      if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING)
+        && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED))
       {
           if (!strcmpic(csp->http->ver, "HTTP/1.1"))
           {
@@ -1921,7 +1922,8 @@ static jb_err client_connection(struct client_state *csp, char **header)
          csp->flags &= ~CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
       }
    }
-   else if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE))
+   else if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
+        && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED))
    {
       log_error(LOG_LEVEL_HEADER,
          "Keeping the client header '%s' around. "
@@ -2378,10 +2380,12 @@ static jb_err server_adjust_content_length(struct client_state *csp, char **head
 static jb_err server_save_content_length(struct client_state *csp, char **header)
 {
    unsigned long long content_length = 0;
+   const char *header_value;
 
    assert(*(*header+14) == ':');
 
-   if (JB_ERR_OK != get_content_length(*header, &content_length))
+   header_value = *header + 15;
+   if (JB_ERR_OK != get_content_length(header_value, &content_length))
    {
       log_error(LOG_LEVEL_ERROR, "Crunching invalid header: %s", *header);
       freez(*header);
@@ -3710,6 +3714,7 @@ static jb_err client_connection_header_adder(struct client_state *csp)
    static const char connection_close[] = "Connection: close";
 
    if (!(csp->flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
+     && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED)
      && (csp->flags & CSP_FLAG_CLIENT_CONNECTION_HEADER_SET))
    {
       return JB_ERR_OK;
@@ -3717,6 +3722,7 @@ static jb_err client_connection_header_adder(struct client_state *csp)
 
 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
+      && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED)
       && (csp->http->ssl == 0)
       && !strcmpic(csp->http->ver, "HTTP/1.1"))
    {
@@ -4303,6 +4309,39 @@ static void create_content_length_header(unsigned long long content_length,
 }
 
 
+/*********************************************************************
+ *
+ * Function    :  get_expected_content_length
+ *
+ * Description :  Figures out the content length from a list of headers.
+ *
+ * Parameters  :
+ *          1  :  headers = List of headers
+ *
+ * Returns     :  Number of bytes to expect
+ *
+ *********************************************************************/
+unsigned long long get_expected_content_length(struct list *headers)
+{
+   const char *content_length_header;
+   unsigned long long content_length = 0;
+
+   content_length_header = get_header_value(headers, "Content-Length:");
+   if (content_length_header != NULL)
+   {
+      if (JB_ERR_OK != get_content_length(content_length_header, &content_length))
+      {
+         log_error(LOG_LEVEL_ERROR,
+            "Failed to get the Content-Length in %s", content_length_header);
+         /* XXX: The header will be removed later on */
+         return 0;
+      }
+   }
+
+   return content_length;
+}
+
+
 /*
   Local Variables:
   tab-width: 3