Rebuild HTML docs for 3.0.22 UNSTABLE
[privoxy.git] / filters.c
index 0b643a3..fcca266 100644 (file)
--- a/filters.c
+++ b/filters.c
@@ -1,4 +1,4 @@
-const char filters_rcs[] = "$Id: filters.c,v 1.170 2012/03/09 17:55:50 fabiankeil Exp $";
+const char filters_rcs[] = "$Id: filters.c,v 1.179 2013/12/24 13:32:51 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/filters.c,v $
@@ -200,10 +200,6 @@ static int match_sockaddr(const struct sockaddr_storage *network,
       netmask_addr += 12;
       addr_len = 4;
    }
-   else if (network->ss_family != address->ss_family)
-   {
-      return 0;
-   }
 
    /* XXX: Port check is signaled in netmask */
    if (*netmask_port && *network_port != *address_port)
@@ -785,8 +781,8 @@ struct http_response *trust_url(struct client_state *csp)
    struct map * exports;
    char buf[BUFFER_SIZE];
    char *p;
-   struct url_spec **tl;
-   struct url_spec *t;
+   struct pattern_spec **tl;
+   struct pattern_spec *t;
    jb_err err;
 
    /*
@@ -1088,6 +1084,11 @@ char *get_last_url(char *subject, const char *redirect_mode)
 
    if (0 == strcmpic(redirect_mode, "check-decoded-url") && strchr(subject, '%'))
    {  
+      char *url_segment = NULL;
+      char **url_segments;
+      size_t max_segments;
+      int segments;
+
       log_error(LOG_LEVEL_REDIRECTS,
          "Checking \"%s\" for encoded redirects.", subject);
 
@@ -1097,15 +1098,12 @@ char *get_last_url(char *subject, const char *redirect_mode)
        * go backwards through the segments, URL-decode them
        * and look for a URL in the decoded result.
        * 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.
        */
-      size_t max_segments = strlen(subject) / 2;
-      char **url_segments = malloc(max_segments * sizeof(char *));
-      int segments;
+      max_segments = strlen(subject) / 2;
+      url_segments = malloc(max_segments * sizeof(char *));
 
       if (NULL == url_segments)
       {
@@ -1115,7 +1113,7 @@ char *get_last_url(char *subject, const char *redirect_mode)
          return NULL;
       }
 
