Fix sorting.
[privoxy.git] / parsers.c
index 6bb3182..77f54af 100644 (file)
--- a/parsers.c
+++ b/parsers.c
@@ -1,4 +1,4 @@
-const char parsers_rcs[] = "$Id: parsers.c,v 1.131 2008/05/20 20:13:30 fabiankeil Exp $";
+const char parsers_rcs[] = "$Id: parsers.c,v 1.140 2008/09/12 17:51:43 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/parsers.c,v $
@@ -44,6 +44,39 @@ const char parsers_rcs[] = "$Id: parsers.c,v 1.131 2008/05/20 20:13:30 fabiankei
  *
  * Revisions   :
  *    $Log: parsers.c,v $
+ *    Revision 1.140  2008/09/12 17:51:43  fabiankeil
+ *    - A few style fixes.
+ *    - Remove a pointless cast.
+ *
+ *    Revision 1.139  2008/09/04 08:13:58  fabiankeil
+ *    Prepare for critical sections on Windows by adding a
+ *    layer of indirection before the pthread mutex functions.
+ *
+ *    Revision 1.138  2008/08/30 12:03:07  fabiankeil
+ *    Remove FEATURE_COOKIE_JAR.
+ *
+ *    Revision 1.137  2008/05/30 15:50:08  fabiankeil
+ *    Remove questionable micro-optimizations
+ *    whose usefulness has never been measured.
+ *
+ *    Revision 1.136  2008/05/26 16:02:24  fabiankeil
+ *    s@Insufficent@Insufficient@
+ *
+ *    Revision 1.135  2008/05/21 20:12:10  fabiankeil
+ *    The whole point of strclean() is to modify the
+ *    first parameter, so don't mark it immutable,
+ *    even though the compiler lets us get away with it.
+ *
+ *    Revision 1.134  2008/05/21 19:27:25  fabiankeil
+ *    As the wafer actions are gone, we can stop including encode.h.
+ *
+ *    Revision 1.133  2008/05/21 15:50:47  fabiankeil
+ *    Ditch cast from (char **) to (char **).
+ *
+ *    Revision 1.132  2008/05/21 15:47:14  fabiankeil
+ *    Streamline sed()'s prototype and declare
+ *    the header parse and add structures static.
+ *
  *    Revision 1.131  2008/05/20 20:13:30  fabiankeil
  *    Factor update_server_headers() out of sed(), ditch the
  *    first_run hack and make server_patterns_light static.
@@ -829,7 +862,6 @@ const char parsers_rcs[] = "$Id: parsers.c,v 1.131 2008/05/20 20:13:30 fabiankei
 #endif /* def FEATURE_PTHREAD */
 #include "list.h"
 #include "parsers.h"
-#include "encode.h"
 #include "ssplit.h"
 #include "errlog.h"
 #include "jbsockets.h"
@@ -894,6 +926,7 @@ static jb_err server_content_disposition(struct client_state *csp, char **header
 
 static jb_err client_host_adder       (struct client_state *csp);
 static jb_err client_xtra_adder       (struct client_state *csp);
+static jb_err client_x_forwarded_for_adder(struct client_state *csp);
 static jb_err connection_close_adder  (struct client_state *csp); 
 
 static jb_err create_forged_referrer(char **header, const char *hostport);
@@ -955,11 +988,12 @@ static const struct parsers server_patterns[] = {
    { "Last-Modified:",           14, server_last_modified },
    { "*",                         0, crunch_server_header },
    { "*",                         0, filter_header },
-   { NULL, 0, NULL }
+   { NULL,                        0, NULL }
 };
 
 static const add_header_func_ptr add_client_headers[] = {
    client_host_adder,
+   client_x_forwarded_for_adder,
    client_xtra_adder,
    /* Temporarily disabled:    client_accept_encoding_adder, */
    connection_close_adder,
@@ -1672,10 +1706,10 @@ static char *get_header_line(struct iob *iob)
    if (*ret == '\0')
    {
       freez(ret);
-      return(NULL);
+      return NULL;
    }
 
-   return(ret);
+   return ret;
 
 }
 
@@ -1716,9 +1750,9 @@ char *get_header_value(const struct list *header_list, const char *header_name)
             /*
              * Found: return pointer to start of value
              */
-            ret = (char *) (cur_entry->str + length);
+            ret = cur_entry->str + length;
             while (*ret && ijb_isspace(*ret)) ret++;
-            return(ret);
+            return ret;
          }
       }
    }
