-const char parsers_rcs[] = "$Id: parsers.c,v 1.63 2006/08/14 13:18:08 david__schmidt Exp $";
+const char parsers_rcs[] = "$Id: parsers.c,v 1.67 2006/09/04 11:01:26 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/parsers.c,v $
*
* Revisions :
* $Log: parsers.c,v $
+ * Revision 1.67 2006/09/04 11:01:26 fabiankeil
+ * After filtering de-chunked instances, remove
+ * "Transfer-Encoding" header entirely instead of changing
+ * it to "Transfer-Encoding: identity", which is invalid.
+ * Thanks Michael Shields <shields@msrl.com>. Fixes PR 1318658.
+ *
+ * Don't use localtime in parse_header_time. An empty time struct
+ * is good enough, it gets overwritten by strptime anyway.
+ *
+ * Revision 1.66 2006/09/03 19:38:28 fabiankeil
+ * Use gmtime_r if available, fallback to gmtime with mutex
+ * protection for MacOSX and use vanilla gmtime for the rest.
+ *
+ * Revision 1.65 2006/08/22 10:55:56 fabiankeil
+ * Changed client_referrer to use the right type (size_t) for
+ * hostlenght and to shorten the temporary referrer string with
+ * '\0' instead of adding a useless line break.
+ *
+ * Revision 1.64 2006/08/17 17:15:10 fabiankeil
+ * - 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.
+ *
* Revision 1.63 2006/08/14 13:18:08 david__schmidt
* OS/2 compilation compatibility fixups
*
*
* Description : - Prohibit filtering (CT_TABOO) if transfer coding compresses
* - Raise the CSP_FLAG_CHUNKED flag if coding is "chunked"
- * - Change from "chunked" to "identity" if body was chunked
- * but has been de-chunked for filtering.
+ * - Remove header if body was chunked but has been
+ * de-chunked for filtering.
*
* Parameters :
* 1 : csp = Current client state (buffers, headers, etc...)
csp->flags |= CSP_FLAG_CHUNKED;
/*
- * If the body was modified, it has been
- * de-chunked first, so adjust the header:
+ * If the body was modified, it has been de-chunked first
+ * and the header must be removed.
*/
if (csp->flags & CSP_FLAG_MODIFIED)
{
+ log_error(LOG_LEVEL_HEADER, "Removing: %s", *header);
freez(*header);
- *header = strdup("Transfer-Encoding: identity");
- log_error(LOG_LEVEL_HEADER, "Set: %s", *header);
- return (header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
}
}
char buf[BUFFER_SIZE];
char newheader[50];
+#ifdef HAVE_GMTIME_R
+ struct tm gmt;
+#endif
struct tm *timeptr = NULL;
time_t now, last_modified;
long int rtime;
{
log_error(LOG_LEVEL_HEADER, "Randomizing: %s", *header);
now = time(NULL);
+#ifdef HAVE_GMTIME_R
+ timeptr = gmtime_r(&now, &gmt);
+#elif OSX_DARWIN
+ pthread_mutex_lock(&gmtime_mutex);
+ timeptr = gmtime(&now);
+ pthread_mutex_unlock(&gmtime_mutex);
+#else
timeptr = gmtime(&now);
+#endif
if ((timeptr = parse_header_time(*header, &last_modified)) == NULL)
{
log_error(LOG_LEVEL_HEADER, "Couldn't parse: %s (crunching!)", *header);
{
rtime = pick_from_range(rtime);
last_modified += rtime;
+#ifdef HAVE_GMTIME_R
+ timeptr = gmtime_r(&last_modified, &gmt);
+#elif OSX_DARWIN
+ pthread_mutex_lock(&gmtime_mutex);
+ timeptr = gmtime(&last_modified);
+ pthread_mutex_unlock(&gmtime_mutex);
+#else
timeptr = gmtime(&last_modified);
+#endif
strftime(newheader, sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr);
freez(*header);
*header = strdup("Last-Modified: ");
const char *newval;
const char *host;
char *referer;
- int hostlenght;
+ size_t hostlenght;
#ifdef FEATURE_FORCE_LOAD
/* Since the referrer can include the prefix even
*if www.example.org/www.example.com-shall-see-the-referer/
*links to www.example.com/
*/
- referer[hostlenght+17] = '\n';
+ referer[hostlenght+17] = '\0';
}
if ( 0 == strstr(referer, host)) /*Host has changed*/
{
jb_err client_if_modified_since(struct client_state *csp, char **header)
{
char newheader[50];
+#ifdef HAVE_GMTIME_R
+ struct tm gmt;
+#endif
struct tm *timeptr = NULL;
time_t tm = 0;
const char *newval;
*header);
}
tm += rtime;
+#ifdef HAVE_GMTIME_R
+ timeptr = gmtime_r(&tm, &gmt);
+#elif OSX_DARWIN
+ pthread_mutex_lock(&gmtime_mutex);
timeptr = gmtime(&tm);
+ pthread_mutex_unlock(&gmtime_mutex);
+#else
+ timeptr = gmtime(&tm);
+#endif
strftime(newheader, sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr);
freez(*header);
{
if ( 0 == strcmpic(*header, "X-Filter: No"))
{
- if (csp->action->flags & ACTION_FORCE_TEXT_MODE)
+ if (!(csp->config->feature_flags & RUNTIME_FEATURE_HTTP_TOGGLE))
{
- log_error(LOG_LEVEL_HEADER, "force-text-mode overruled the client's request to disable filtering!");
+ log_error(LOG_LEVEL_INFO, "Ignored the client's request to fetch without filtering.");
}
- else
- {
- csp->content_type = CT_TABOO;
- log_error(LOG_LEVEL_HEADER, "Disabled filter mode on behalf of the client.");
+ else
+ {
+ if (csp->action->flags & ACTION_FORCE_TEXT_MODE)
+ {
+ log_error(LOG_LEVEL_HEADER, "force-text-mode overruled the client's request to fetch without filtering!");
+ }
+ else
+ {
+ csp->content_type = CT_TABOO;
+ log_error(LOG_LEVEL_HEADER, "Accepted the client's request to fetch without filtering.");
+ }
+ log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
+ freez(*header);
}
- log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
- freez(*header);
}
return JB_ERR_OK;
}
struct tm *parse_header_time(char *header, time_t *tm) {
char * timestring;
+ struct tm gmt;
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)
+ if (strptime(timestring, ": %a, %d %b %Y %H:%M:%S", &gmt) == NULL)
{
timeptr = NULL;
}
else
{
- *tm = timegm(timeptr);
+ *tm = timegm(&gmt);
}
return(timeptr);
}