From 04104131e7e779b2373db118a09e9343a906ffab Mon Sep 17 00:00:00 2001 From: Fabian Keil Date: Thu, 17 Aug 2006 17:15:10 +0000 Subject: [PATCH] - Back to timegm() using GnuPG's replacement if necessary. 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 | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++-- miscutil.h | 14 ++++++-- parsers.c | 96 ++++++++++++++++++++++--------------------------- parsers.h | 10 ++++-- 4 files changed, 164 insertions(+), 60 deletions(-) diff --git a/miscutil.c b/miscutil.c index 5679ca2a..1f6f0c4e 100644 --- a/miscutil.c +++ b/miscutil.c @@ -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 #include +#ifndef HAVE_TIMEGM +#include +#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/ diff --git a/miscutil.h b/miscutil.h index 9c1c5b33..01b31793 100644 --- a/miscutil.h +++ b/miscutil.h @@ -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 @@ -37,6 +37,10 @@ * * 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[]; diff --git a/parsers.c b/parsers.c index 317c8cdf..fdd9f473 100644 --- 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); } diff --git a/parsers.h b/parsers.h index c562c941..5e79aeee 100644 --- 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 $ @@ -43,6 +43,12 @@ * * 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: http://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); -- 2.39.2