- Back to timegm() using GnuPG's replacement if necessary.
authorFabian Keil <fk@fabiankeil.de>
Thu, 17 Aug 2006 17:15:10 +0000 (17:15 +0000)
committerFabian Keil <fk@fabiankeil.de>
Thu, 17 Aug 2006 17:15:10 +0000 (17:15 +0000)
  Using mktime() and localtime() could add a on hour offset if
  the randomize factor was big enough to lead to a summer/wintertime
  switch.

- Removed now-useless Privoxy 3.0.3 compatibility glue.

- Moved randomization code into pick_from_range().

- Changed parse_header_time definition.
  time_t isn't guaranteed to be signed and
  if it isn't, -1 isn't available as error code.
  Changed some variable types in client_if_modified_since()
  because of the same reason.

miscutil.c
miscutil.h
parsers.c
parsers.h

index 5679ca2..1f6f0c4 100644 (file)
@@ -1,7 +1,7 @@
-const char miscutil_rcs[] = "$Id: miscutil.c,v 1.37.2.4 2003/12/01 14:45:14 oes Exp $";
+const char miscutil_rcs[] = "$Id: miscutil.c,v 1.39 2006/07/18 14:48:46 david__schmidt Exp $";
 /*********************************************************************
  *
- * File        :  $Source: /cvsroot/ijbswa/current/Attic/miscutil.c,v $
+ * File        :  $Source: /cvsroot/ijbswa/current/miscutil.c,v $
  *
  * Purpose     :  zalloc, hash_string, safe_strerror, strcmpic,
  *                strncmpic, chomp, and MinGW32 strdup
@@ -36,6 +36,10 @@ const char miscutil_rcs[] = "$Id: miscutil.c,v 1.37.2.4 2003/12/01 14:45:14 oes
  *
  * Revisions   :
  *    $Log: miscutil.c,v $
+ *    Revision 1.39  2006/07/18 14:48:46  david__schmidt
+ *    Reorganizing the repository: swapping out what was HEAD (the old 3.1 branch)
+ *    with what was really the latest development (the v_3_0_branch branch)
+ *
  *    Revision 1.37.2.4  2003/12/01 14:45:14  oes
  *    Fixed two more problems with wildcarding in simplematch()
  *
@@ -229,6 +233,10 @@ const char miscutil_rcs[] = "$Id: miscutil.c,v 1.37.2.4 2003/12/01 14:45:14 oes
 #include <ctype.h>
 #include <assert.h>
 
+#ifndef HAVE_TIMEGM
+#include <time.h>
+#endif /* #ifndef HAVE_TIMEGM */
+
 #include "project.h"
 #include "miscutil.h"
 #include "errlog.h"
@@ -1017,6 +1025,98 @@ char * make_path(const char * dir, const char * file)
 }
 
 
