'/* inside comment' warning removed.
[privoxy.git] / parsers.c
index ff58e7d..7c12bea 100644 (file)
--- a/parsers.c
+++ b/parsers.c
@@ -1,4 +1,4 @@
-const char parsers_rcs[] = "$Id: parsers.c,v 1.5 2001/05/26 00:28:36 jongfoster Exp $";
+const char parsers_rcs[] = "$Id: parsers.c,v 1.10 2001/05/29 09:50:24 jongfoster Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/parsers.c,v $
@@ -11,7 +11,7 @@ const char parsers_rcs[] = "$Id: parsers.c,v 1.5 2001/05/26 00:28:36 jongfoster
  *                   `client_x_forwarded_adder', `client_xtra_adder',
  *                   `content_type', `crumble', `destroy_list', `enlist',
  *                   `flush_socket', `free_http_request', `get_header',
- *                   `list_to_text', `match', `parse_http_request', `sed',
+ *                   `list_to_text', `parse_http_request', `sed',
  *                   and `server_set_cookie'.
  *
  * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
@@ -41,6 +41,54 @@ const char parsers_rcs[] = "$Id: parsers.c,v 1.5 2001/05/26 00:28:36 jongfoster
  *
  * Revisions   :
  *    $Log: parsers.c,v $
+ *    Revision 1.10  2001/05/29 09:50:24  jongfoster
+ *    Unified blocklist/imagelist/permissionslist.
+ *    File format is still under discussion, but the internal changes
+ *    are (mostly) done.
+ *
+ *    Also modified interceptor behaviour:
+ *    - We now intercept all URLs beginning with one of the following
+ *      prefixes (and *only* these prefixes):
+ *        * http://i.j.b/
+ *        * http://ijbswa.sf.net/config/
+ *        * http://ijbswa.sourceforge.net/config/
+ *    - New interceptors "home page" - go to http://i.j.b/ to see it.
+ *    - Internal changes so that intercepted and fast redirect pages
+ *      are not replaced with an image.
+ *    - Interceptors now have the option to send a binary page direct
+ *      to the client. (i.e. ijb-send-banner uses this)
+ *    - Implemented show-url-info interceptor.  (Which is why I needed
+ *      the above interceptors changes - a typical URL is
+ *      "http://i.j.b/show-url-info?url=www.somesite.com/banner.gif".
+ *      The previous mechanism would not have intercepted that, and
+ *      if it had been intercepted then it then it would have replaced
+ *      it with an image.)
+ *
+ *    Revision 1.9  2001/05/28 17:26:33  jongfoster
+ *    Fixing segfault if last header was crunched.
+ *    Fixing Windows build (snprintf() is _snprintf() under Win32, but we
+ *    can use the cross-platform sprintf() instead.)
+ *
+ *    Revision 1.8  2001/05/27 22:17:04  oes
+ *
+ *    - re_process_buffer no longer writes the modified buffer
+ *      to the client, which was very ugly. It now returns the
+ *      buffer, which it is then written by chat.
+ *
+ *    - content_length now adjusts the Content-Length: header
+ *      for modified documents rather than crunch()ing it.
+ *      (Length info in csp->content_length, which is 0 for
+ *      unmodified documents)
+ *
+ *    - For this to work, sed() is called twice when filtering.
+ *
+ *    Revision 1.7  2001/05/27 13:19:06  oes
+ *    Patched Joergs solution for the content-length in.
+ *
+ *    Revision 1.6  2001/05/26 13:39:32  jongfoster
+ *    Only crunches Content-Length header if applying RE filtering.
+ *    Without this fix, Microsoft Windows Update wouldn't work.
+ *
  *    Revision 1.5  2001/05/26 00:28:36  jongfoster
  *    Automatic reloading of config file.
  *    Removed obsolete SIGHUP support (Unix) and Reload menu option (Win32).
@@ -182,6 +230,7 @@ const struct interceptors intercept_patterns[] = {
 #ifdef TRUST_FILES
    { "ij-untrusted-url",   15, ij_untrusted_url },
 #endif /* def TRUST_FILES */
+   { "show-url-info",      13, ijb_show_url_info },
    { NULL, 0, NULL }
 };
 
@@ -211,43 +260,6 @@ void (* const add_server_headers[])(struct client_state *) = {
 };
 
 
-/*********************************************************************
- *
- * Function    :  match
- *
- * Description :  Do a `strncmpic' on every pattern in pats.
- *
- * Parameters  :
- *          1  :  buf = a string to match to a list of patterns
- *          2  :  pats = list of strings to compare against buf.
- *
- * Returns     :  Return the matching "struct parsers *",
- *                or NULL if no pattern matches.
- *
- *********************************************************************/
-static const struct parsers *match(char *buf, const struct parsers *pats)
-{
-   const struct parsers *v;
-
-   if (buf == NULL)
-   {
-      /* hit me */
-      log_error(LOG_LEVEL_ERROR, "NULL parameter to match()");
-      return(NULL);
-   }
-
-   for (v = pats; v->str ; v++)
-   {
-      if (strncmpic(buf, v->str, v->len) == 0)
-      {
-         return(v);
-      }
-   }
-   return(NULL);
-
-}
-
-
 /*********************************************************************
  *
  * Function    :  flush_socket
@@ -551,17 +563,22 @@ char *sed(const struct parsers pats[], void (* const more_headers[])(struct clie
    char *hdr;
    void (* const *f)();
 
-   for (p = csp->headers->next; p ; p = p->next)
+   for (v = pats; v->str ; v++)
    {
-      log_error(LOG_LEVEL_HEADER, "scan: %s", p->str);
-
-      if ((v = match(p->str, pats)))
+      for (p = csp->headers->next; p ; p = p->next)
       {
-         hdr = v->parser(v, p->str, csp);
-         freez(p->str);
-         p->str = hdr;
-      }
+         /* Header crunch()ed in previous run? -> ignore */
+         if (p->str == NULL) continue;
+
+         if (v == pats) log_error(LOG_LEVEL_HEADER, "scan: %s", p->str);
 
