Drop the 'Functions declared include:' comment sections
[privoxy.git] / filters.c
index 4de7c90..5ca6b99 100644 (file)
--- a/filters.c
+++ b/filters.c
@@ -1,19 +1,11 @@
-const char filters_rcs[] = "$Id: filters.c,v 1.152 2011/10/30 16:18:12 fabiankeil Exp $";
+const char filters_rcs[] = "$Id: filters.c,v 1.163 2011/12/26 17:03:08 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/filters.c,v $
  *
  * Purpose     :  Declares functions to parse/crunch headers and pages.
- *                Functions declared include:
- *                   `acl_addr', `add_stats', `block_acl', `block_imageurl',
- *                   `block_url', `url_actions', `domain_split',
- *                   `filter_popups', `forward_url', 'redirect_url',
- *                   `ij_untrusted_url', `intercept_url', `pcrs_filter_respose',
- *                   `ijb_send_banner', `trust_url', `gif_deanimate_response',
- *                   `execute_single_pcrs_command', `rewrite_url',
- *                   `get_last_url'
- *
- * Copyright   :  Written by and Copyright (C) 2001-2010 the
+ *
+ * Copyright   :  Written by and Copyright (C) 2001-2011 the
  *                Privoxy team. http://www.privoxy.org/
  *
  *                Based on the Internet Junkbuster originally written
@@ -78,11 +70,6 @@ const char filters_rcs[] = "$Id: filters.c,v 1.152 2011/10/30 16:18:12 fabiankei
 #include "urlmatch.h"
 #include "loaders.h"
 
-#ifdef HAVE_STRTOK
-/* Only used for locks */
-#include "jcc.h"
-#endif /* def HAVE_STRTOK */
-
 #ifdef _WIN32
 #include "win32.h"
 #endif
@@ -1110,73 +1097,78 @@ char *get_last_url(char *subject, const char *redirect_mode)
       return NULL;
    }
 
-   if (0 == strcmpic(redirect_mode, "check-decoded-url"))
+   if (0 == strcmpic(redirect_mode, "check-decoded-url") && strchr(subject, '%'))
    {  
       log_error(LOG_LEVEL_REDIRECTS,
          "Checking \"%s\" for encoded redirects.", subject);
 
-#if defined(MUTEX_LOCKS_AVAILABLE) && defined(HAVE_STRTOK)
       /*
        * Check each parameter in the URL separately.
        * Sectionize the URL at "?" and "&",
-       * then URL-decode each component,
+       * go backwards through the segments, URL-decode them
        * and look for a URL in the decoded result.
-       * Keep the last one we spot.
+       * Stop the search after the first match.
+       */
+      char *url_segment = NULL;
+      /*
+       * XXX: This estimate is guaranteed to be high enough as we
+       *      let ssplit() ignore empty fields, but also a bit wasteful.
        */
-      char *found = NULL;
+      size_t max_segments = strlen(subject) / 2;
+      char **url_segments = malloc(max_segments * sizeof(char *));
+      int segments;
+
+      if (NULL == url_segments)
+      {
+         log_error(LOG_LEVEL_ERROR, "Out of memory while decoding URL: %s", new_url);
+         freez(subject);
+         return NULL;
+      }
 
-      privoxy_mutex_lock(&strtok_mutex);
-      char *token = strtok(subject, "?&");
-      while (token)
+      segments = ssplit(subject, "?&", url_segments, max_segments, 1, 1);
+
+      while (segments-- > 0)
       {
-         char *dtoken = url_decode(token);
+         char *dtoken = url_decode(url_segments[segments]);
          if (NULL == dtoken)
          {
-            log_error(LOG_LEVEL_ERROR, "Unable to decode \"%s\".", token);
+            log_error(LOG_LEVEL_ERROR, "Unable to decode \"%s\".", url_segments[segments]);
             continue;
          }
-         char *h1 = strstr(dtoken, "http://");
-         char *h2 = strstr(dtoken, "https://");
-         char *h = (h1 && h2
-                    ? (h1 < h2 ? h1 : h2)
-                    : (h1 ? h1 : h2));
-         if (h)
+         url_segment = strstr(dtoken, "http://");
+         if (NULL == url_segment)
+         {
+            url_segment = strstr(dtoken, "https://");
+         }
+         if (NULL != url_segment)
          {
-            freez(found);
-            found = strdup(h);
-            if (found == NULL)
+            url_segment = strdup(url_segment);
+            freez(dtoken);
+            if (url_segment == NULL)
             {
                log_error(LOG_LEVEL_ERROR,
                   "Out of memory while searching for redirects.");
-               privoxy_mutex_unlock(&strtok_mutex);
                return NULL;
             }
+            break;
          }
          freez(dtoken);
-         token = strtok(NULL, "?&");
       }
-      privoxy_mutex_unlock(&strtok_mutex);
       freez(subject);
+      freez(url_segments);
 
-      return found;
-#else
-      new_url = url_decode(subject);
-      if (new_url != NULL)
-      {
-         freez(subject);
-         subject = new_url;
-      }
-      else
+      if (url_segment == NULL)
       {
-         log_error(LOG_LEVEL_ERROR, "Unable to decode \"%s\".", subject);
+         return NULL;
       }
-#endif /* defined(MUTEX_LOCKS_AVAILABLE) && defined(HAVE_STRTOK) */
+      subject = url_segment;
+   }
+   else
+   {
+      /* Look for a URL inside this one, without decoding anything. */
+      log_error(LOG_LEVEL_REDIRECTS,
+         "Checking \"%s\" for unencoded redirects.", subject);
    }
-
-   /* Else, just look for a URL inside this one, without decoding anything. */
-
-   log_error(LOG_LEVEL_REDIRECTS,
-      "Checking \"%s\" for unencoded redirects.", subject);
 
    /*
     * Find the last URL encoded in the request
@@ -1308,6 +1300,21 @@ struct http_response *redirect_url(struct client_state *csp)
    /* Did any redirect action trigger? */
    if (new_url)
    {
+      if (url_requires_percent_encoding(new_url))
+      {
+         char *encoded_url;
+         log_error(LOG_LEVEL_REDIRECTS, "Percent-encoding redirect URL: %N",
+            strlen(new_url), new_url);
+         encoded_url = percent_encode_url(new_url);
+         freez(new_url);
+         if (encoded_url == NULL)
+         {
+            return cgi_error_memory();
+         }
+         new_url = encoded_url;
+         assert(FALSE == url_requires_percent_encoding(new_url));
+      }
+
       if (0 == strcmpic(new_url, csp->http->url))
       {
          log_error(LOG_LEVEL_ERROR,
@@ -1325,8 +1332,8 @@ struct http_response *redirect_url(struct client_state *csp)
             return cgi_error_memory();
          }
 
-         if ( enlist_unique_header(rsp->headers, "Location", new_url)
-           || (NULL == (rsp->status = strdup("302 Local Redirect from Privoxy"))) )
+         if (enlist_unique_header(rsp->headers, "Location", new_url)
+           || (NULL == (rsp->status = strdup("302 Local Redirect from Privoxy"))))
          {
             freez(new_url);
             free_http_response(rsp);
@@ -1839,19 +1846,15 @@ static jb_err remove_chunked_transfer_coding(char *buffer, size_t *size)
          return JB_ERR_PARSE;
       }
 
-      if ((newsize += chunksize) >= *size)
+      if (chunksize >= *size - newsize)
       {
-         /*
-          * XXX: The message is a bit confusing. Isn't the real problem that
-          *      the specified chunk size is greater than the number of bytes
-          *      left in the buffer? This probably means the connection got
-          *      closed prematurely. To be investigated after 3.0.17 is out.
-          */
          log_error(LOG_LEVEL_ERROR,
-            "Chunk size %d exceeds buffer size %d in \"chunked\" transfer coding",
-            chunksize, *size);
+            "Chunk size %u exceeds buffered data left. "
+            "Already digested %u of %u buffered bytes.",
+            chunksize, (unsigned int)newsize, (unsigned int)*size);
          return JB_ERR_PARSE;
       }
+      newsize += chunksize;
       from_p += 2;
 
       memmove(to_p, from_p, (size_t) chunksize);