+/*********************************************************************
+ *
+ * Function    :  pick_from_range
+ *
+ * Description :  Pick a positive number out of a given range.
+ *                Should only be used if randomness would be nice,
+ *                but isn't really necessary.
+ *
+ * Parameters  :
+ *          1  :  range: Highest possible number to pick.
+ *
+ * Returns     :  Picked number. 
+ *
+ *********************************************************************/
+
+long int pick_from_range(long int range)
+{
+   long int number;
+#ifndef HAVE_RANDOM
+   unsigned int weak_seed;
+
+   weak_seed = (unsigned int)(time(NULL) | range);
+   srand(weak_seed);
+   /*
+    * Some rand implementations aren't that random and return mostly
+    * lower numbers. Low entropy doesn't matter for the header times, 
+    * but higher "random" factors are prefered.
+    */
+   number = (rand() * 12345) % (long int)(range + 1);
+   /* Overflows don't matter either, positive numbers do. */
+   if(number<0)
+   {
+      number*= -1;
+   }
+#else
+   number = random() % range + 1; 
+#endif /* (ifndef HAVE_RANDOM) */
+   return (number);
+}
+
+
+#ifndef HAVE_TIMEGM
+/*********************************************************************
+ *
+ * Function    :  timegm
+ *
+ * Description :  libc replacement function for the inverse of gmtime()
+ *                Copyright (C) 2004 Free Software Foundation, Inc.
+ *                Code copied from GnuPG with minor style changes.
+ *
+ * Parameters  :
+ *          1  :  tm: Broken-down time struct.
+ *
+ * Returns     :  tm converted into time_t seconds. 
+ *
+ *********************************************************************/
+
+time_t timegm(struct tm *tm)
+{
+   time_t answer;
+   char *zone;
+
+   zone=getenv("TZ");
+   putenv("TZ=UTC");
+   tzset();
+   answer=mktime(tm);
+   if(zone)
+   {
+      char *old_zone;
+
+      old_zone=malloc(3+strlen(zone)+1);
+      if(old_zone)
+      {
+         strcpy(old_zone,"TZ=");
+         strcat(old_zone,zone);
+         putenv(old_zone);     
+      }
+   }
+   else
+   {
+#ifdef HAVE_UNSETENV
+      unsetenv("TZ");
+#else
+      putenv("TZ");
+#endif
+   }
+   tzset();
+   return answer;
+}
+#endif /* (ifndef HAVE_TIMEGM) */
+
+
 /*
  * What follows is a portable snprintf routine, written by Mark Martinec.
  * See: http://www.ijs.si/software/snprintf/
index 9c1c5b3..01b3179 100644 (file)
@@ -1,9 +1,9 @@
 #ifndef MISCUTIL_H_INCLUDED
 #define MISCUTIL_H_INCLUDED
-#define MISCUTIL_H_VERSION "$Id: miscutil.h,v 1.21 2002/04/26 12:55:38 oes Exp $"
+#define MISCUTIL_H_VERSION "$Id: miscutil.h,v 1.23 2006/07/18 14:48:47 david__schmidt Exp $"
 /*********************************************************************
  *
- * File        :  $Source: /cvsroot/ijbswa/current/Attic/miscutil.h,v $
+ * File        :  $Source: /cvsroot/ijbswa/current/miscutil.h,v $
  *
  * Purpose     :  zalloc, hash_string, safe_strerror, strcmpic,
  *                strncmpic, and MinGW32 strdup functions.  These are
  *
  * Revisions   :
  *    $Log: miscutil.h,v $
+ *    Revision 1.23  2006/07/18 14:48:47  david__schmidt
+ *    Reorganizing the repository: swapping out what was HEAD (the old 3.1 branch)
+ *    with what was really the latest development (the v_3_0_branch branch)
+ *
  *    Revision 1.21  2002/04/26 12:55:38  oes
  *    New function string_toupper
  *
@@ -172,6 +176,8 @@ extern char *bindup(const char *string, size_t len);
 
 extern char *make_path(const char * dir, const char * file);
 
+long int pick_from_range(long int range);
+
 #ifdef __MINGW32__
 extern char *strdup(const char *s);
 #endif /* def __MINGW32__ */
@@ -180,6 +186,10 @@ extern char *strdup(const char *s);
 extern int snprintf(char *, size_t, const char *, /*args*/ ...);
 #endif /* def __OS2__ */
 
+#ifndef HAVE_TIMEGM
+time_t timegm(struct tm *tm);
+#endif /* ndef HAVE_TIMEGM */
+
 /* Revision control strings from this header and associated .c file */
 extern const char miscutil_rcs[];
 extern const char miscutil_h_rcs[];
index 317c8cd..fdd9f47 100644 (file)
--- a/parsers.c
+++ b/parsers.c
@@ -1,4 +1,4 @@
-const char parsers_rcs[] = "$Id: parsers.c,v 1.62 2006/08/14 08:58:42 fabiankeil Exp $";
+const char parsers_rcs[] = "$Id: parsers.c,v 1.63 2006/08/14 13:18:08 david__schmidt Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/parsers.c,v $
@@ -40,6 +40,9 @@ const char parsers_rcs[] = "$Id: parsers.c,v 1.62 2006/08/14 08:58:42 fabiankeil
  *
  * Revisions   :
  *    $Log: parsers.c,v $