@@ -1813,7 +1847,7 @@ jb_err sed(struct client_state *csp, int filter_server_headers)
          if ((strncmpic(p->str, v->str, v->len) == 0) ||
              (v->len == CHECK_EVERY_HEADER_REMAINING))
          {
-            err = v->parser(csp, (char **)&(p->str));
+            err = v->parser(csp, &(p->str));
          }
       }
       v++;
@@ -1853,7 +1887,7 @@ jb_err update_server_headers(struct client_state *csp)
 #ifdef FEATURE_ZLIB
       { "Content-Encoding:",  17, server_content_encoding },
 #endif /* def FEATURE_ZLIB */
-      { NULL, 0, NULL }
+      { NULL,                  0, NULL }
    };
 
    if (strncmpic(csp->http->cmd, "HEAD", 4))
@@ -1941,7 +1975,7 @@ static jb_err header_tagger(struct client_state *csp, char *header)
    {
       log_error(LOG_LEVEL_ERROR, "Inconsistent configuration: "
          "tagging enabled, but no taggers available.");
-      return(JB_ERR_OK);
+      return JB_ERR_OK;
    }
 
    for (i = 0; i < MAX_AF_FILES; i++)
@@ -2159,7 +2193,7 @@ static jb_err filter_header(struct client_state *csp, char **header)
    {
       log_error(LOG_LEVEL_ERROR, "Inconsistent configuration: "
          "header filtering enabled, but no matching filters available.");
-      return(JB_ERR_OK);
+      return JB_ERR_OK;
    }
 
    for (i = 0; i < MAX_AF_FILES; i++)
@@ -2259,7 +2293,7 @@ static jb_err filter_header(struct client_state *csp, char **header)
       freez(*header);
    }
 
-   return(JB_ERR_OK);
+   return JB_ERR_OK;
 }
 
 
