Help clang understand that we aren't dereferencing
[privoxy.git] / parsers.c
index e60b141..85137fe 100644 (file)
--- a/parsers.c
+++ b/parsers.c
@@ -1,4 +1,4 @@
-const char parsers_rcs[] = "$Id: parsers.c,v 1.145 2008/10/09 18:21:41 fabiankeil Exp $";
+const char parsers_rcs[] = "$Id: parsers.c,v 1.151 2009/02/15 14:46:35 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/parsers.c,v $
@@ -17,7 +17,7 @@ const char parsers_rcs[] = "$Id: parsers.c,v 1.145 2008/10/09 18:21:41 fabiankei
  *                   `client_if_none_match', `get_destination_from_headers',
  *                   `parse_header_time', `decompress_iob' and `server_set_cookie'.
  *
- * Copyright   :  Written by and Copyright (C) 2001-2008 the SourceForge
+ * Copyright   :  Written by and Copyright (C) 2001-2009 the
  *                Privoxy team. http://www.privoxy.org/
  *
  *                Based on the Internet Junkbuster originally written
@@ -44,6 +44,30 @@ const char parsers_rcs[] = "$Id: parsers.c,v 1.145 2008/10/09 18:21:41 fabiankei
  *
  * Revisions   :
  *    $Log: parsers.c,v $
+ *    Revision 1.151  2009/02/15 14:46:35  fabiankeil
+ *    Don't let hide-referrer{conditional-*}} pass
+ *    Referer headers without http URLs.
+ *
+ *    Revision 1.150  2008/12/04 18:12:19  fabiankeil
+ *    Fix some cparser warnings.
+ *
+ *    Revision 1.149  2008/11/21 18:39:53  fabiankeil
+ *    In case of CONNECT requests there's no point
+ *    in trying to keep the connection alive.
+ *
+ *    Revision 1.148  2008/11/16 12:43:49  fabiankeil
+ *    Turn keep-alive support into a runtime feature
+ *    that is disabled by setting keep-alive-timeout
+ *    to a negative value.
+ *
+ *    Revision 1.147  2008/11/04 17:20:31  fabiankeil
+ *    HTTP/1.1 responses without Connection
+ *    header imply keep-alive. Act accordingly.
+ *
+ *    Revision 1.146  2008/10/12 16:46:35  fabiankeil
+ *    Remove obsolete warning about delayed delivery with chunked
+ *    transfer encoding and FEATURE_CONNECTION_KEEP_ALIVE enabled.
+ *
  *    Revision 1.145  2008/10/09 18:21:41  fabiankeil
  *    Flush work-in-progress changes to keep outgoing connections
  *    alive where possible. Incomplete and mostly #ifdef'd out.
@@ -961,6 +985,7 @@ static jb_err create_forged_referrer(char **header, const char *hostport);
 static jb_err create_fake_referrer(char **header, const char *fake_referrer);
 static jb_err handle_conditional_hide_referrer_parameter(char **header,
    const char *host, const int parameter_conditional_block);
+static const char *get_appropiate_connection_header(const struct client_state *csp);
 
 /*
  * List of functions to run on a list of headers.
@@ -1190,7 +1215,7 @@ jb_err decompress_iob(struct client_state *csp)
 
    cur = csp->iob->cur;
 
-   if (bufsize < 10)
+   if (bufsize < (size_t)10)
    {
       /*
        * This is to protect the parsing of gzipped data,
@@ -1445,7 +1470,7 @@ jb_err decompress_iob(struct client_state *csp)
           */
          assert(zstr.avail_out == tmpbuf + bufsize - (char *)zstr.next_out);
          assert((char *)zstr.next_out == tmpbuf + ((char *)oldnext_out - buf));
-         assert(zstr.avail_out > 0);
+         assert(zstr.avail_out > 0U);
 
          buf = tmpbuf;
       }
