-const char parsers_rcs[] = "$Id: parsers.c,v 1.69 2006/09/06 16:25:51 fabiankeil Exp $";
+const char parsers_rcs[] = "$Id: parsers.c,v 1.78 2006/12/26 17:19:20 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/parsers.c,v $
* `client_uagent', `client_x_forwarded',
* `client_x_forwarded_adder', `client_xtra_adder',
* `content_type', `crumble', `destroy_list', `enlist',
- * `flush_socket', ``get_header', `sed',
- * and `server_set_cookie'.
- *
- * Copyright : Written by and Copyright (C) 2001 the SourceForge
+ * `flush_socket', ``get_header', `sed', `filter_server_header'
+ * `filter_client_header', `filter_header', `crunch_server_header',
+ * `server_content_encoding', `server_content_disposition',
+ * `server_last_modified', `client_accept_language',
+ * `crunch_client_header', `client_if_modified_since',
+ * `client_if_none_match', `get_destination_from_headers',
+ * `parse_header_time' and `server_set_cookie'.
+ *
+ * Copyright : Written by and Copyright (C) 2001-2006 the SourceForge
* Privoxy team. http://www.privoxy.org/
*
* Based on the Internet Junkbuster originally written
*
* Revisions :
* $Log: parsers.c,v $
+ * Revision 1.78 2006/12/26 17:19:20 fabiankeil
+ * Bringing back the "useless" localtime() call
+ * I removed in revision 1.67. On some platforms
+ * it's necessary to prevent time zone offsets.
+ *
+ * Revision 1.77 2006/12/07 18:44:26 fabiankeil
+ * Rebuild request URL in get_destination_from_headers()
+ * to make sure redirect{pcrs command} works as expected
+ * for intercepted requests.
+ *
+ * Revision 1.76 2006/12/06 19:52:25 fabiankeil
+ * Added get_destination_from_headers().
+ *
+ * Revision 1.75 2006/11/13 19:05:51 fabiankeil
+ * Make pthread mutex locking more generic. Instead of
+ * checking for OSX and OpenBSD, check for FEATURE_PTHREAD
+ * and use mutex locking unless there is an _r function
+ * available. Better safe than sorry.
+ *
+ * Fixes "./configure --disable-pthread" and should result
+ * in less threading-related problems on pthread-using platforms,
+ * but it still doesn't fix BR#1122404.
+ *
+ * Revision 1.74 2006/10/02 16:59:12 fabiankeil
+ * The special header "X-Filter: No" now disables
+ * header filtering as well.
+ *
+ * Revision 1.73 2006/09/23 13:26:38 roro
+ * Replace TABs by spaces in source code.
+ *
+ * Revision 1.72 2006/09/23 12:37:21 fabiankeil
+ * Don't print a log message every time filter_headers is
+ * entered or left. It only creates noise without any real
+ * information.
+ *
+ * Revision 1.71 2006/09/21 19:55:17 fabiankeil
+ * Fix +hide-if-modified-since{-n}.
+ *
+ * Revision 1.70 2006/09/08 12:06:34 fabiankeil
+ * Have hide-if-modified-since interpret the random
+ * range value as minutes instead of hours. Allows
+ * more fine-grained configuration.
+ *
* Revision 1.69 2006/09/06 16:25:51 fabiankeil
* Always have parse_header_time return a pointer
* that actual makes sense, even though we currently
#include "project.h"
-#ifdef OSX_DARWIN
-#include <pthread.h>
+#ifdef FEATURE_PTHREAD
#include "jcc.h"
/* jcc.h is for mutex semapores only */
-#endif /* def OSX_DARWIN */
+#endif /* def FEATURE_PTHREAD */
#include "list.h"
#include "parsers.h"
#include "encode.h"
* or buffer limit reached.
*
*********************************************************************/
-jb_err add_to_iob(struct client_state *csp, char *buf, int n)
+jb_err add_to_iob(struct client_state *csp, char *buf, size_t n)
{
struct iob *iob = csp->iob;
size_t used, offset, need, want;
if (n <= 0) return JB_ERR_OK;
- used = iob->eod - iob->buf;
- offset = iob->cur - iob->buf;
+ used = (size_t)(iob->eod - iob->buf);
+ offset = (size_t)(iob->cur - iob->buf);
need = used + n + 1;
/*
int i, found_filters = 0;
- log_error(LOG_LEVEL_RE_FILTER, "Entered filter_headers");
/*
* Need to check the set of re_filterfiles...
*/
if ( 0 == size )
{
- log_error(LOG_LEVEL_HEADER, "Removing empty header %s", *header);
+ log_error(LOG_LEVEL_HEADER, "Removing empty header %s", *header);
freez(*header);
}
- log_error(LOG_LEVEL_RE_FILTER, "Leaving filter headers");
- return(JB_ERR_OK);
+ return(JB_ERR_OK);
}
now = time(NULL);
#ifdef HAVE_GMTIME_R
timeptr = gmtime_r(&now, &gmt);
-#elif OSX_DARWIN
+#elif FEATURE_PTHREAD
pthread_mutex_lock(&gmtime_mutex);
timeptr = gmtime(&now);
pthread_mutex_unlock(&gmtime_mutex);
}
else
{
- rtime = difftime(now, last_modified);
+ rtime = (long int)difftime(now, last_modified);
if (rtime)
{
rtime = pick_from_range(rtime);
last_modified += rtime;
#ifdef HAVE_GMTIME_R
timeptr = gmtime_r(&last_modified, &gmt);
-#elif OSX_DARWIN
+#elif FEATURE_PTHREAD
pthread_mutex_lock(&gmtime_mutex);
timeptr = gmtime(&last_modified);
pthread_mutex_unlock(&gmtime_mutex);
else
{
rtime = strtol(newval, &endptr, 0);
- if(rtime < 0)
- {
- rtime *= -1;
- negative = 1;
- }
if(rtime)
{
log_error(LOG_LEVEL_HEADER, "Randomizing: %s (random range: %d minut%s)",
*header, rtime, (rtime == 1 || rtime == -1) ? "e": "es");
+ if(rtime < 0)
+ {
+ rtime *= -1;
+ negative = 1;
+ }
rtime *= 60;
rtime = pick_from_range(rtime);
}
log_error(LOG_LEVEL_ERROR, "Random range is 0. Assuming time transformation test.",
*header);
}
- tm += rtime;
+ tm += rtime * (negative ? -1 : 1);
#ifdef HAVE_GMTIME_R
timeptr = gmtime_r(&tm, &gmt);
-#elif OSX_DARWIN
+#elif FEATURE_PTHREAD
pthread_mutex_lock(&gmtime_mutex);
timeptr = gmtime(&tm);
pthread_mutex_unlock(&gmtime_mutex);
{
log_error(LOG_LEVEL_INFO, "Ignored the client's request to fetch without filtering.");
}
- else
+ else
{
if (csp->action->flags & ACTION_FORCE_TEXT_MODE)
{
else
{
csp->content_type = CT_TABOO;
+ csp->action->flags &= ~ACTION_FILTER_SERVER_HEADERS;
+ csp->action->flags &= ~ACTION_FILTER_CLIENT_HEADERS;
log_error(LOG_LEVEL_HEADER, "Accepted the client's request to fetch without filtering.");
}
log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
time (&now);
#ifdef HAVE_LOCALTIME_R
tm_now = *localtime_r(&now, &tm_now);
-#elif OSX_DARWIN
+#elif FEATURE_PTHREAD
pthread_mutex_lock(&localtime_mutex);
tm_now = *localtime (&now);
pthread_mutex_unlock(&localtime_mutex);
*********************************************************************/
int strclean(const char *string, const char *substring)
{
- int hits = 0, len = strlen(substring);
+ int hits = 0;
+ size_t len;
char *pos, *p;
+ len = strlen(substring);
+
while((pos = strstr(string, substring)) != NULL)
{
p = pos + len;
* 2 : tm = storage for the resulting time in seconds
*
* Returns : Time struct containing the header time, or
- * NULL in case of a parsing problem.
+ * NULL in case of a parsing problems.
*
*********************************************************************/
struct tm *parse_header_time(char *header, time_t *tm) {
struct tm gmt;
struct tm * timeptr;
+ /*
+ * Initializing gmt to prevent time zone offsets.
+ *
+ * While this is only necessary on some platforms
+ * (mingw32 for example), I don't know how to
+ * detect these automatically and doing it everywhere
+ * shouldn't hurt.
+ */
+ time(tm);
+#ifdef HAVE_LOCALTIME_R
+ gmt = *localtime_r(tm, &gmt);
+#elif FEATURE_PTHREAD
+ pthread_mutex_lock(&localtime_mutex);
+ gmt = *localtime(tm);
+ pthread_mutex_unlock(&localtime_mutex);
+#else
+ gmt = *localtime(tm);
+#endif
+
/* Skipping header name */
timestring = strstr(header, ": ");
if (strptime(timestring, ": %a, %d %b %Y %H:%M:%S", &gmt) == NULL)
else
{
*tm = timegm(&gmt);
- timeptr=&gmt;
+ timeptr = &gmt;
}
return(timeptr);
+
+}
+
+/*********************************************************************
+ *
+ * Function : get_destination_from_headers
+ *
+ * Description : Parse the "Host:" header to get the request's destination.
+ * Only needed if the client's request was forcefully
+ * redirected into Privoxy.
+ *
+ * Code mainly copied from client_host() which is currently
+ * run too late for this purpose.
+ *
+ * Parameters :
+ * 1 : headers = List of headers (one of them hopefully being
+ * the "Host:" header)
+ * 2 : http = storage for the result (host, port and hostport).
+ *
+ * Returns : JB_ERR_MEMORY in case of memory problems,
+ * JB_ERR_PARSE if the host header couldn't be found,
+ * JB_ERR_OK otherwise.
+ *
+ *********************************************************************/
+jb_err get_destination_from_headers(const struct list *headers, struct http_request *http)
+{
+ char *q;
+ char *p;
+ char *host;
+
+ host = get_header_value(headers, "Host:");
+
+ if (NULL == host)
+ {
+ log_error(LOG_LEVEL_ERROR, "No \"Host:\" header found.");
+ return JB_ERR_PARSE;
+ }
+
+ if (NULL == (p = strdup((host))))
+ {
+ log_error(LOG_LEVEL_ERROR, "Out of memory while parsing \"Host:\" header");
+ return JB_ERR_MEMORY;
+ }
+ chomp(p);
+ if (NULL == (q = strdup(p)))
+ {
+ freez(p);
+ log_error(LOG_LEVEL_ERROR, "Out of memory while parsing \"Host:\" header");
+ return JB_ERR_MEMORY;
+ }
+
+ freez(http->hostport);
+ http->hostport = p;
+ freez(http->host);
+ http->host = q;
+ q = strchr(http->host, ':');
+ if (q != NULL)
+ {
+ /* Terminate hostname and evaluate port string */
+ *q++ = '\0';
+ http->port = atoi(q);
+ }
+ else
+ {
+ http->port = http->ssl ? 443 : 80;
+ }
+
+ /* Rebuild request URL */
+ freez(http->url);
+ http->url = strdup(http->ssl ? "https://" : "http://");
+ string_append(&http->url, http->hostport);
+ string_append(&http->url, http->path);
+ if (http->url == NULL)
+ {
+ return JB_ERR_MEMORY;
+ }
+
+ log_error(LOG_LEVEL_HEADER, "Destination extracted from \"Host:\" header. New request URL: %s",
+ http->url);
+
+ return JB_ERR_OK;
+
}