@@ -2823,7 +2857,7 @@ static jb_err server_last_modified(struct client_state *csp, char **header)
 
       if (*header == NULL)
       {
-         log_error(LOG_LEVEL_HEADER, "Insufficent memory. Last-Modified header got lost, boohoo.");  
+         log_error(LOG_LEVEL_HEADER, "Insufficient memory. Last-Modified header got lost, boohoo.");  
       }
       else
       {
@@ -2839,9 +2873,9 @@ static jb_err server_last_modified(struct client_state *csp, char **header)
 #ifdef HAVE_GMTIME_R
       timeptr = gmtime_r(&now, &gmt);
 #elif FEATURE_PTHREAD
-      pthread_mutex_lock(&gmtime_mutex);
+      privoxy_mutex_lock(&gmtime_mutex);
       timeptr = gmtime(&now);
-      pthread_mutex_unlock(&gmtime_mutex);
+      privoxy_mutex_unlock(&gmtime_mutex);
 #else
       timeptr = gmtime(&now);
 #endif
@@ -2869,9 +2903,9 @@ static jb_err server_last_modified(struct client_state *csp, char **header)
 #ifdef HAVE_GMTIME_R
             timeptr = gmtime_r(&last_modified, &gmt);
 #elif FEATURE_PTHREAD
-            pthread_mutex_lock(&gmtime_mutex);
+            privoxy_mutex_lock(&gmtime_mutex);
             timeptr = gmtime(&last_modified);
-            pthread_mutex_unlock(&gmtime_mutex);
+            privoxy_mutex_unlock(&gmtime_mutex);
 #else
             timeptr = gmtime(&last_modified);
 #endif
@@ -2882,21 +2916,19 @@ static jb_err server_last_modified(struct client_state *csp, char **header)
 
             if (*header == NULL)
             {
-               log_error(LOG_LEVEL_ERROR, "Insufficent memory, header crunched without replacement.");
+               log_error(LOG_LEVEL_ERROR, "Insufficient memory, header crunched without replacement.");
                return JB_ERR_MEMORY;  
             }
 
-            if (LOG_LEVEL_HEADER & debug) /* Save cycles if the user isn't interested. */
-            {
-               days    = rtime / (3600 * 24);
-               hours   = rtime / 3600 % 24;
-               minutes = rtime / 60 % 60;
-               seconds = rtime % 60;            
-
-               log_error(LOG_LEVEL_HEADER, "Randomized:  %s (added %d da%s %d hou%s %d minut%s %d second%s",
-                  *header, days, (days == 1) ? "y" : "ys", hours, (hours == 1) ? "r" : "rs",
-                  minutes, (minutes == 1) ? "e" : "es", seconds, (seconds == 1) ? ")" : "s)");
-            }
+            days    = rtime / (3600 * 24);
+            hours   = rtime / 3600 % 24;
+            minutes = rtime / 60 % 60;
+            seconds = rtime % 60;
+
+            log_error(LOG_LEVEL_HEADER,
+               "Randomized:  %s (added %d da%s %d hou%s %d minut%s %d second%s",
+               *header, days, (days == 1) ? "y" : "ys", hours, (hours == 1) ? "r" : "rs",
+               minutes, (minutes == 1) ? "e" : "es", seconds, (seconds == 1) ? ")" : "s)");
          }
          else
          {
@@ -3118,7 +3150,7 @@ static jb_err client_accept_language(struct client_state *csp, char **header)
       if (*header == NULL)
       {
          log_error(LOG_LEVEL_ERROR,
-            "Insufficent memory. Accept-Language header crunched without replacement.");  
+            "Insufficient memory. Accept-Language header crunched without replacement.");  
       }
       else
       {
@@ -3341,11 +3373,27 @@ static jb_err client_send_cookie(struct client_state *csp, char **header)
  *********************************************************************/
 jb_err client_x_forwarded(struct client_state *csp, char **header)
 {
-   if ((csp->action->flags & ACTION_HIDE_FORWARDED) != 0)
+   int block_header = (((csp->action->flags & ACTION_HIDE_FORWARDED) != 0)
+      || ((csp->action->flags & ACTION_CHANGE_X_FORWARDED_FOR) &&
+         (0 == strcmpic(csp->action->string[ACTION_STRING_CHANGE_X_FORWARDED_FOR], "block"))));
+
+   if (block_header)
    {
       freez(*header);
       log_error(LOG_LEVEL_HEADER, "crunched x-forwarded-for!");
    }
+   else if (0 == strcmpic(csp->action->string[ACTION_STRING_CHANGE_X_FORWARDED_FOR], "add"))
+   {
+      /* Save it so we can re-add it later */
+      freez(csp->x_forwarded_for);
+      csp->x_forwarded_for = *header;
+
+      /*
+       * Always set *header = NULL, since this information
+       * will be sent at the end of the header.
+       */
+      *header = NULL;
+   }
 
    return JB_ERR_OK;
 }
@@ -3567,9 +3615,9 @@ static jb_err client_if_modified_since(struct client_state *csp, char **header)
 #ifdef HAVE_GMTIME_R
             timeptr = gmtime_r(&tm, &gmt);
 #elif FEATURE_PTHREAD
-            pthread_mutex_lock(&gmtime_mutex);
+            privoxy_mutex_lock(&gmtime_mutex);
             timeptr = gmtime(&tm);
-            pthread_mutex_unlock(&gmtime_mutex);
+            privoxy_mutex_unlock(&gmtime_mutex);
 #else
             timeptr = gmtime(&tm);
 #endif
@@ -3581,20 +3629,19 @@ static jb_err client_if_modified_since(struct client_state *csp, char **header)
 
             if (*header == NULL)
             {
-               log_error(LOG_LEVEL_HEADER, "Insufficent memory, header crunched without replacement.");
+               log_error(LOG_LEVEL_HEADER, "Insufficient memory, header crunched without replacement.");
                return JB_ERR_MEMORY;  
             }
 
-            if (LOG_LEVEL_HEADER & debug) /* Save cycles if the user isn't interested. */
-            {
-               hours   = rtime / 3600;
-               minutes = rtime / 60 % 60;
-               seconds = rtime % 60;            
+            hours   = rtime / 3600;
+            minutes = rtime / 60 % 60;
+            seconds = rtime % 60;
 
-               log_error(LOG_LEVEL_HEADER, "Randomized:  %s (%s %d hou%s %d minut%s %d second%s",
-                  *header, (negative) ? "subtracted" : "added", hours, (hours == 1) ? "r" : "rs",
-                  minutes, (minutes == 1) ? "e" : "es", seconds, (seconds == 1) ? ")" : "s)");
-            }
+            log_error(LOG_LEVEL_HEADER,
+               "Randomized:  %s (%s %d hou%s %d minut%s %d second%s",
+               *header, (negative) ? "subtracted" : "added", hours,
+               (hours == 1) ? "r" : "rs", minutes, (minutes == 1) ? "e" : "es",
+               seconds, (seconds == 1) ? ")" : "s)");
          }
       }
    }