@@ -1497,7 +1522,7 @@ jb_err decompress_iob(struct client_state *csp)
     && (csp->iob->eod <= csp->iob->buf + csp->iob->size))
    {
       const size_t new_size = (size_t)(csp->iob->eod - csp->iob->cur);
-      if (new_size > 0)
+      if (new_size > (size_t)0)
       {
          log_error(LOG_LEVEL_RE_FILTER,
             "Decompression successful. Old size: %d, new size: %d.",
@@ -1730,6 +1755,7 @@ static char *get_header_line(struct iob *iob)
       /* FIXME No way to handle error properly */
       log_error(LOG_LEVEL_FATAL, "Out of memory in get_header_line()");
    }
+   assert(ret != NULL);
 
    iob->cur = p+1;
 
@@ -2077,6 +2103,7 @@ static jb_err header_tagger(struct client_state *csp, char *header)
                      if (0 > hits)
                      {
                         /* Regex failure, log it but continue anyway. */
+                        assert(NULL != header);
                         log_error(LOG_LEVEL_ERROR,
                            "Problems with tagger \'%s\' and header \'%s\': %s",
                            b->name, *header, pcrs_strerror(hits));
@@ -2357,7 +2384,9 @@ static jb_err server_connection(struct client_state *csp, char **header)
    if (strcmpic(*header, "Connection: close"))
    {
 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
-      if (!strcmpic(*header, "Connection: keep-alive"))
+      if ((csp->config->feature_flags &
+           RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
+         && !strcmpic(*header, "Connection: keep-alive"))
       {
          /* Remember to keep the connection alive. */
          csp->flags |= CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE;
@@ -2401,11 +2430,7 @@ static jb_err server_connection(struct client_state *csp, char **header)
 static jb_err client_connection(struct client_state *csp, char **header)
 {
    char *old_header = *header;
-#ifdef FEATURE_CONNECTION_KEEP_ALIVE
-   static const char wanted_header[] = "Connection: keep-alive";
-#else
-   static const char wanted_header[] = "Connection: close";
-#endif /* FEATURE_CONNECTION_KEEP_ALIVE */
+   const char *wanted_header = get_appropiate_connection_header(csp);
 
    if (strcmpic(*header, wanted_header))
    {
@@ -2445,6 +2470,7 @@ static jb_err client_connection(struct client_state *csp, char **header)
  *********************************************************************/
 static jb_err crumble(struct client_state *csp, char **header)
 {
+   (void)csp;
    log_error(LOG_LEVEL_HEADER, "crumble crunched: %s!", *header);
    freez(*header);
    return JB_ERR_OK;
@@ -3551,12 +3577,13 @@ static jb_err client_max_forwards(struct client_state *csp, char **header)
        (0 == strcmpic(csp->http->gpc, "options")))
    {
       assert(*(*header+12) == ':');
-      if (1 == sscanf(*header+12, ": %u", &max_forwards))
+      if (1 == sscanf(*header+12, ": %d", &max_forwards))
       {
          if (max_forwards > 0)
          {
-            snprintf(*header, strlen(*header)+1, "Max-Forwards: %u", --max_forwards);
-            log_error(LOG_LEVEL_HEADER, "Max-Forwards value for %s request reduced to %u.",
+            snprintf(*header, strlen(*header)+1, "Max-Forwards: %d", --max_forwards);
+            log_error(LOG_LEVEL_HEADER,
+               "Max-Forwards value for %s request reduced to %d.",
                csp->http->gpc, max_forwards);
          }
          else if (max_forwards < 0)
@@ -4068,6 +4095,7 @@ static jb_err client_x_forwarded_for_adder(struct client_state *csp)
 static jb_err server_connection_close_adder(struct client_state *csp)
 {
    const unsigned int flags = csp->flags;
+   const char *response_status_line = csp->headers->first->str;
 
    if ((flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
     && (flags & CSP_FLAG_SERVER_CONNECTION_CLOSE_SET))
@@ -4075,6 +4103,19 @@ static jb_err server_connection_close_adder(struct client_state *csp)
       return JB_ERR_OK;
    }
 
+   /*
+    * XXX: if we downgraded the response, this check will fail.
+    */
+   if ((csp->config->feature_flags &
+        RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
+    && (NULL != response_status_line)
+    && !strncmpic(response_status_line, "HTTP/1.1", 8))
+   {
+      log_error(LOG_LEVEL_HEADER, "A HTTP/1.1 response "
+         "without Connection header implies keep-alive.");
+      csp->flags |= CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE;
+   }
+
    log_error(LOG_LEVEL_HEADER, "Adding: Connection: close");
 
    return enlist(csp->headers, "Connection: close");
@@ -4097,12 +4138,8 @@ static jb_err server_connection_close_adder(struct client_state *csp)
  *********************************************************************/
 static jb_err client_connection_header_adder(struct client_state *csp)
 {
-#ifdef FEATURE_CONNECTION_KEEP_ALIVE
-   static const char wanted_header[] = "Connection: keep-alive";
-#else
-   static const char wanted_header[] = "Connection: close";
-#endif /* FEATURE_CONNECTION_KEEP_ALIVE */
    const unsigned int flags = csp->flags;
+   const char *wanted_header = get_appropiate_connection_header(csp);
 
    if (!(flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
      && (flags & CSP_FLAG_CLIENT_CONNECTION_HEADER_SET))
@@ -4616,6 +4653,7 @@ static jb_err handle_conditional_hide_referrer_parameter(char **header,
 {
    char *referer = strdup(*header);
    const size_t hostlenght = strlen(host);
+   const char *referer_url = NULL;
 
    if (NULL == referer)
    {
@@ -4624,7 +4662,7 @@ static jb_err handle_conditional_hide_referrer_parameter(char **header,
    }
 
    /* referer begins with 'Referer: http[s]://' */
-   if (hostlenght < (strlen(referer)-17))
+   if ((hostlenght+17) < strlen(referer))
    {
       /*
        * Shorten referer to make sure the referer is blocked
@@ -4633,9 +4671,10 @@ static jb_err handle_conditional_hide_referrer_parameter(char **header,
        */
       referer[hostlenght+17] = '\0';
    }
-   if (NULL == strstr(referer, host))
+   referer_url = strstr(referer, "http://");
+   if ((NULL == referer_url) || (NULL == strstr(referer_url, host)))
    {
-      /* Host has changed */
+      /* Host has changed, Referer is invalid or a https URL. */
       if (parameter_conditional_block)
       {
          log_error(LOG_LEVEL_HEADER, "New host is: %s. Crunching %s!", host, *header);
@@ -4654,6 +4693,33 @@ static jb_err handle_conditional_hide_referrer_parameter(char **header,
 
 }
 
+
+/*********************************************************************
+ *
+ * Function    :  get_appropiate_connection_header
+ *
+ * Description :  Returns an appropiate Connection header
+ *                depending on whether or not we try to keep
+ *                the connection to the server alive.
+ *
+ * Parameters  :
+ *          1  :  csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns     :  Pointer to statically allocated header buffer.
+ *
+ *********************************************************************/
+static const char *get_appropiate_connection_header(const struct client_state *csp)
+{
+   static const char connection_keep_alive[] = "Connection: keep-alive";
+   static const char connection_close[] = "Connection: close";
+
+   if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
+    && (csp->http->ssl == 0))
+   {
+      return connection_keep_alive;
+   }
+   return connection_close;
+}
 /*
   Local Variables:
   tab-width: 3