+ *    Revision 1.63  2006/08/14 13:18:08  david__schmidt
+ *    OS/2 compilation compatibility fixups
+ *
  *    Revision 1.62  2006/08/14 08:58:42  fabiankeil
  *    Changed include from strptime.c to strptime.h
  *
@@ -970,20 +973,13 @@ jb_err filter_header(struct client_state *csp, char **header)
 
    int i, found_filters = 0;
 
-#ifndef  MAX_AF_FILES
-# define MAX_AF_FILES 1
-# define INDEX_OR_NOT
-#else
-# define INDEX_OR_NOT [i] 
-#endif
-
    log_error(LOG_LEVEL_RE_FILTER, "Entered filter_headers");
    /*
     * Need to check the set of re_filterfiles...
     */
    for (i = 0; i < MAX_AF_FILES; i++)
    {
-      fl = csp->rlist INDEX_OR_NOT;
+      fl = csp->rlist[i];
       if (NULL != fl)
       {
          if (NULL != fl->f)
@@ -1002,12 +998,12 @@ jb_err filter_header(struct client_state *csp, char **header)
 
    for (i = 0; i < MAX_AF_FILES; i++)
    {
-      fl = csp->rlist INDEX_OR_NOT;
+      fl = csp->rlist[i];
       if ((NULL == fl) || (NULL == fl->f))
          break;
       /*
        * For all applying +filter actions, look if a filter by that
-       * name exists and if yes, execute it's pcrs_joblist on the
+       * name exists and if yes, execute its pcrs_joblist on the
        * buffer.
        */
       for (b = fl->f; b; b = b->next)
@@ -1519,23 +1515,19 @@ 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 ( (last_modified = parse_header_time(*header, timeptr)) < 0 )
+      if ((timeptr = parse_header_time(*header, &last_modified)) == NULL)
       {
-          log_error(LOG_LEVEL_HEADER, "Couldn't parse: %s (crunching!)", *header);
-          freez(*header);
+         log_error(LOG_LEVEL_HEADER, "Couldn't parse: %s (crunching!)", *header);
+         freez(*header);
       }
       else
       {
          rtime = difftime(now, last_modified);
          if (rtime)
          {
-#if !defined(_WIN32) && !defined(__OS2__)
-            rtime = random() % rtime + 1; 
-#else
-            rtime = rand() % (long int)(rtime + 1);
-#endif /* (ifndef _WIN32 || __OS2__) */
+            rtime = pick_from_range(rtime);
             last_modified += rtime;
-            timeptr = localtime(&last_modified);
+            timeptr = gmtime(&last_modified);
             strftime(newheader, sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr);
             freez(*header);
             *header = strdup("Last-Modified: ");
@@ -1543,7 +1535,7 @@ 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, "Insufficent memory, header crunched without replacement.");
                return JB_ERR_MEMORY;  
             }
 
@@ -2219,8 +2211,8 @@ jb_err client_if_modified_since(struct client_state *csp, char **header)
    struct tm *timeptr = NULL;
    time_t tm = 0;                  
    const char *newval;
-   time_t rtime;
-   time_t hours, minutes, seconds;
+   long int rtime;
+   long int hours, minutes, seconds;
    int negative = 0;
    char * endptr;
    
@@ -2247,28 +2239,25 @@ jb_err client_if_modified_since(struct client_state *csp, char **header)
       }
       else /* add random value */
       {
-         if ( (tm = parse_header_time(*header, timeptr)) < 0 )
+         if ((timeptr = parse_header_time(*header, &tm)) == NULL)
          {
             log_error(LOG_LEVEL_HEADER, "Couldn't parse: %s (crunching!)", *header);
             freez(*header);
          }
          else
          {
-            rtime = (time_t) strtol(newval, &endptr, 0);
+            rtime = strtol(newval, &endptr, 0);
+            if(rtime < 0)
+            {
+                rtime *= -1; 
+                negative = 1;
+            }
             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 + 1; 
-#else
-               rtime = rand() % (long int)(rtime + 1);
-#endif /* (_WIN32 || __OS2__) */
-               if(newval[0] == '-')
-               {
-                  rtime *= -1;      
-               }
+               rtime = pick_from_range(rtime);
             }
             else
             {
@@ -2276,7 +2265,7 @@ jb_err client_if_modified_since(struct client_state *csp, char **header)
                   *header);
             }
             tm += rtime;
-            timeptr = localtime(&tm);
+            timeptr = gmtime(&tm);
             strftime(newheader, sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr);
 
             freez(*header);
@@ -2285,20 +2274,15 @@ 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, "Insufficent memory, header crunched without replacement.");
                return JB_ERR_MEMORY;  
             }
 
             if(LOG_LEVEL_HEADER & debug) /* Save cycles if the user isn't interested. */
             {
-               if(rtime < 0)
-               {
-                  rtime *= -1; 
-                  negative = 1;
-               }
-               hours   = (int)rtime / 3600 % 24;
-               minutes = (int)rtime / 60 % 60;
-               seconds = (int)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",
@@ -2832,26 +2816,30 @@ int strclean(const char *string, const char *substring)
  *
  * Parameters  :
  *          1  :  header = header to parse
- *          2  :  timeptr = storage for the resulting time structure 
+ *          2  :  tm = storage for the resulting time in seconds 
  *
- * Returns     :  Time in seconds since Unix epoch or -1 for failure.
+ * Returns     :  Time struct containing the header time, or
+ *                NULL in case of a parsing problem.
  *
  *********************************************************************/
-time_t parse_header_time(char *header, struct tm *timeptr) {
+struct tm *parse_header_time(char *header, time_t *tm) {
 
    char * timestring;
-   time_t tm;
-
-   tm = time(NULL);
-   timeptr = localtime(&tm);
+   struct tm * timeptr;
+   
+   *tm = 0;
+   timeptr = localtime(tm);
    /* Skipping header name */
    timestring = strstr(header, ": ");
    if (strptime(timestring, ": %a, %d %b %Y %H:%M:%S", timeptr) == NULL)
    {
-      return(-1);
+      timeptr = NULL;
+   }
+   else
+   {
+      *tm = timegm(timeptr);
    }
-   tm = mktime(timeptr);
-   return(tm);
+   return(timeptr);
 }
 
 
index c562c94..5e79aee 100644 (file)
--- a/parsers.h
+++ b/parsers.h
@@ -1,6 +1,6 @@
 #ifndef PARSERS_H_INCLUDED
 #define PARSERS_H_INCLUDED
-#define PARSERS_H_VERSION "$Id: parsers.h,v 1.29 2006/08/03 02:46:41 david__schmidt Exp $"
+#define PARSERS_H_VERSION "$Id: parsers.h,v 1.30 2006/08/14 08:25:19 fabiankeil Exp $"
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/parsers.h,v $
  *
  * Revisions   :
  *    $Log: parsers.h,v $
+ *    Revision 1.30  2006/08/14 08:25:19  fabiankeil
+ *    Split filter-headers{} into filter-client-headers{}
+ *    and filter-server-headers{}.
+ *    Added parse_header_time() to share some code.
+ *    Replaced timegm() with mktime().
+ *
  *    Revision 1.29  2006/08/03 02:46:41  david__schmidt
  *    Incorporate Fabian Keil's patch work:\rhttp://www.fabiankeil.de/sourcecode/privoxy/
  *
@@ -206,7 +212,7 @@ extern char *get_header(struct client_state *csp);
 extern char *get_header_value(const struct list *header_list, const char *header_name);
 extern char *sed(const struct parsers pats[], const add_header_func_ptr more_headers[], struct client_state *csp);
 extern void get_http_time(int time_offset, char *buf);
-time_t parse_header_time(char *header, struct tm *timeptr);
+struct tm *parse_header_time(char *header, time_t *tm);
 
 extern jb_err crumble                (struct client_state *csp, char **header);
 extern jb_err client_referrer        (struct client_state *csp, char **header);