-      segments = ssplit(subject, "?&", url_segments, max_segments, 1, 1);
+      segments = ssplit(subject, "?&", url_segments, max_segments);
 
       while (segments-- > 0)
       {
@@ -1411,7 +1409,7 @@ int is_untrusted_url(const struct client_state *csp)
 {
    struct file_list *fl;
    struct block_spec *b;
-   struct url_spec **trusted_url;
+   struct pattern_spec **trusted_url;
    struct http_request rhttp[1];
    const char * referer;
    jb_err err;
@@ -1527,6 +1525,66 @@ int is_untrusted_url(const struct client_state *csp)
 #endif /* def FEATURE_TRUST */
 
 
+/*********************************************************************
+ *
+ * Function    :  get_filter
+ *
+ * Description :  Get a filter with a given name and type.
+ *                Note that taggers are filters, too.
+ *
+ * Parameters  :
+ *          1  :  csp = Current client state (buffers, headers, etc...)
+ *          2  :  requested_name = Name of the content filter to get
+ *          3  :  requested_type = Type of the filter to tagger to lookup
+ *
+ * Returns     :  A pointer to the requested filter
+ *                or NULL if the filter wasn't found
+ *
+ *********************************************************************/
+struct re_filterfile_spec *get_filter(const struct client_state *csp,
+                                      const char *requested_name,
+                                      enum filter_type requested_type)
+{
+   int i;
+   struct re_filterfile_spec *b;
+   struct file_list *fl;
+
+   for (i = 0; i < MAX_AF_FILES; i++)
+   {
+     fl = csp->rlist[i];
+     if ((NULL == fl) || (NULL == fl->f))
+     {
+        /*
+         * Either there are no filter files left or this
+         * filter file just contains no valid filters.
+         *
+         * Continue to be sure we don't miss valid filter
+         * files that are chained after empty or invalid ones.
+         */
+        continue;
+     }
+
+     for (b = fl->f; b != NULL; b = b->next)
+     {
+        if (b->type != requested_type)
+        {
+           /* The callers isn't interested in this filter type. */
+           continue;
+        }
+        if (strcmp(b->name, requested_name) == 0)
+        {
+           /* The requested filter has been found. Abort search. */
+           return b;
+        }
+     }
+   }
+
+   /* No filter with the given name and type exists. */
+   return NULL;
+
+}
+
+
 /*********************************************************************
  *
  * Function    :  pcrs_filter_response
@@ -1545,14 +1603,12 @@ int is_untrusted_url(const struct client_state *csp)
 static char *pcrs_filter_response(struct client_state *csp)
 {
    int hits = 0;
-   int i;
    size_t size, prev_size;
 
    char *old = NULL;
    char *new = NULL;
    pcrs_job *job;
 
-   struct file_list *fl;
    struct re_filterfile_spec *b;
    struct list_entry *filtername;
 
@@ -1574,108 +1630,87 @@ static char *pcrs_filter_response(struct client_state *csp)
    size = (size_t)(csp->iob->eod - csp->iob->cur);
    old = csp->iob->cur;
 
-   for (i = 0; i < MAX_AF_FILES; i++)
-   {
-     fl = csp->rlist[i];
-     if ((NULL == fl) || (NULL == fl->f))
-     {
-        /*
-         * Either there are no filter files
-         * left, or this filter file just
-         * contains no valid filters.
-         *
-         * Continue to be sure we don't miss
-         * valid filter files that are chained
-         * after empty or invalid ones.
-         */
-        continue;
-     }
    /*
     * For all applying +filter actions, look if a filter by that
     * name exists and if yes, execute it's pcrs_joblist on the
     * buffer.
     */
-   for (b = fl->f; b; b = b->next)
+   for (filtername = csp->action->multi[ACTION_MULTI_FILTER]->first;
+        filtername != NULL; filtername = filtername->next)
    {
-      if (b->type != FT_CONTENT_FILTER)
+      int current_hits = 0; /* Number of hits caused by this filter */
+      int job_number   = 0; /* Which job we're currently executing  */
+      int job_hits     = 0; /* How many hits the current job caused */
+      pcrs_job *joblist;
+
+      b = get_filter(csp, filtername->str, FT_CONTENT_FILTER);
+      if (b == NULL)
       {
-         /* Skip header filters */
          continue;
       }
 
-      for (filtername = csp->action->multi[ACTION_MULTI_FILTER]->first;
-           filtername ; filtername = filtername->next)
-      {
-         if (strcmp(b->name, filtername->str) == 0)
-         {
-            int current_hits = 0; /* Number of hits caused by this filter */
-            int job_number   = 0; /* Which job we're currently executing  */
-            int job_hits     = 0; /* How many hits the current job caused */
-            pcrs_job *joblist = b->joblist;
+      joblist = b->joblist;
 
-            if (b->dynamic) joblist = compile_dynamic_pcrs_job_list(csp, b);
+      if (b->dynamic) joblist = compile_dynamic_pcrs_job_list(csp, b);
 
-            if (NULL == joblist)
-            {
-               log_error(LOG_LEVEL_RE_FILTER, "Filter %s has empty joblist. Nothing to do.", b->name);
-               continue;
-            }
+      if (NULL == joblist)
+      {
+         log_error(LOG_LEVEL_RE_FILTER, "Filter %s has empty joblist. Nothing to do.", b->name);
+         continue;
+      }
 
-            prev_size = size;
-            /* Apply all jobs from the joblist */
-            for (job = joblist; NULL != job; job = job->next)
-            {
-               job_number++;
-               job_hits = pcrs_execute(job, old, size, &new, &size);
+      prev_size = size;
+      /* Apply all jobs from the joblist */
+      for (job = joblist; NULL != job; job = job->next)
+      {
+         job_number++;
+         job_hits = pcrs_execute(job, old, size, &new, &size);
 
-               if (job_hits >= 0)
-               {
-                  /*
-                   * That went well. Continue filtering
-                   * and use the result of this job as
-                   * input for the next one.
-                   */
-                  current_hits += job_hits;
-                  if (old != csp->iob->cur)
-                  {
-                     freez(old);
-                  }
-                  old = new;
-               }
-               else
-               {
-                  /*
-                   * This job caused an unexpected error. Inform the user
-                   * and skip the rest of the jobs in this filter. We could
-                   * continue with the next job, but usually the jobs
-                   * depend on each other or are similar enough to
-                   * fail for the same reason.
-                   *
-                   * At the moment our pcrs expects the error codes of pcre 3.4,
-                   * but newer pcre versions can return additional error codes.
-                   * As a result pcrs_strerror()'s error message might be
-                   * "Unknown error ...", therefore we print the numerical value
-                   * as well.
-                   *
-                   * XXX: Is this important enough for LOG_LEVEL_ERROR or
-                   * should we use LOG_LEVEL_RE_FILTER instead?
-                   */
-                  log_error(LOG_LEVEL_ERROR, "Skipped filter \'%s\' after job number %u: %s (%d)",
-                     b->name, job_number, pcrs_strerror(job_hits), job_hits);
-                  break;
-               }
+         if (job_hits >= 0)
+         {
+            /*
+             * That went well. Continue filtering
+             * and use the result of this job as
+             * input for the next one.
+             */
+            current_hits += job_hits;
+            if (old != csp->iob->cur)
+            {
+               freez(old);
             }
+            old = new;
+         }
+         else
+         {
+            /*
+             * This job caused an unexpected error. Inform the user
+             * and skip the rest of the jobs in this filter. We could
+             * continue with the next job, but usually the jobs
+             * depend on each other or are similar enough to
+             * fail for the same reason.
+             *
+             * At the moment our pcrs expects the error codes of pcre 3.4,
+             * but newer pcre versions can return additional error codes.
+             * As a result pcrs_strerror()'s error message might be
+             * "Unknown error ...", therefore we print the numerical value
+             * as well.
+             *
+             * XXX: Is this important enough for LOG_LEVEL_ERROR or
+             * should we use LOG_LEVEL_RE_FILTER instead?
+             */
+            log_error(LOG_LEVEL_ERROR, "Skipped filter \'%s\' after job number %u: %s (%d)",
+               b->name, job_number, pcrs_strerror(job_hits), job_hits);
+            break;
+         }
+      }
 
-            if (b->dynamic) pcrs_free_joblist(joblist);
+      if (b->dynamic) pcrs_free_joblist(joblist);
 
-            log_error(LOG_LEVEL_RE_FILTER,
-               "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);
+      log_error(LOG_LEVEL_RE_FILTER,
+         "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;
-         }
-      }
-   }
+      hits += current_hits;
    }
 
    /*
@@ -1690,7 +1725,7 @@ static char *pcrs_filter_response(struct client_state *csp)
 
    csp->flags |= CSP_FLAG_MODIFIED;
    csp->content_length = size;
-   IOB_RESET(csp);
+   clear_iob(csp->iob);
 
    return(new);
 
@@ -2128,7 +2163,7 @@ const static struct forward_spec *get_forward_override_settings(struct client_st
       return NULL;
    }
 
-   vec_count = ssplit(forward_settings, " \t", vec, SZ(vec), 1, 1);
+   vec_count = ssplit(forward_settings, " \t", vec, SZ(vec));
    if ((vec_count == 2) && !strcasecmp(vec[0], "forward"))
    {
       fwd->type = SOCKS_NONE;
@@ -2156,6 +2191,11 @@ const static struct forward_spec *get_forward_override_settings(struct client_st
          fwd->type = SOCKS_5;
          socks_proxy = vec[1];
       }
+      else if (!strcasecmp(vec[0], "forward-socks5t"))
+      {
+         fwd->type = SOCKS_5T;
+         socks_proxy = vec[1];
+      }
 
       if (NULL != socks_proxy)
       {
@@ -2208,7 +2248,7 @@ const static struct forward_spec *get_forward_override_settings(struct client_st
 const struct forward_spec *forward_url(struct client_state *csp,
                                        const struct http_request *http)
 {
-   static const struct forward_spec fwd_default[1] = { FORWARD_SPEC_INITIALIZER };
+   static const struct forward_spec fwd_default[1]; /* Zero'ed due to being static. */
    struct forward_spec *fwd = csp->config->forward;
 
    if (csp->action->flags & ACTION_FORWARD_OVERRIDE)