+         if (strncmpic(p->str, v->str, v->len) == 0)
+         {
+            hdr = v->parser(v, p->str, csp);
+            freez(p->str);
+            p->str = hdr;
+         }
+      }
    }
 
    /* place any additional headers on the csp->headers list */
@@ -570,8 +587,13 @@ char *sed(const struct parsers pats[], void (* const more_headers[])(struct clie
       (*f)(csp);
    }
 
-   /* add the blank line at the end of the header */
-   enlist(csp->headers, "");
+   /* add the blank line at the end of the header, if necessary */
+   if ( (csp->headers->last == NULL)
+     || (csp->headers->last->str == NULL)
+     || (*csp->headers->last->str != '\0') )
+   {
+      enlist(csp->headers, "");
+   }
 
    hdr = list_to_text(csp->headers);
 
@@ -783,7 +805,7 @@ char *crumble(const struct parsers *v, char *s, struct client_state *csp)
  *
  * Function    :  content_type
  *
- * Description :  Is this a text/* or javascript MIME Type?
+ * Description :  Is this a text/.* or javascript MIME Type?
  *
  * Parameters  :
  *          1  :  v = ignored
@@ -805,6 +827,7 @@ char *content_type(const struct parsers *v, char *s, struct client_state *csp)
 }
 #endif /* defined(PCRS) || defined(KILLPOPUPS) */
 
+
 #ifdef PCRS
 /*********************************************************************
  *
@@ -823,11 +846,13 @@ char *content_type(const struct parsers *v, char *s, struct client_state *csp)
  *********************************************************************/
 char *content_length(const struct parsers *v, char *s, struct client_state *csp)
 {
-   if ((csp->permissions & PERMIT_RE_FILTER) != 0)
-   {
-      log_error(LOG_LEVEL_HEADER, "crunch!");
-      return(NULL);
-   }
+   if (csp->content_length != 0) /* Content has been modified */
+       {
+          s = (char *) zalloc(100);
+          sprintf(s, "Content-Length: %d", csp->content_length);
+               log_error(LOG_LEVEL_HEADER, "Adjust Content-Length to %d", csp->content_length);
+          return(s);
+       }
    else
    {
       return(strdup(s));
@@ -863,54 +888,55 @@ char *client_referrer(const struct parsers *v, char *s, struct client_state *csp
    strclean(s, FORCE_PREFIX);
 #endif /* def FORCE_LOAD */
 
+#ifdef TRUST_FILES\r
    csp->referrer = strdup(s);
+#endif /* def TRUST_FILES */\r
+
+   /*
+    * Check permissionsfile.  If we have allowed this site to get the
+    * referer, then send it and we're done.
+    */
+   if (csp->permissions & PERMIT_REFERER)
+   {
+      return(strdup(s));
+   }
 
-   if (csp->config->referrer == NULL)
+   /*
+    * Check configfile.  Are we blocking referer?
+    */
+   if ( (csp->config->referrer == NULL) 
+     || (*csp->config->referrer == '@') )
    {
       log_error(LOG_LEVEL_HEADER, "crunch!");
       return(NULL);
    }
 
+   /*
+    * Check configfile.  Are we always sending referer?
+    */
    if (*csp->config->referrer == '.')
    {
       return(strdup(s));
    }
 
-   if (*csp->config->referrer == '@')
-   {
-      if (csp->permissions & PERMIT_COOKIE_READ)
-      {
-         return(strdup(s));
-      }
-      else
-      {
-         log_error(LOG_LEVEL_HEADER, "crunch!");
-         return(NULL);
-      }
-   }
-
    /*
     * New option § or L: Forge a referer as http://[hostname:port of REQUEST]/
     * to fool stupid checks for in-site links
     */
-
    if (*csp->config->referrer == '§' || *csp->config->referrer == 'L')
    {
-      if (csp->permissions & PERMIT_COOKIE_READ)
-      {
-         return(strdup(s));
-      }
-      else
-      {
-         log_error(LOG_LEVEL_HEADER, "crunch+forge!");
-         s = strsav(NULL, "Referer: ");
-         s = strsav(s, "http://");
-         s = strsav(s, csp->http->hostport);
-         s = strsav(s, "/");
-         return(s);
-      }
+      log_error(LOG_LEVEL_HEADER, "crunch+forge!");
+      s = strsav(NULL, "Referer: ");
+      s = strsav(s, "http://");
+      s = strsav(s, csp->http->hostport);
+      s = strsav(s, "/");
+      return(s);
    }
 
+   /*
+    * We have a specific (fixed) referer we want to send.
+    */
+
    log_error(LOG_LEVEL_HEADER, "modified");
 
    s = strsav( NULL, "Referer: " );
@@ -961,7 +987,7 @@ char *client_uagent(const struct parsers *v, char *s, struct client_state *csp)
 
    if (*csp->config->uagent == '@')
    {
-      if (csp->permissions & PERMIT_COOKIE_READ)
+      if (csp->permissions & PERMIT_USER_AGENT)
       {
          return(strdup(s));
       }
@@ -1010,7 +1036,7 @@ char *client_ua(const struct parsers *v, char *s, struct client_state *csp)
 
    if (*csp->config->uagent == '@')
    {
-      if (csp->permissions & PERMIT_COOKIE_READ)
+      if (csp->permissions & PERMIT_USER_AGENT)
       {
          return(strdup(s));
       }