- Remove filter_client_header() and filter_client_header(),
[privoxy.git] / filters.c
index c938399..4fde672 100644 (file)
--- a/filters.c
+++ b/filters.c
@@ -1,4 +1,4 @@
-const char filters_rcs[] = "$Id: filters.c,v 1.78 2007/01/28 13:41:18 fabiankeil Exp $";
+const char filters_rcs[] = "$Id: filters.c,v 1.83 2007/03/17 15:20:05 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/filters.c,v $
@@ -13,7 +13,7 @@ const char filters_rcs[] = "$Id: filters.c,v 1.78 2007/01/28 13:41:18 fabiankeil
  *                   `jpeg_inspect_response', `execute_single_pcrs_command',
  *                   `rewrite_url', `get_last_url'
  *
- * Copyright   :  Written by and Copyright (C) 2001, 2004-2006 the SourceForge
+ * Copyright   :  Written by and Copyright (C) 2001, 2004-2007 the SourceForge
  *                Privoxy team. http://www.privoxy.org/
  *
  *                Based on the Internet Junkbuster originally written
@@ -40,6 +40,29 @@ const char filters_rcs[] = "$Id: filters.c,v 1.78 2007/01/28 13:41:18 fabiankeil
  *
  * Revisions   :
  *    $Log: filters.c,v $
+ *    Revision 1.83  2007/03/17 15:20:05  fabiankeil
+ *    New config option: enforce-blocks.
+ *
+ *    Revision 1.82  2007/03/13 11:28:43  fabiankeil
+ *    - Fix port handling in acl_addr() and use a temporary acl spec
+ *      copy so error messages don't contain a truncated version.
+ *    - Log size of iob before and after decompression.
+ *
+ *    Revision 1.81  2007/03/05 14:40:53  fabiankeil
+ *    - Cosmetical changes for LOG_LEVEL_RE_FILTER messages.
+ *    - Hide the "Go there anyway" link for blocked CONNECT
+ *      requests where going there anyway doesn't work anyway.
+ *
+ *    Revision 1.80  2007/02/07 10:55:20  fabiankeil
+ *    - Save the reason for generating http_responses.
+ *    - Block (+block) with status code 403 instead of 404.
+ *    - Use a different kludge to remember a failed decompression.
+ *
+ *    Revision 1.79  2007/01/31 16:21:38  fabiankeil
+ *    Search for Max-Forwards headers case-insensitive,
+ *    don't generate the "501 unsupported" message for invalid
+ *    Max-Forwards values and don't increase negative ones.
+ *
  *    Revision 1.78  2007/01/28 13:41:18  fabiankeil
  *    - Add HEAD support to finish_http_response.
  *    - Add error favicon to internal HTML error messages.
@@ -640,20 +663,33 @@ int block_acl(struct access_control_addr *dst, struct client_state *csp)
  * Returns     :  0 => Ok, everything else is an error.
  *
  *********************************************************************/
-int acl_addr(char *aspec, struct access_control_addr *aca)
+int acl_addr(const char *aspec, struct access_control_addr *aca)
 {
-   int i, masklength, port;
+   int i, masklength;
+   long port;
    char *p;
+   char *acl_spec = NULL;
 
    masklength = 32;
    port       =  0;
 
-   if ((p = strchr(aspec, '/')) != NULL)
+   /*
+    * Use a temporary acl spec copy so we can log
+    * the unmodified original in case of parse errors.
+    */
+   acl_spec = strdup(aspec);
+   if (acl_spec == NULL)
    {
-      *p++ = '\0';
+      /* XXX: This will be logged as parse error. */
+      return(-1);
+   }
 
+   if ((p = strchr(acl_spec, '/')) != NULL)
+   {
+      *p++ = '\0';
       if (ijb_isdigit(*p) == 0)
       {
+         free(acl_spec);
          return(-1);
       }
       masklength = atoi(p);
@@ -661,26 +697,32 @@ int acl_addr(char *aspec, struct access_control_addr *aca)
 
    if ((masklength < 0) || (masklength > 32))
    {
+      free(acl_spec);
       return(-1);
    }
 
-   if ((p = strchr(aspec, ':')) != NULL)
+   if ((p = strchr(acl_spec, ':')) != NULL)
    {
+      char *endptr;
+
       *p++ = '\0';
+      port = strtol(p, &endptr, 10);
 
-      if (ijb_isdigit(*p) == 0)
+      if (port <= 0 || port > 65535 || *endptr != '\0')
       {
+         free(acl_spec);
          return(-1);
       }
-      port = atoi(p);
    }
 
-   aca->port = port;
+   aca->port = (unsigned long)port;
 
-   aca->addr = ntohl(resolve_hostname_to_ip(aspec));
+   aca->addr = ntohl(resolve_hostname_to_ip(acl_spec));
+   free(acl_spec);
 
    if (aca->addr == INADDR_NONE)
    {
+      /* XXX: This will be logged as parse error. */
       return(-1);
    }
 
@@ -978,7 +1020,7 @@ struct http_response *block_url(struct client_state *csp)
       }
       else
       {
-         rsp->status = strdup("404 Request for blocked URL");
+         rsp->status = strdup("403 Request for blocked URL");
       }
 
       if (rsp->status == NULL)
@@ -996,7 +1038,15 @@ struct http_response *block_url(struct client_state *csp)
 
 #ifdef FEATURE_FORCE_LOAD
       err = map(exports, "force-prefix", 1, FORCE_PREFIX, 1);
-      if (csp->http->ssl != 0)
+      /*
+       * Export the force conditional block killer if
+       *
+       * - Privoxy was compiled without FEATURE_FORCE_LOAD, or
+       * - Privoxy is configured to enforce blocks, or
+       * - it's a CONNECT request and enforcing wouldn't work anyway.
+       */
+      if ((csp->config->feature_flags & RUNTIME_FEATURE_ENFORCE_BLOCKS)
+       || (0 == strcmpic(csp->http->gpc, "connect")))
 #endif /* ndef FEATURE_FORCE_LOAD */
       {
          err = map_block_killer(exports, "force-support");
@@ -1021,6 +1071,7 @@ struct http_response *block_url(struct client_state *csp)
          return cgi_error_memory();
       }
    }
