Adding action +no-cookies-keep
[privoxy.git] / parsers.c
index 46f1189..5445cc5 100644 (file)
--- a/parsers.c
+++ b/parsers.c
@@ -1,4 +1,4 @@
-const char parsers_rcs[] = "$Id: parsers.c,v 1.34 2001/10/07 18:50:55 oes Exp $";
+const char parsers_rcs[] = "$Id: parsers.c,v 1.40 2001/10/26 20:13:09 jongfoster Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/parsers.c,v $
@@ -18,10 +18,10 @@ const char parsers_rcs[] = "$Id: parsers.c,v 1.34 2001/10/07 18:50:55 oes Exp $"
  *                IJBSWA team.  http://ijbswa.sourceforge.net
  *
  *                Based on the Internet Junkbuster originally written
- *                by and Copyright (C) 1997 Anonymous Coders and 
+ *                by and Copyright (C) 1997 Anonymous Coders and
  *                Junkbusters Corporation.  http://www.junkbusters.com
  *
- *                This program is free software; you can redistribute it 
+ *                This program is free software; you can redistribute it
  *                and/or modify it under the terms of the GNU General
  *                Public License as published by the Free Software
  *                Foundation; either version 2 of the License, or (at
@@ -41,6 +41,33 @@ const char parsers_rcs[] = "$Id: parsers.c,v 1.34 2001/10/07 18:50:55 oes Exp $"
  *
  * Revisions   :
  *    $Log: parsers.c,v $
+ *    Revision 1.40  2001/10/26 20:13:09  jongfoster
+ *    ctype.h is needed in Windows, too.
+ *
+ *    Revision 1.39  2001/10/26 17:40:04  oes
+ *    Introduced get_header_value()
+ *    Removed http->user_agent, csp->referrer and csp->accept_types
+ *    Removed client_accept()
+ *
+ *    Revision 1.38  2001/10/25 03:40:48  david__schmidt
+ *    Change in porting tactics: OS/2's EMX porting layer doesn't allow multiple
+ *    threads to call select() simultaneously.  So, it's time to do a real, live,
+ *    native OS/2 port.  See defines for __EMX__ (the porting layer) vs. __OS2__
+ *    (native). Both versions will work, but using __OS2__ offers multi-threading.
+ *
+ *    Revision 1.37  2001/10/23 21:36:02  jongfoster
+ *    Documenting sed()'s error behaviou (doc change only)
+ *
+ *    Revision 1.36  2001/10/13 12:51:51  joergs
+ *    Removed client_host, (was only required for the old 2.0.2-11 http://noijb.
+ *    force-load), instead crumble Host: and add it (again) in client_host_adder
+ *    (in case we get a HTTP/1.0 request without Host: header and forward it to
+ *    a HTTP/1.1 server/proxy).
+ *
+ *    Revision 1.35  2001/10/09 22:39:21  jongfoster
+ *    assert.h is also required under Win32, so moving out of #ifndef _WIN32
+ *    block.
+ *
  *    Revision 1.34  2001/10/07 18:50:55  oes
  *    Added server_content_encoding, renamed server_transfer_encoding
  *
@@ -289,14 +316,14 @@ const char parsers_rcs[] = "$Id: parsers.c,v 1.34 2001/10/07 18:50:55 oes Exp $"
 #ifndef _WIN32
 #include <stdio.h>
 #include <sys/types.h>
-#include <stdlib.h>
-#include <ctype.h>
 #endif
 
+#include <stdlib.h>
+#include <ctype.h>
 #include <assert.h>
 #include <string.h>
 
-#ifndef _WIN32
+#if !defined(_WIN32) && !defined(__OS2__)
 #include <unistd.h>
 #endif
 
@@ -308,6 +335,7 @@ const char parsers_rcs[] = "$Id: parsers.c,v 1.34 2001/10/07 18:50:55 oes Exp $"
 #include "errlog.h"
 #include "jbsockets.h"
 #include "miscutil.h"
+#include "list.h"
 
 const char parsers_h_rcs[] = PARSERS_H_VERSION;
 
@@ -317,8 +345,8 @@ const char parsers_h_rcs[] = PARSERS_H_VERSION;
  * as an array index.  Therefore we need to make sure that high-bit
  * characters generate +ve values, and ideally we also want to make
  * the argument match the declared parameter type of "int".
- * 
- * Why did they write a character function that can't take a simple 
+ *
+ * Why did they write a character function that can't take a simple
  * "char" argument?  Doh!
  */
 #define ijb_isupper(__X) isupper((int)(unsigned char)(__X))
@@ -334,16 +362,11 @@ const struct parsers client_patterns[] = {
    { "x-forwarded-for:",         16,   client_x_forwarded },
    { "Accept-Encoding:",         16,   client_accept_encoding },
    { "TE:",                      3,    client_te },
-#if defined(FEATURE_IMAGE_DETECT_MSIE)
-   { "Accept:",                   7,   client_accept },
-#endif /* defined(FEATURE_IMAGE_DETECT_MSIE) */
-#ifdef FEATURE_FORCE_LOAD
-   { "Host:",                     5,   client_host },
-#endif /* def FEATURE_FORCE_LOAD */
+   { "Host:",                     5,   crumble },
 /* { "if-modified-since:",       18,   crumble }, */
    { "Keep-Alive:",              11,   crumble },
    { "connection:",              11,   crumble },
-   { "proxy-connection:",        17,   crumble },        
+   { "proxy-connection:",        17,   crumble },
    { NULL,                       0,    NULL }
 };
 
@@ -355,7 +378,7 @@ const struct parsers server_patterns[] = {
    { "Content-Type:",      13, server_content_type },
    { "Content-Length:",    15, server_content_length },
    { "Content-MD5:",       12, server_content_md5 },
-   { "Content-Encoding:",  17, server_content_encoding },   
+   { "Content-Encoding:",  17, server_content_encoding },
    { "Transfer-Encoding:", 18, server_transfer_coding },
    { "Keep-Alive:",        11, crumble },
    { NULL, 0, NULL }
@@ -363,17 +386,18 @@ const struct parsers server_patterns[] = {
 
 
 void (* const add_client_headers[])(struct client_state *) = {
+   client_host_adder,
    client_cookie_adder,
    client_x_forwarded_adder,
    client_xtra_adder,
    client_accept_encoding_adder,
-   connection_close_adder, 
+   connection_close_adder,
    NULL
 };
 
 
 void (* const add_server_headers[])(struct client_state *) = {
-   connection_close_adder, 
+   connection_close_adder,
    NULL
 };
 
@@ -534,6 +558,56 @@ char *get_header(struct client_state *csp)
 }
 
 
+/*********************************************************************
+ *
+ * Function    :  get_header_value
+ *
+ * Description :  Get the value of a given header from a chained list
+ *                of header lines or return NULL if no such header is
+ *                present in the list.
+ *
+ * Parameters  :
+ *          1  :  header_list = pointer to list
+ *          2  :  header_name = string with name of header to look for.
+ *                              Trailing colon required, capitalization
+ *                              doesn't matter.
+ *
+ * Returns     :  NULL if not found, else value of header
+ *
+ *********************************************************************/
+char *get_header_value(const struct list *header_list, const char *header_name)
+{
+   struct list_entry *cur_entry;
+   char *ret = NULL;
+   size_t length = 0;
+
+   assert(header_list);
+   assert(header_name);
+   length = strlen(header_name);
+
+   for (cur_entry = header_list->first; cur_entry ; cur_entry = cur_entry->next)
+   {
+      if (cur_entry->str)
+      {
+         if (!strncmpic(cur_entry->str, header_name, length))
+         {
+            /*
+             * Found: return pointer to start of value
+             */
+            ret = (char *) (cur_entry->str + length);
+            while (*ret && ijb_isspace(*ret)) ret++;
+            return(ret);
+         }
+      }
+   }
+
+   /* 
+    * Not found
+    */
+   return NULL;
+
+}
+
 /*********************************************************************
  *
  * Function    :  sed
@@ -552,7 +626,8 @@ char *get_header(struct client_state *csp)
  *                headers (client or server)
  *          3  :  csp = Current client state (buffers, headers, etc...)
  *
- * Returns     :  Single pointer to a fully formed header.
+ * Returns     :  Single pointer to a fully formed header, or NULL
+ *                on out-of-memory error.
  *
  *********************************************************************/
 char *sed(const struct parsers pats[], void (* const more_headers[])(struct client_state *), struct client_state *csp)
@@ -574,7 +649,7 @@ char *sed(const struct parsers pats[], void (* const more_headers[])(struct clie
          if (strncmpic(p->str, v->str, v->len) == 0)
          {
             hdr = v->parser(v, p->str, csp);
-            freez((char *)p->str); /* FIXME: Yuck! patching a list...*/
+            freez(p->str); /* FIXME: Yuck! patching a list...*/
             p->str = hdr;
          }
       }
@@ -588,7 +663,7 @@ char *sed(const struct parsers pats[], void (* const more_headers[])(struct clie
 
    hdr = list_to_text(csp->headers);
 
-   return(hdr);
+   return hdr;
 
 }
 
@@ -617,7 +692,6 @@ void free_http_request(struct http_request *http)
    freez(http->path);
    freez(http->ver);
    freez(http->host_ip_addr_str);
-   freez(http->user_agent);
 
 }
 
@@ -643,7 +717,7 @@ void parse_http_request(char *req, struct http_request *http, struct client_stat
    int n;
 
    memset(http, '\0', sizeof(*http));
-   http->cmd = strdup(req);  
+   http->cmd = strdup(req);
 
    buf = strdup(req);
    n = ssplit(buf, " \r\n", v, SZ(v), 1, 1);
@@ -703,7 +777,7 @@ void parse_http_request(char *req, struct http_request *http, struct client_stat
                *p = '\0';
                http->hostport = strdup(url);
             }
-            /* 
+            /*
              * Repair broken HTTP requests that don't contain a path
              */
             else
@@ -852,7 +926,7 @@ char *server_transfer_coding(const struct parsers *v, const char *s, struct clie
       csp->content_type = CT_TABOO;
    }
 
-   /* 
+   /*
     * Raise flag if body chunked
     */
    if (strstr(s, "chunked"))
@@ -860,7 +934,7 @@ char *server_transfer_coding(const struct parsers *v, const char *s, struct clie
       csp->flags |= CSP_FLAG_CHUNKED;
 
       /*
-       * If the body was modified, it has been 
+       * If the body was modified, it has been
        * de-chunked first, so adjust the header:
        */
       if (csp->flags & CSP_FLAG_MODIFIED)
@@ -1057,15 +1131,11 @@ char *client_referrer(const struct parsers *v, const char *s, struct client_stat
 #ifdef FEATURE_FORCE_LOAD
    /* Since the referrer can include the prefix even
     * even if the request itself is non-forced, we must
-    * clean it unconditionally 
+    * clean it unconditionally
     */
    strclean(s, FORCE_PREFIX);
 #endif /* def FEATURE_FORCE_LOAD */
 
-#ifdef FEATURE_TRUST
-   csp->referrer = strdup(s);
-#endif /* def FEATURE_TRUST */
-
    /*
     * Are we sending referer?
     */
@@ -1159,22 +1229,6 @@ char *client_uagent(const struct parsers *v, const char *s, struct client_state
    const char * newval;
    char * s2;
 
-   /* Save the client's User-Agent: value */
-   if (strlen(s) >= 12)
-   {
-      csp->http->user_agent = strdup(s + 12);
-   }
-
-#ifdef FEATURE_IMAGE_DETECT_MSIE
-   if (strstr (s, "MSIE "))
-   {
-      /* This is Microsoft Internet Explorer.
-       * Enable auto-detect.
-       */
-      csp->accept_types |= ACCEPT_TYPE_IS_MSIE;
-   }
-#endif /* def FEATURE_IMAGE_DETECT_MSIE */
-
    if ((csp->action->flags & ACTION_HIDE_USER_AGENT) == 0)
    {
       return(strdup(s));
@@ -1337,48 +1391,32 @@ char *client_x_forwarded(const struct parsers *v, const char *s, struct client_s
 
 }
 
-#if defined(FEATURE_IMAGE_DETECT_MSIE)
+/* the following functions add headers directly to the header list */
+
 /*********************************************************************
  *
- * Function    :  client_accept
+ * Function    :  client_host_adder
  *
- * Description :  Detect whether the client wants HTML or an image.
- *                Clients do not always make this information available
- *                in a sane way.  Always passes the header through
- *                the proxy unchanged.
+ * Description :  (re)adds the host header. Called from `sed'.
  *
  * Parameters  :
- *          1  :  v = Ignored.
- *          2  :  s = Header string.  Null terminated.
- *          3  :  csp = Current client state (buffers, headers, etc...)
+ *          1  :  csp = Current client state (buffers, headers, etc...)
  *
- * Returns     :  Duplicate of argument s.
+ * Returns     :  N/A
  *
  *********************************************************************/
-char *client_accept(const struct parsers *v, const char *s, struct client_state *csp)
+void client_host_adder(struct client_state *csp)
 {
-#ifdef FEATURE_IMAGE_DETECT_MSIE
-   if (strstr (s, "image/gif"))
-   {
-      /* Client will accept HTML.  If this seems counterintuitive,
-       * blame Microsoft. 
-       */
-      csp->accept_types |= ACCEPT_TYPE_MSIE_HTML;
-   }
-   else
-   {
-      csp->accept_types |= ACCEPT_TYPE_MSIE_IMAGE;
-   }
-#endif /* def FEATURE_IMAGE_DETECT_MSIE */
-
-   return(strdup(s));
-
-}
-#endif /* defined(FEATURE_IMAGE_DETECT_MSIE) */
+   char *p = NULL;
 
+   p = strsav(p, "Host: ");
+   p = strsav(p, csp->http->hostport);
 
+   log_error(LOG_LEVEL_HEADER, "addh: %s", p);
+   enlist(csp->headers, p);
 
-/* the following functions add headers directly to the header list */
+   freez(p);
+}
 
 
 /*********************************************************************
@@ -1571,7 +1609,7 @@ void connection_close_adder(struct client_state *csp)
 char *server_http(const struct parsers *v, const char *s, struct client_state *csp)
 {
    char *ret = strdup(s);
-   
+
    sscanf(ret, "HTTP/%*d.%*d %d", &(csp->http->status));
    if (csp->http->status == 206)
    {
@@ -1607,9 +1645,23 @@ char *server_http(const struct parsers *v, const char *s, struct client_state *c
 char *server_set_cookie(const struct parsers *v, const char *s, struct client_state *csp)
 {
 #ifdef FEATURE_COOKIE_JAR
+
+       /*
+       * Write timestamp into outbuf.
+       *
+       * Complex because not all OSs have tm_gmtoff or
+       * the %z field in strftime()
+       */
+       char tempbuf[ BUFFER_SIZE ];
+       time_t now; 
+       struct tm *tm_now; 
+       time (&now); 
+       tm_now = localtime (&now); 
+       strftime (tempbuf, BUFFER_SIZE-6, "%b %d %H:%M:%S ", tm_now); 
+    
    if (csp->config->jar)
    {
-      fprintf(csp->config->jar, "%s\t%s\n", csp->http->host, (s + v->len + 1));
+      fprintf(csp->config->jar, "%s %s\t%s\n", tempbuf, csp->http->host, (s + v->len + 1));
    }
 #endif /* def FEATURE_COOKIE_JAR */
 
@@ -1624,41 +1676,11 @@ char *server_set_cookie(const struct parsers *v, const char *s, struct client_st
 
 
 #ifdef FEATURE_FORCE_LOAD
-/*********************************************************************
- *
- * Function    :  client_host
- *
- * Description :  Clean the FORCE_PREFIX out of the 'host' http
- *                header, if we use force
- *
- * Parameters  :
- *          1  :  v = ignored
- *          2  :  s = header (from sed) to clean
- *          3  :  csp = Current client state (buffers, headers, etc...)
- *
- * Returns     :  A malloc'ed pointer to the cleaned host header 
- *
- *********************************************************************/
-char *client_host(const struct parsers *v, const char *s, struct client_state *csp)
-{
-   char *cleanhost = strdup(s);
-   if(csp->flags & CSP_FLAG_FORCED)
-   {
-      strclean(cleanhost, FORCE_PREFIX);
-   }
-   return(cleanhost);
-}
-#endif /* def FEATURE_FORCE_LOAD */
-#ifdef FEATURE_FORCE_LOAD 
 /*********************************************************************
  *
  * Function    :  strclean
  *
- * Description :  In-Situ-Eliminate all occurances of substring in 
+ * Description :  In-Situ-Eliminate all occurances of substring in
  *                string
  *
  * Parameters  :
@@ -1678,7 +1700,7 @@ int strclean(const char *string, const char *substring)
       p = pos + len;
       do
       {
-         *(p - len) = *p; 
+         *(p - len) = *p;
       }
       while (*p++ != '\0');