-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 $
*
* 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/
*
#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
{ "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 }
};
{ "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 }
};
/* 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);
+}
/*********************************************************************
*
# 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...
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;
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)
{
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);
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;
}
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: ");
}
#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:
#ifndef PARSERS_H_INCLUDED
#define PARSERS_H_INCLUDED
-#define PARSERS_H_VERSION "$Id: parsers.h,v 1.28 2006/07/18 14:48:47 david__schmidt Exp $"
+#define PARSERS_H_VERSION "$Id: parsers.h,v 1.29 2006/08/03 02:46:41 david__schmidt Exp $"
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/parsers.h,v $
*
* Revisions :
* $Log: parsers.h,v $
+ * Revision 1.29 2006/08/03 02:46:41 david__schmidt
+ * Incorporate Fabian Keil's patch work:\rhttp://www.fabiankeil.de/sourcecode/privoxy/
+ *
* Revision 1.28 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)
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);
extern jb_err crumble (struct client_state *csp, char **header);
extern jb_err client_referrer (struct client_state *csp, char **header);
extern jb_err client_if_none_match (struct client_state *csp, char **header);
extern jb_err crunch_client_header (struct client_state *csp, char **header);
extern jb_err filter_header (struct client_state *csp, char **header);
+extern jb_err filter_client_header (struct client_state *csp, char **header);
+extern jb_err filter_server_header (struct client_state *csp, char **header);
extern jb_err client_x_filter (struct client_state *csp, char **header);