Split filter-headers{} into filter-client-headers{}
[privoxy.git] / parsers.c
index da4f317..63c9e3d 100644 (file)
--- a/parsers.c
+++ b/parsers.c
@@ -1,4 +1,4 @@
-const char parsers_rcs[] = "$Id: parsers.c,v 1.59 2006/08/03 02:46:41 david__schmidt Exp $";
+const char parsers_rcs[] = "$Id: parsers.c,v 1.60 2006/08/12 03:54:37 david__schmidt Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/parsers.c,v $
@@ -40,6 +40,9 @@ const char parsers_rcs[] = "$Id: parsers.c,v 1.59 2006/08/03 02:46:41 david__sch
  *
  * Revisions   :
  *    $Log: parsers.c,v $
+ *    Revision 1.60  2006/08/12 03:54:37  david__schmidt
+ *    Windows service integration
+ *
  *    Revision 1.59  2006/08/03 02:46:41  david__schmidt
  *    Incorporate Fabian Keil's patch work:\rhttp://www.fabiankeil.de/sourcecode/privoxy/
  *
@@ -473,6 +476,10 @@ const char parsers_rcs[] = "$Id: parsers.c,v 1.59 2006/08/03 02:46:41 david__sch
 #include "miscutil.h"
 #include "list.h"
 
+#ifndef HAVE_STRPTIME
+#include "strptime.c"
+#endif
+
 const char parsers_h_rcs[] = PARSERS_H_VERSION;
 
 /* Fix a problem with Solaris.  There should be no effect on other
@@ -508,7 +515,7 @@ const struct parsers client_patterns[] = {
    { "if-none-match:",           14,   client_if_none_match },
    { "X-Filter:",                 9,   client_x_filter },
    { "*",                         0,   crunch_client_header },
-   { "*",                         0,   filter_header },
+   { "*",                         0,   filter_client_header },
    { NULL,                        0,   NULL }
 };
 
@@ -525,7 +532,7 @@ const struct parsers server_patterns[] = {
    { "content-disposition:",     20, server_content_disposition },
    { "Last-Modified:",           14, server_last_modified },
    { "*",                         0, crunch_server_header },
-   { "*",                         0, filter_header },
+   { "*",                         0, filter_server_header },
    { NULL, 0, NULL }
 };
 
@@ -868,6 +875,57 @@ char *sed(const struct parsers pats[],
 
 /* here begins the family of parser functions that reformat header lines */
 
+/*********************************************************************
+ *
+ * Function    :  filter_server_header
+ *
+ * Description :  Checks if server header filtering is enabled.
+ *                If it is, filter_header is called to do the work. 
+ *
+ * Parameters  :
+ *          1  :  csp = Current client state (buffers, headers, etc...)
+ *          2  :  header = On input, pointer to header to modify.
+ *                On output, pointer to the modified header, or NULL
+ *                to remove the header.  This function frees the
+ *                original string if necessary.
+ *
+ * Returns     :  JB_ERR_OK on success and always succeeds
+ *
+ *********************************************************************/
+jb_err filter_server_header(struct client_state *csp, char **header)
+{
+   if (csp->action->flags & ACTION_FILTER_SERVER_HEADERS)
+   {
+      filter_header(csp, header);
+   }
+   return(JB_ERR_OK);
+}
+
+/*********************************************************************
+ *
+ * Function    :  filter_client_header
+ *
+ * Description :  Checks if client header filtering is enabled.
+ *                If it is, filter_header is called to do the work. 
+ *
+ * Parameters  :
+ *          1  :  csp = Current client state (buffers, headers, etc...)
+ *          2  :  header = On input, pointer to header to modify.
+ *                On output, pointer to the modified header, or NULL
+ *                to remove the header.  This function frees the
+ *                original string if necessary.
+ *
+ * Returns     :  JB_ERR_OK on success and always succeeds
+ *
+ *********************************************************************/
+jb_err filter_client_header(struct client_state *csp, char **header)
+{
+   if (csp->action->flags & ACTION_FILTER_CLIENT_HEADERS)
+   {
+      filter_header(csp, header);
+   }
+   return(JB_ERR_OK);
+}
 
 /*********************************************************************
  *
@@ -910,10 +968,6 @@ jb_err filter_header(struct client_state *csp, char **header)
 # define INDEX_OR_NOT [i] 
 #endif
 
-   if (!(csp->action->flags & ACTION_FILTER_HEADERS))
-   {
-      return(JB_ERR_OK);
-   }
    log_error(LOG_LEVEL_RE_FILTER, "Entered filter_headers");
    /*
     * Need to check the set of re_filterfiles...
@@ -1407,7 +1461,7 @@ jb_err server_last_modified(struct client_state *csp, char **header)
    char buf[BUFFER_SIZE];
 
    char newheader[50];
-   struct tm *timeptr;
+   struct tm *timeptr = NULL;
    time_t now, last_modified;                  
    long int rtime;
    long int days, hours, minutes, seconds;
@@ -1456,14 +1510,13 @@ jb_err server_last_modified(struct client_state *csp, char **header)
       log_error(LOG_LEVEL_HEADER, "Randomizing: %s", *header);
       now = time(NULL);
       timeptr = gmtime(&now);
-      if (strptime(*header, "Last-Modified: %a, %d %b %Y %T", timeptr) == NULL)
+      if ( (last_modified = parse_header_time(*header, timeptr)) < 0 )
       {
           log_error(LOG_LEVEL_HEADER, "Couldn't parse: %s (crunching!)", *header);
           freez(*header);
       }
       else
       {
-         last_modified = timegm(timeptr);
          rtime = difftime(now, last_modified);
          if (rtime)
          {
@@ -1473,8 +1526,8 @@ jb_err server_last_modified(struct client_state *csp, char **header)
             rtime = rand() % rtime + 1; 
 #endif /* (ifndef _WIN32 || __OS2__) */
             last_modified += rtime;