+   rsp->reason = RSP_REASON_BLOCKED;
 
    return finish_http_response(csp, rsp);
 
@@ -1144,10 +1195,22 @@ struct http_response *trust_url(struct client_state *csp)
    }
 
    /*
-    * Export the force prefix or the force conditional block killer
+    * Export the force conditional block killer if
+    *
+    * - Privoxy was compiled without FEATURE_FORCE_LOAD, or
+    * - Privoxy is configured to enforce blocks, or
+    * - it's a CONNECT request and enforcing wouldn't work anyway.
     */
 #ifdef FEATURE_FORCE_LOAD
-   err = map(exports, "force-prefix", 1, FORCE_PREFIX, 1);
+   if ((csp->config->feature_flags & RUNTIME_FEATURE_ENFORCE_BLOCKS)
+    || (0 == strcmpic(csp->http->gpc, "connect")))
+   {
+      err = map_block_killer(exports, "force-support");
+   }
+   else
+   {
+      err = map(exports, "force-prefix", 1, FORCE_PREFIX, 1);
+   }
 #else /* ifndef FEATURE_FORCE_LOAD */
    err = map_block_killer(exports, "force-support");
 #endif /* ndef FEATURE_FORCE_LOAD */
@@ -1168,6 +1231,7 @@ struct http_response *trust_url(struct client_state *csp)
       free_http_response(rsp);
       return cgi_error_memory();
    }
+   rsp->reason = RSP_REASON_UNTRUSTED;
 
    return finish_http_response(csp, rsp);
 }
@@ -1470,7 +1534,9 @@ struct http_response *redirect_url(struct client_state *csp)
             free_http_response(rsp);
             return cgi_error_memory();
          }
+         rsp->reason = RSP_REASON_REDIRECTED;
          freez(new_url);
+
          return finish_http_response(csp, rsp);
       }
    }
@@ -1660,6 +1726,7 @@ int is_untrusted_url(const struct client_state *csp)
          return 0;
       }
    }
+
    return 1;
 }
 #endif /* def FEATURE_TRUST */
@@ -1753,22 +1820,29 @@ char *pcrs_filter_response(struct client_state *csp)
     * uncompress it first, adjusting size and iob->eod.
     * Note that decompression occurs after de-chunking.
     */
-   if (csp->content_type & CT_GZIP || csp->content_type & CT_DEFLATE)
+   if (csp->content_type & (CT_GZIP | CT_DEFLATE))
    {
       /* Notice that we at least tried to decompress. */
       if (JB_ERR_OK != decompress_iob(csp))
       {
          /*
           * We failed to decompress the data; there's no point
-          * in continuing since we can't filter. This is
-          * slightly tricky because we need to remember not to
-          * modify the Content-Encoding header later; using
-          * CT_TABOO flag is a kludge for this purpose.
+          * in continuing since we can't filter.
+          *
+          * XXX: Actually the Accept-Encoding header may
+          * just be incorrect in which case we could continue
+          * with filtering.
+          *
+          * Unset CT_GZIP and CT_DEFLATE to remember not
+          * to modify the Content-Encoding header later.
           */
-          csp->content_type |= CT_TABOO;
+          csp->content_type &= ~CT_GZIP;
+          csp->content_type &= ~CT_DEFLATE;
           return(NULL);
       }
-      log_error(LOG_LEVEL_RE_FILTER, "Decompressing successful");
+      log_error(LOG_LEVEL_RE_FILTER,
+         "Decompression successful. Old size: %d, new size: %d.",
+         size, csp->iob->eod - csp->iob->cur);
 
       /*
        * Decompression gives us a completely new iob,
@@ -1805,6 +1879,12 @@ char *pcrs_filter_response(struct client_state *csp)
     */
    for (b = fl->f; b; b = b->next)
    {
+      if (b->type != FT_CONTENT_FILTER)
+      {
+         /* Skip header filters */
+         continue;
+      }
+
       for (filtername = csp->action->multi[ACTION_MULTI_FILTER]->first;
            filtername ; filtername = filtername->next)
       {
@@ -1866,7 +1946,7 @@ char *pcrs_filter_response(struct client_state *csp)
             }
 
             log_error(LOG_LEVEL_RE_FILTER,
-               "re_filtering %s%s (size %d) with filter %s produced %d hits (new size %d).",
+               "filtering %s%s (size %d) with \'%s\' produced %d hits (new size %d).",
                csp->http->hostport, csp->http->path, prev_size, b->name, current_hits, size);
 
             hits += current_hits;
@@ -2277,6 +2357,8 @@ struct http_response *direct_response(struct client_state *csp)
                }
 
                rsp->is_static = 1;
+               rsp->reason = RSP_REASON_UNSUPPORTED;
+
                return(finish_http_response(csp, rsp));
             }
          }