@@ -3829,6 +3876,54 @@ static jb_err client_xtra_adder(struct client_state *csp)
 }
 
 
+/*********************************************************************
+ *
+ * Function    :  client_x_forwarded_for_adder
+ *
+ * Description :  Used in the add_client_headers list.  Called from `sed'.
+ *
+ * Parameters  :
+ *          1  :  csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns     :  JB_ERR_OK on success, or
+ *                JB_ERR_MEMORY on out-of-memory error.
+ *
+ *********************************************************************/
+static jb_err client_x_forwarded_for_adder(struct client_state *csp)
+{
+   char *header = NULL;
+   jb_err err;
+
+   if (!((csp->action->flags & ACTION_CHANGE_X_FORWARDED_FOR) &&
+         (0 == strcmpic(csp->action->string[ACTION_STRING_CHANGE_X_FORWARDED_FOR], "add"))))
+   {
+      return JB_ERR_OK;
+   }
+
+   if (csp->x_forwarded_for)
+   {
+      header = strdup(csp->x_forwarded_for);
+      string_append(&header, ", ");
+   }
+   else
+   {
+      header = strdup("X-Forwarded-For: ");
+   }
+   string_append(&header, csp->ip_addr_str);
+
+   if (header == NULL)
+   {
+      return JB_ERR_MEMORY;
+   }
+
+   log_error(LOG_LEVEL_HEADER, "addh: %s", header);
+   err = enlist(csp->headers, header);
+   freez(header);
+
+   return err;
+}
+
+
 /*********************************************************************
  *
  * Function    :  connection_close_adder
@@ -3953,35 +4048,8 @@ static jb_err server_set_cookie(struct client_state *csp, char **header)
 {
    time_t now;
    time_t cookie_time; 
-   struct tm tm_now; 
-   time(&now);
 
-#ifdef FEATURE_COOKIE_JAR
-   if (csp->config->jar)
-   {
-      /*
-       * Write timestamp into outbuf.
-       *
-       * Complex because not all OSs have tm_gmtoff or
-       * the %z field in strftime()
-       */
-      char tempbuf[ BUFFER_SIZE ];
-#ifdef HAVE_LOCALTIME_R
-      tm_now = *localtime_r(&now, &tm_now);
-#elif FEATURE_PTHREAD
-      pthread_mutex_lock(&localtime_mutex);
-      tm_now = *localtime (&now);
-      pthread_mutex_unlock(&localtime_mutex);
-#else
-      tm_now = *localtime (&now);
-#endif
-      strftime(tempbuf, BUFFER_SIZE-6, "%b %d %H:%M:%S ", &tm_now); 
-
-      /* strlen("set-cookie: ") = 12 */
-      fprintf(csp->config->jar, "%s %s\t%s\n", tempbuf, csp->http->host, *header + 12);
-   }
-#endif /* def FEATURE_COOKIE_JAR */
+   time(&now);
 
    if ((csp->action->flags & ACTION_NO_COOKIE_SET) != 0)
    {
@@ -4145,7 +4213,7 @@ static jb_err server_set_cookie(struct client_state *csp, char **header)
  * Returns     :  Number of eliminations
  *
  *********************************************************************/
-int strclean(const char *string, const char *substring)
+int strclean(char *string, const char *substring)
 {
    int hits = 0;
    size_t len;