-            timeptr = gmtime(&last_modified);
-            strftime(newheader, sizeof(newheader), "%a, %d %b %Y %T GMT", timeptr);
+            timeptr = localtime(&last_modified);
+            strftime(newheader, sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr);
             freez(*header);
             *header = strdup("Last-Modified: ");
             string_append(header, newheader);
@@ -2154,7 +2207,7 @@ jb_err client_host(struct client_state *csp, char **header)
 jb_err client_if_modified_since(struct client_state *csp, char **header)
 {
    char newheader[50];
-   struct tm *timeptr;
+   struct tm *timeptr = NULL;
    time_t tm = 0;                  
    const char *newval;
    time_t rtime;
@@ -2185,35 +2238,37 @@ jb_err client_if_modified_since(struct client_state *csp, char **header)
       }
       else /* add random value */
       {
-         /*
-          * tm must be initinalized to prevent segmentation faults.
-          */
-         timeptr = gmtime(&tm);
-         if (strptime(*header, "If-Modified-Since: %a, %d %b %Y %T", timeptr) == NULL)
+         if ( (tm = parse_header_time(*header, timeptr)) < 0 )
          {
             log_error(LOG_LEVEL_HEADER, "Couldn't parse: %s (crunching!)", *header);
             freez(*header);
          }
          else
          {
-            rtime = strtol(newval, &endptr, 0);
-
-            log_error(LOG_LEVEL_HEADER, "Randomizing: %s (random range: %d hou%s)",
-               *header, rtime, (rtime == 1 || rtime == -1) ? "r": "rs");
-
-            rtime *= 3600;
+            rtime = (time_t) strtol(newval, &endptr, 0);
+            if(rtime)
+            {
+               log_error(LOG_LEVEL_HEADER, "Randomizing: %s (random range: %d hou%s)",
+                  *header, rtime, (rtime == 1 || rtime == -1) ? "r": "rs");
+               rtime *= 3600;
 #if !defined(_WIN32) && !defined(__OS2__)
-            rtime = random() % rtime
+               rtime = random() % rtime + 1
 #else
-            rtime = rand() % rtime
+               rtime = rand() % rtime + 1
 #endif /* (_WIN32 || __OS2__) */
-            if(newval[0] == '-')
+               if(newval[0] == '-')
+               {
+                  rtime *= -1;      
+               }
+            }
+            else
             {
-               rtime *= -1;      
+               log_error(LOG_LEVEL_ERROR, "Random range is 0. Assuming time transformation test.",
+                  *header);
             }
-            tm = timegm(timeptr) + rtime;
-            timeptr = gmtime(&tm);
-            strftime(newheader, sizeof(newheader), "%a, %d %b %Y %T GMT", timeptr);
+            tm += rtime;
+            timeptr = localtime(&tm);
+            strftime(newheader, sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr);
 
             freez(*header);
             *header = strdup("If-Modified-Since: ");
@@ -2759,6 +2814,37 @@ int strclean(const char *string, const char *substring)
 }
 #endif /* def FEATURE_FORCE_LOAD */
 
+/*********************************************************************
+ *
+ * Function    :  parse_header_time
+ *
+ * Description :  Transforms time inside a HTTP header into
+ *                the usual time format.
+ *
+ * Parameters  :
+ *          1  :  header = header to parse
+ *          2  :  timeptr = storage for the resulting time structure 
+ *
+ * Returns     :  Time in seconds since Unix epoch or -1 for failure.
+ *
+ *********************************************************************/
+time_t parse_header_time(char *header, struct tm *timeptr) {
+
+   char * timestring;
+   time_t tm;
+
+   tm = time(NULL);
+   timeptr = localtime(&tm);
+   /* Skipping header name */
+   timestring = strstr(header, ": ");
+   if (strptime(timestring, ": %a, %d %b %Y %H:%M:%S", timeptr) == NULL)
+   {
+      return(-1);
+   }
+   tm = mktime(timeptr);
+   return(tm);
+}
+
 
 /*
   Local Variables: