/*********************************************************************
*
- * File : $Source: /cvsroot/ijbswa/current/Attic/actionlist.h,v $
+ * File : $Source: /cvsroot/ijbswa/current/actionlist.h,v $
*
* Purpose : Master list of supported actions.
* Not really a header, since it generates code.
*
* Revisions :
* $Log: actionlist.h,v $
+ * Revision 1.19 2006/07/18 14:48:45 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.17.2.3 2004/10/03 12:53:32 david__schmidt
* Add the ability to check jpeg images for invalid
* lengths of comment blocks. Defensive strategy
DEFINE_CGI_PARAM_RADIO ("deanimate-gifs", ACTION_DEANIMATE, ACTION_STRING_DEANIMATE, "first", 0)
DEFINE_CGI_PARAM_RADIO ("deanimate-gifs", ACTION_DEANIMATE, ACTION_STRING_DEANIMATE, "last", 1)
DEFINE_ACTION_BOOL ("downgrade-http-version", ACTION_DOWNGRADE)
-DEFINE_ACTION_BOOL ("fast-redirects", ACTION_FAST_REDIRECTS)
+DEFINE_ACTION_STRING ("fast-redirects", ACTION_FAST_REDIRECTS, ACTION_STRING_FAST_REDIRECTS)
+DEFINE_CGI_PARAM_RADIO ("fast-redirects", ACTION_FAST_REDIRECTS, ACTION_STRING_FAST_REDIRECTS, "simple-check", 0)
+DEFINE_CGI_PARAM_RADIO ("fast-redirects", ACTION_FAST_REDIRECTS, ACTION_STRING_FAST_REDIRECTS, "check-decoded-url", 1)
DEFINE_ACTION_MULTI ("filter", ACTION_MULTI_FILTER)
DEFINE_ACTION_BOOL ("handle-as-image", ACTION_IMAGE)
DEFINE_ACTION_BOOL ("hide-forwarded-for-headers", ACTION_HIDE_FORWARDED)
DEFINE_ACTION_STRING ("hide-from-header", ACTION_HIDE_FROM, ACTION_STRING_FROM)
DEFINE_CGI_PARAM_RADIO ("hide-from-header", ACTION_HIDE_FROM, ACTION_STRING_FROM, "block", 1)
DEFINE_CGI_PARAM_CUSTOM ("hide-from-header", ACTION_HIDE_FROM, ACTION_STRING_FROM, "spam_me_senseless@sittingduck.xyz")
+DEFINE_ACTION_BOOL ("filter-headers", ACTION_FILTER_HEADERS)
+DEFINE_ACTION_STRING ("crunch-server-header", ACTION_CRUNCH_SERVER_HEADER, ACTION_STRING_SERVER_HEADER)
+DEFINE_CGI_PARAM_NO_RADIO("crunch-server-header", ACTION_CRUNCH_SERVER_HEADER, ACTION_STRING_SERVER_HEADER, "X-Whatever:")
+DEFINE_ACTION_STRING ("crunch-client-header", ACTION_CRUNCH_CLIENT_HEADER, ACTION_STRING_CLIENT_HEADER)
+DEFINE_CGI_PARAM_NO_RADIO("crunch-client-header", ACTION_CRUNCH_CLIENT_HEADER, ACTION_STRING_CLIENT_HEADER, "X-Whatever:")
+DEFINE_ACTION_STRING ("hide-accept-language", ACTION_HIDE_ACCEPT_LANGUAGE, ACTION_STRING_LANGUAGE)
+DEFINE_CGI_PARAM_RADIO ("hide-accept-language", ACTION_HIDE_ACCEPT_LANGUAGE, ACTION_STRING_LANGUAGE, "block", 0)
+DEFINE_CGI_PARAM_CUSTOM ("hide-accept-language", ACTION_HIDE_ACCEPT_LANGUAGE, ACTION_STRING_LANGUAGE, "de-de")
+DEFINE_ACTION_STRING ("content-type-overwrite", ACTION_CONTENT_TYPE_OVERWRITE, ACTION_STRING_CONTENT_TYPE)
+DEFINE_CGI_PARAM_NO_RADIO("content-type-overwrite", ACTION_CONTENT_TYPE_OVERWRITE, ACTION_STRING_CONTENT_TYPE, "text/html")
+DEFINE_ACTION_STRING ("hide-content-disposition", ACTION_HIDE_CONTENT_DISPOSITION, ACTION_STRING_CONTENT_DISPOSITION)
+DEFINE_CGI_PARAM_RADIO ("hide-content-disposition", ACTION_HIDE_CONTENT_DISPOSITION, ACTION_STRING_CONTENT_DISPOSITION, "block", 0)
+DEFINE_CGI_PARAM_CUSTOM ("hide-content-disposition", ACTION_HIDE_CONTENT_DISPOSITION, ACTION_STRING_CONTENT_DISPOSITION, "attachment; filename=WHATEVER.txt")
+DEFINE_ACTION_STRING ("hide-if-modified-since", ACTION_HIDE_IF_MODIFIED_SINCE, ACTION_STRING_IF_MODIFIED_SINCE)
+DEFINE_CGI_PARAM_RADIO ("hide-if-modified-since", ACTION_HIDE_IF_MODIFIED_SINCE, ACTION_STRING_IF_MODIFIED_SINCE, "block", 0)
+DEFINE_CGI_PARAM_CUSTOM ("hide-if-modified-since", ACTION_HIDE_IF_MODIFIED_SINCE, ACTION_STRING_IF_MODIFIED_SINCE, "-1")
+DEFINE_ACTION_STRING ("overwrite-last-modified", ACTION_OVERWRITE_LAST_MODIFIED, ACTION_STRING_LAST_MODIFIED)
+DEFINE_CGI_PARAM_RADIO ("overwrite-last-modified", ACTION_OVERWRITE_LAST_MODIFIED, ACTION_STRING_LAST_MODIFIED, "block", 0)
+DEFINE_CGI_PARAM_RADIO ("overwrite-last-modified", ACTION_OVERWRITE_LAST_MODIFIED, ACTION_STRING_LAST_MODIFIED, "reset-to-request-time", 1)
+DEFINE_CGI_PARAM_RADIO ("overwrite-last-modified", ACTION_OVERWRITE_LAST_MODIFIED, ACTION_STRING_LAST_MODIFIED, "randomize", 2)
+DEFINE_ACTION_BOOL ("crunch-if-none-match", ACTION_CRUNCH_IF_NONE_MATCH)
+DEFINE_ACTION_BOOL ("force-text-mode", ACTION_FORCE_TEXT_MODE)
+DEFINE_ACTION_BOOL ("handle-as-empty-document", ACTION_HANDLE_AS_EMPTY_DOCUMENT)
+DEFINE_ACTION_BOOL ("treat-forbidden-connects-like-blocks", ACTION_TREAT_FORBIDDEN_CONNECTS_LIKE_BLOCKS)
+DEFINE_ACTION_STRING ("redirect", ACTION_REDIRECT, ACTION_STRING_REDIRECT)
+DEFINE_CGI_PARAM_NO_RADIO("redirect", ACTION_REDIRECT, ACTION_STRING_REDIRECT, "http://localhost/")
DEFINE_ACTION_STRING ("hide-referrer", ACTION_HIDE_REFERER, ACTION_STRING_REFERER)
+DEFINE_CGI_PARAM_RADIO ("hide-referrer", ACTION_HIDE_REFERER, ACTION_STRING_REFERER, "conditional-block", 2)
DEFINE_CGI_PARAM_RADIO ("hide-referrer", ACTION_HIDE_REFERER, ACTION_STRING_REFERER, "forge", 1)
DEFINE_CGI_PARAM_RADIO ("hide-referrer", ACTION_HIDE_REFERER, ACTION_STRING_REFERER, "block", 0)
DEFINE_CGI_PARAM_CUSTOM ("hide-referrer", ACTION_HIDE_REFERER, ACTION_STRING_REFERER, "http://www.google.com/")
-const char cgi_rcs[] = "$Id: cgi.c,v 1.70.2.13 2004/02/17 13:30:23 oes Exp $";
+const char cgi_rcs[] = "$Id: cgi.c,v 1.72 2006/07/18 14:48:45 david__schmidt Exp $";
/*********************************************************************
*
- * File : $Source: /cvsroot/ijbswa/current/Attic/cgi.c,v $
+ * File : $Source: /cvsroot/ijbswa/current/cgi.c,v $
*
* Purpose : Declares functions to intercept request, generate
* html or gif answers, and to compose HTTP resonses.
*
* Revisions :
* $Log: cgi.c,v $
+ * Revision 1.72 2006/07/18 14:48:45 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.70.2.13 2004/02/17 13:30:23 oes
* Moved cgi_error_disabled() from cgiedit.c to
* cgi.c to re-enable build with --disable-editor.
else
{
/*
- * Compliant browsers should not cache this due to the "Cache-Control"
- * setting. However, to be certain, we also set both "Last-Modified"
- * and "Expires" to the current time.
+ * Setting "Cache-Control" to "no-cache" and "Expires" to
+ * the current time doesn't exactly forbid caching, it just
+ * requires the client to revalidate the cached copy.
+ *
+ * If a temporary problem occurres and the user tries again after
+ * getting Privoxy's error message, a compliant browser may set the
+ * If-Modified-Since header with the content of the error page's
+ * Last-Modified header. More often than not, the document on the server
+ * is older than Privoxy's error message, the server would send status code
+ * 304 and the browser would display the outdated error message again and again.
+ *
+ * As a last resort we set "Last-Modified" to Tim Berners-Lee's birthday,
+ * which predates the age of any page on the web and can be safely used to
+ * "revalidate" without getting a status code 304.
+ *
+ * There is no need to let the useless If-Modified-Since header reach the
+ * server, it is therefore stripped by client_if_modified_since in parsers.c.
*/
if (!err) err = enlist_unique_header(rsp->headers, "Cache-Control", "no-cache");
get_http_time(0, buf);
if (!err) err = enlist_unique_header(rsp->headers, "Date", buf);
- if (!err) err = enlist_unique_header(rsp->headers, "Last-Modified", buf);
+ if (!err) err = enlist_unique_header(rsp->headers, "Last-Modified", "Wed, 08 Jun 1955 12:00:00 GMT");
if (!err) err = enlist_unique_header(rsp->headers, "Expires", "Sat, 17 Jun 2000 12:00:00 GMT");
+ if (!err) err = enlist_unique_header(rsp->headers, "Pragma", "no-cache");
}
#
# Copyright (C) 2001-2004 Privoxy Developers http://privoxy.org
#
-# $Id: config,v 1.39.2.17 2006/01/31 11:52:32 david__schmidt Exp $
+# $Id: config,v 1.47 2006/07/18 14:48:45 david__schmidt Exp $
#
####################################################################
# #
#
# listen-address 192.168.0.1:8118
#
-listen-address :8118
+listen-address :8119
#
# 4.2. toggle
#
# File : $Source: /cvsroot/ijbswa/current/default.action.master,v $
#
-# $Id: default.action.master,v 1.10 2006/07/18 14:48:45 david__schmidt Exp $
+# $Id: default.action.master,v 1.11 2006/08/02 17:36:19 david__schmidt Exp $
#
# Purpose : Default actions file, see
# http://www.privoxy.org/user-manual/actions-file.html
# responses as well. Use this action for servers that use HTTP/1.1
# protocol features that Privoxy currently can't handle yet.
#
-# +fast-redirects
+# +fast-redirects{check-decoded-url}
# Many sites, like yahoo.com, don't just link to other sites.
# Instead, they will link to some script on their own server,
# giving the destination as a parameter, which will then redirect
# time is wasted, while your browser aks the server for one redirect
# after the other. Plus, it feeds the advertisers.
#
-# The +fast-redirects option enables interception of these requests
+# The +fast-redirects{check-decoded-url} option enables interception of these requests
# by Privoxy, who will cut off all but the last valid URL in the
# request and send a local redirect back to your browser without
# contacting the intermediate sites.
#MASTER# PROBLEM-URL: http://www.hh.schule.de/ak/nt/
www.hh.schule.de/ak/nt/
-{+fast-redirects -block}
+{+fast-redirects{check-decoded-url} -block}
#MASTER# PROBLEM-URL: http://isbn.nu/0596001088/price/2.html
www.commission-junction.com/track/
#MASTER# PROBLEM-URL: http://uk.rd.yahoo.com/M=200059723.200849546.202365062.200414073/D=ukhmpg/S=15426100:TEAR/A=200396897/R=1119/id=img1_nocap_dial/*http://ad.uk.doubleclick.net/clk;5982435;8261020;g?http://www.lunnpoly.com
-const char errlog_rcs[] = "$Id: errlog.c,v 1.40.2.4 2005/04/03 20:10:50 david__schmidt Exp $";
+const char errlog_rcs[] = "$Id: errlog.c,v 1.42 2006/07/18 14:48:46 david__schmidt Exp $";
/*********************************************************************
*
- * File : $Source: /cvsroot/ijbswa/current/Attic/errlog.c,v $
+ * File : $Source: /cvsroot/ijbswa/current/errlog.c,v $
*
* Purpose : Log errors to a designated destination in an elegant,
* printf-like fashion.
*
* Revisions :
* $Log: errlog.c,v $
+ * Revision 1.42 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.40.2.4 2005/04/03 20:10:50 david__schmidt
* Thanks to Jindrich Makovicka for a race condition fix for the log
* file. The race condition remains for non-pthread implementations.
static FILE *logfp = NULL;
/* logging detail level. */
-static int debug = (LOG_LEVEL_FATAL | LOG_LEVEL_ERROR | LOG_LEVEL_INFO);
+int debug = (LOG_LEVEL_FATAL | LOG_LEVEL_ERROR | LOG_LEVEL_INFO);
/* static functions */
static void fatal_error(const char * error_message);
-const char filters_rcs[] = "$Id: filters.c,v 1.58.2.9 2006/01/29 23:10:56 david__schmidt Exp $";
+const char filters_rcs[] = "$Id: filters.c,v 1.60 2006/07/18 14:48:46 david__schmidt Exp $";
/*********************************************************************
*
- * File : $Source: /cvsroot/ijbswa/current/Attic/filters.c,v $
+ * File : $Source: /cvsroot/ijbswa/current/filters.c,v $
*
* Purpose : Declares functions to parse/crunch headers and pages.
* Functions declared include:
*
* Revisions :
* $Log: filters.c,v $
+ * Revision 1.60 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.58.2.9 2006/01/29 23:10:56 david__schmidt
* Multiple filter file support
*
struct http_response *block_url(struct client_state *csp)
{
struct http_response *rsp;
+ const char *new_content_type = NULL;
/*
* If it's not blocked, don't block it ;-)
{
return NULL;
}
-
+ if (csp->action->flags & ACTION_REDIRECT)
+ {
+ log_error(LOG_LEVEL_ERROR, "redirect{} overruled by block.");
+ }
/*
* Else, prepare a response
*/
/* determine HOW images should be blocked */
p = csp->action->string[ACTION_STRING_IMAGE_BLOCKER];
+ if(csp->action->flags & ACTION_HANDLE_AS_EMPTY_DOCUMENT)
+ {
+ log_error(LOG_LEVEL_ERROR, "handle-as-empty-document overruled by handle-as-image.");
+ }
#if 1 /* Two alternative strategies, use this one for now: */
/* and handle accordingly: */
if ((p == NULL) || (0 == strcmpic(p, "pattern")))
{
+ rsp->status = strdup("403 Request blocked by Privoxy");
+ if (rsp->status == NULL)
+ {
+ free_http_response(rsp);
+ return cgi_error_memory();
+ }
rsp->body = bindup(image_pattern_data, image_pattern_length);
if (rsp->body == NULL)
{
else if (0 == strcmpic(p, "blank"))
{
+ rsp->status = strdup("403 Request blocked by Privoxy");
+ if (rsp->status == NULL)
+ {
+ free_http_response(rsp);
+ return cgi_error_memory();
+ }
rsp->body = bindup(image_blank_data, image_blank_length);
if (rsp->body == NULL)
{
return cgi_error_memory();
}
#endif /* Preceeding code is disabled for now */
+ }
+ else if(csp->action->flags & ACTION_HANDLE_AS_EMPTY_DOCUMENT)
+ {
+ /*
+ * Send empty document.
+ */
+ new_content_type = csp->action->string[ACTION_STRING_CONTENT_TYPE];
+
+ freez(rsp->body);
+ rsp->body = strdup(" ");
+ rsp->content_length = 1;
+
+ rsp->status = strdup("403 Request blocked by Privoxy");
+ if (rsp->status == NULL)
+ {
+ free_http_response(rsp);
+ return cgi_error_memory();
+ }
+ if (new_content_type != 0)
+ {
+ log_error(LOG_LEVEL_HEADER, "Overwriting Content-Type with %s", new_content_type);
+ if (enlist_unique_header(rsp->headers, "Content-Type", new_content_type))
+ {
+ free_http_response(rsp);
+ return cgi_error_memory();
+ }
+ }
+
}
else
#endif /* def FEATURE_IMAGE_BLOCKING */
{
char *p, *q;
struct http_response *rsp;
+ char *redirect_mode = NULL;
+ int x, y;
- p = q = csp->http->path;
- log_error(LOG_LEVEL_REDIRECTS, "checking path for redirects: %s", p);
-
- /*
- * find the last URL encoded in the request
- */
- while ((p = strstr(p, "http://")) != NULL)
+ if ((csp->action->flags & ACTION_REDIRECT))
{
- q = p++;
+ q = csp->action->string[ACTION_STRING_REDIRECT];
}
+ else
+ {
+ redirect_mode = csp->action->string[ACTION_STRING_FAST_REDIRECTS];
+ if (0 == strcmpic(redirect_mode, "check-decoded-url"))
+ {
+ p = q = csp->http->path;
+ log_error(LOG_LEVEL_REDIRECTS, "Decoding path: %s if necessary.", p);
+ while (*p)
+ {
+ if (*p == '%') /* Escape sequence? */
+ {
+ /* Yes, translate from hexadecimal to decimal */
+ p++;
+ /* First byte */
+ x=((int)*p++)-48;
+ if (x>9) x-=7;
+ x<<=4;
+ /* Second byte */
+ y=((int)*p++)-48;
+ if (y>9)y-=7;
+ /* Merge */
+ *q++=(char)(x|y);
+ }
+ else
+ {
+ /* No, forward character. */
+ *q++=*p++;
+ }
+ }
+ *q='\0';
+ }
+ p = q = csp->http->path;
+ log_error(LOG_LEVEL_REDIRECTS, "Checking path for redirects: %s", p);
+ /*
+ * find the last URL encoded in the request
+ */
+ while ((p = strstr(p, "http://")) != NULL)
+ {
+ q = p++;
+ }
+ }
/*
* if there was any, generate and return a HTTP redirect
*/
-const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.35.2.8 2006/01/21 16:16:08 david__schmidt Exp $";
+const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.38 2006/07/18 14:48:46 david__schmidt Exp $";
/*********************************************************************
*
- * File : $Source: /cvsroot/ijbswa/current/Attic/jbsockets.c,v $
+ * File : $Source: /cvsroot/ijbswa/current/jbsockets.c,v $
*
* Purpose : Contains wrappers for system-specific sockets code,
* so that the rest of Junkbuster can be more
*
* Revisions :
* $Log: jbsockets.c,v $
+ * Revision 1.38 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.35.2.8 2006/01/21 16:16:08 david__schmidt
* Thanks to Edward Carrel for his patch to modernize OSX's\rpthreads support. See bug #1409623.
*
{
struct sockaddr_in inaddr;
struct hostent *hostp;
+ unsigned int dns_retries = 0;
#if defined(HAVE_GETHOSTBYNAME_R_6_ARGS) || defined(HAVE_GETHOSTBYNAME_R_5_ARGS) || defined(HAVE_GETHOSTBYNAME_R_3_ARGS)
struct hostent result;
#if defined(HAVE_GETHOSTBYNAME_R_6_ARGS) || defined(HAVE_GETHOSTBYNAME_R_5_ARGS)
if ((inaddr.sin_addr.s_addr = inet_addr(host)) == -1)
{
#if defined(HAVE_GETHOSTBYNAME_R_6_ARGS)
- gethostbyname_r(host, &result, hbuf,
- HOSTENT_BUFFER_SIZE, &hostp, &thd_err);
+ while ( gethostbyname_r(host, &result, hbuf,
+ HOSTENT_BUFFER_SIZE, &hostp, &thd_err)
+ && (thd_err == TRY_AGAIN) && (dns_retries++ < 10) )
+ {
+ log_error(LOG_LEVEL_ERROR, "Timeout #%u while trying to resolve %s. Trying again.",
+ dns_retries, host);
+ }
#elif defined(HAVE_GETHOSTBYNAME_R_5_ARGS)
hostp = gethostbyname_r(host, &result, hbuf,
HOSTENT_BUFFER_SIZE, &thd_err);
}
#elif OSX_DARWIN
pthread_mutex_lock(&gethostbyname_mutex);
- hostp = gethostbyname(host);
+ while ( NULL == (hostp = gethostbyname(host))
+ && (h_errno == TRY_AGAIN) && (dns_retries++ < 10) )
+ {
+ log_error(LOG_LEVEL_ERROR, "Timeout #%u while trying to resolve %s. Trying again.",
+ dns_retries, host);
+ }
pthread_mutex_unlock(&gethostbyname_mutex);
#else
- hostp = gethostbyname(host);
+ while ( NULL == (hostp = gethostbyname(host))
+ && (h_errno == TRY_AGAIN) && (dns_retries++ < 10) )
+ {
+ log_error(LOG_LEVEL_ERROR, "Timeout #%u while trying to resolve %s. Trying again.",
+ dns_retries, host);
+ }
#endif /* def HAVE_GETHOSTBYNAME_R_(6|5|3)_ARGS */
/*
* On Mac OSX, if a domain exists but doesn't have a type A
-const char jcc_rcs[] = "$Id: jcc.c,v 1.92.2.16 2005/04/03 20:10:50 david__schmidt Exp $";
+const char jcc_rcs[] = "$Id: jcc.c,v 1.94 2006/07/18 14:48:46 david__schmidt Exp $";
/*********************************************************************
*
- * File : $Source: /cvsroot/ijbswa/current/Attic/jcc.c,v $
+ * File : $Source: /cvsroot/ijbswa/current/jcc.c,v $
*
* Purpose : Main file. Contains main() method, main loop, and
* the main connection-handling function.
*
* Revisions :
* $Log: jcc.c,v $
+ * Revision 1.94 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.92.2.16 2005/04/03 20:10:50 david__schmidt
* Thanks to Jindrich Makovicka for a race condition fix for the log
* file. The race condition remains for non-pthread implementations.
int server_body;
int ms_iis5_hack = 0;
int byte_count = 0;
+ unsigned int socks_retries = 0;
const struct forward_spec * fwd;
struct http_request *http;
int len; /* for buffer sizes */
|| (csp->action->flags & ACTION_LIMIT_CONNECT
&& !match_portlist(csp->action->string[ACTION_STRING_LIMIT_CONNECT], csp->http->port)) )
{
- strcpy(buf, CFORBIDDEN);
- write_socket(csp->cfd, buf, strlen(buf));
-
- log_error(LOG_LEVEL_CONNECT, "Denying suspicious CONNECT request from %s", csp->ip_addr_str);
- log_error(LOG_LEVEL_CLF, "%s - - [%T] \" \" 403 0", csp->ip_addr_str);
-
- return;
+ if (csp->action->flags & ACTION_TREAT_FORBIDDEN_CONNECTS_LIKE_BLOCKS)
+ {
+ /* The response will violate the specs, but makes unblocking easier. */
+ log_error(LOG_LEVEL_ERROR, "Marking suspicious CONNECT request from %s for blocking.",
+ csp->ip_addr_str);
+ csp->action->flags |= ACTION_BLOCK;
+ http->ssl = 0;
+ }
+ else
+ {
+ strcpy(buf, CFORBIDDEN);
+ write_socket(csp->cfd, buf, strlen(buf));
+ log_error(LOG_LEVEL_CONNECT, "Denying suspicious CONNECT request from %s", csp->ip_addr_str);
+ log_error(LOG_LEVEL_CLF, "%s - - [%T] \" \" 403 0", csp->ip_addr_str);
+ return;
+ }
}
}
csp->flags |= CSP_FLAG_REJECTED;
#endif /* def FEATURE_STATISTICS */
- /* Log (FIXME: All intercept reasons apprear as "crunch" with Status 200) */
+ /* Log (FIXME: All intercept reasons appear as "crunch" with Status 200) */
log_error(LOG_LEVEL_GPC, "%s%s crunch!", http->hostport, http->path);
log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 3", csp->ip_addr_str, http->ocmd);
/* here we connect to the server, gateway, or the forwarder */
- csp->sfd = forwarded_connect(fwd, http, csp);
+ while ( (csp->sfd = forwarded_connect(fwd, http, csp))
+ && (errno == EINVAL) && (socks_retries++ < 3))
+ {
+ log_error(LOG_LEVEL_ERROR, "failed request #%u to connect to %s. Trying again.",
+ socks_retries, http->hostport);
+ }
if (csp->sfd == JB_INVALID_SOCKET)
{
csp->content_length = csp->iob->eod - csp->iob->cur;
}
- hdr = sed(server_patterns, add_server_headers, csp);
+ hdr = sed(server_patterns_light, NULL, csp);
+
if (hdr == NULL)
{
/* FIXME Should handle error properly */
-const char parsers_rcs[] = "$Id: parsers.c,v 1.56.2.10 2006/01/21 16:16:08 david__schmidt Exp $";
+const char parsers_rcs[] = "$Id: parsers.c,v 1.58 2006/07/18 14:48:47 david__schmidt Exp $";
/*********************************************************************
*
- * File : $Source: /cvsroot/ijbswa/current/Attic/parsers.c,v $
+ * File : $Source: /cvsroot/ijbswa/current/parsers.c,v $
*
* Purpose : Declares functions to parse/crunch headers and pages.
* Functions declared include:
*
* Revisions :
* $Log: parsers.c,v $
+ * Revision 1.58 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.56.2.10 2006/01/21 16:16:08 david__schmidt
* Thanks to Edward Carrel for his patch to modernize OSX's\rpthreads support. See bug #1409623.
*
#include <ctype.h>
#include <assert.h>
#include <string.h>
+#include <time.h>
#if !defined(_WIN32) && !defined(__OS2__)
#include <unistd.h>
const struct parsers client_patterns[] = {
- { "referer:", 8, client_referrer },
+ { "referer:", 8, client_referrer },
{ "user-agent:", 11, client_uagent },
- { "ua-", 3, client_ua },
- { "from:", 5, client_from },
- { "cookie:", 7, client_send_cookie },
+ { "ua-", 3, client_ua },
+ { "from:", 5, client_from },
+ { "cookie:", 7, client_send_cookie },
{ "x-forwarded-for:", 16, client_x_forwarded },
{ "Accept-Encoding:", 16, client_accept_encoding },
{ "TE:", 3, client_te },
{ "Host:", 5, client_host },
-/* { "if-modified-since:", 18, crumble }, */
+ { "if-modified-since:", 18, client_if_modified_since },
{ "Keep-Alive:", 11, crumble },
{ "connection:", 11, crumble },
{ "proxy-connection:", 17, crumble },
{ "max-forwards:", 13, client_max_forwards },
- { NULL, 0, NULL }
+ { "Accept-Language:", 16, client_accept_language },
+ { "if-none-match:", 14, client_if_none_match },
+ { "X-Filter:", 9, client_x_filter },
+ { "*", 0, crunch_client_header },
+ { "*", 0, filter_header },
+ { NULL, 0, NULL }
};
-
const struct parsers server_patterns[] = {
- { "HTTP", 4, server_http },
- { "set-cookie:", 11, server_set_cookie },
- { "connection:", 11, crumble },
- { "Content-Type:", 13, server_content_type },
- { "Content-Length:", 15, server_content_length },
- { "Content-MD5:", 12, server_content_md5 },
- { "Content-Encoding:", 17, server_content_encoding },
- { "Transfer-Encoding:", 18, server_transfer_coding },
- { "Keep-Alive:", 11, crumble },
+ { "HTTP", 4, server_http },
+ { "set-cookie:", 11, server_set_cookie },
+ { "connection:", 11, crumble },
+ { "Content-Type:", 13, server_content_type },
+ { "Content-Length:", 15, server_content_length },
+ { "Content-MD5:", 12, server_content_md5 },
+ { "Content-Encoding:", 17, server_content_encoding },
+ { "Transfer-Encoding:", 18, server_transfer_coding },
+ { "Keep-Alive:", 11, crumble },
+ { "content-disposition:", 20, server_content_disposition },
+ { "Last-Modified:", 14, server_last_modified },
+ { "*", 0, crunch_server_header },
+ { "*", 0, filter_header },
{ NULL, 0, NULL }
};
+const struct parsers server_patterns_light[] = {
+ { "Content-Length:", 15, server_content_length },
+ { "Transfer-Encoding:", 18, server_transfer_coding },
+ { NULL, 0, NULL }
+};
const add_header_func_ptr add_client_headers[] = {
client_host_adder,
NULL
};
-
/*********************************************************************
*
* Function : flush_socket
const struct parsers *v;
const add_header_func_ptr *f;
jb_err err = JB_ERR_OK;
+ int first_run;
+
+ /*
+ * If filtering is enabled, sed is run twice,
+ * but most of the work needs to be done only once.
+ */
+ first_run = (more_headers != NULL ) ? 1 : 0;
- for (v = pats; (err == JB_ERR_OK) && (v->str != NULL) ; v++)
+ if (first_run) /* Parse and print */
{
- for (p = csp->headers->first; (err == JB_ERR_OK) && (p != NULL) ; p = p->next)
+ for (v = pats; (err == JB_ERR_OK) && (v->str != NULL) ; v++)
{
- /* Header crunch()ed in previous run? -> ignore */
- if (p->str == NULL) continue;
+ for (p = csp->headers->first; (err == JB_ERR_OK) && (p != NULL) ; p = p->next)
+ {
+ /* Header crunch()ed in previous run? -> ignore */
+ if (p->str == NULL) continue;
- if (v == pats) log_error(LOG_LEVEL_HEADER, "scan: %s", p->str);
+ if (v == pats) log_error(LOG_LEVEL_HEADER, "scan: %s", p->str);
- if (strncmpic(p->str, v->str, v->len) == 0)
- {
- err = v->parser(csp, (char **)&(p->str));
+ /* Does the current parser handle this header? */
+ if ((strncmpic(p->str, v->str, v->len) == 0) || (v->len == CHECK_EVERY_HEADER_REMAINING))
+ {
+ err = v->parser(csp, (char **)&(p->str));
+ }
}
}
+ /* place any additional headers on the csp->headers list */
+ for (f = more_headers; (err == JB_ERR_OK) && (*f) ; f++)
+ {
+ err = (*f)(csp);
+ }
}
-
- /* place any additional headers on the csp->headers list */
- for (f = more_headers; (err == JB_ERR_OK) && (*f) ; f++)
+ else /* Parse only */
{
- err = (*f)(csp);
+ /*
+ * The second run is only needed if the body was modified
+ * and the content-lenght has changed.
+ */
+ if (strncmpic(csp->http->cmd, "HEAD", 4))
+ {
+ /*XXX: Code duplication*/
+ for (v = pats; (err == JB_ERR_OK) && (v->str != NULL) ; v++)
+ {
+ for (p = csp->headers->first; (err == JB_ERR_OK) && (p != NULL) ; p = p->next)
+ {
+ /* Header crunch()ed in previous run? -> ignore */
+ if (p->str == NULL) continue;
+
+ /* Does the current parser handle this header? */
+ if (strncmpic(p->str, v->str, v->len) == 0)
+ {
+ err = v->parser(csp, (char **)&(p->str));
+ }
+ }
+ }
+ }
}
if (err != JB_ERR_OK)
/* here begins the family of parser functions that reformat header lines */
+/*********************************************************************
+ *
+ * Function : filter_header
+ *
+ * Description : Executes all text substitutions from all applying
+ * +filter actions on the header.
+ * Most of the code was copied from pcrs_filter_response,
+ * including the rather short variable names
+ *
+ * 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_header(struct client_state *csp, char **header)
+{
+ int hits=0;
+ int matches;
+ size_t size = strlen(*header);
+
+ char *newheader = NULL;
+ pcrs_job *job;
+
+ struct file_list *fl;
+ struct re_filterfile_spec *b;
+ struct list_entry *filtername;
+
+ 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
+
+ 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...
+ */
+ for (i = 0; i < MAX_AF_FILES; i++)
+ {
+ fl = csp->rlist INDEX_OR_NOT;
+ if (NULL != fl)
+ {
+ if (NULL != fl->f)
+ {
+ found_filters = 1;
+ break;
+ }
+ }
+ }
+
+ if (0 == found_filters)
+ {
+ log_error(LOG_LEVEL_ERROR, "Unable to get current state of regexp filtering.");
+ return(JB_ERR_OK);
+ }
+
+ for (i = 0; i < MAX_AF_FILES; i++)
+ {
+ fl = csp->rlist INDEX_OR_NOT;
+ 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
+ * buffer.
+ */
+ for (b = fl->f; b; b = b->next)
+ {
+ for (filtername = csp->action->multi[ACTION_MULTI_FILTER]->first;
+ filtername ; filtername = filtername->next)
+ {
+ if (strcmp(b->name, filtername->str) == 0)
+ {
+ int current_hits = 0;
+
+ if ( NULL == b->joblist )
+ {
+ log_error(LOG_LEVEL_RE_FILTER, "Filter %s has empty joblist. Nothing to do.", b->name);
+ continue;
+ }
+
+ log_error(LOG_LEVEL_RE_FILTER, "re_filtering %s (size %d) with filter %s...",
+ *header, size, b->name);
+
+ /* Apply all jobs from the joblist */
+ for (job = b->joblist; NULL != job; job = job->next)
+ {
+ matches = pcrs_execute(job, *header, size, &newheader, &size);
+ if ( 0 < matches )
+ {
+ current_hits += matches;
+ log_error(LOG_LEVEL_HEADER, "Transforming \"%s\" to \"%s\"", *header, newheader);
+ freez(*header);
+ *header = newheader;
+ }
+ else if ( 0 == matches )
+ {
+ /* Filter doesn't change header */
+ freez(newheader);
+ }
+ else
+ {
+ /* RegEx failure */
+ log_error(LOG_LEVEL_ERROR, "Filtering \'%s\' with \'%s\' didn't work out: %s",
+ *header, b->name, pcrs_strerror(matches));
+ if( newheader != NULL)
+ {
+ log_error(LOG_LEVEL_ERROR, "Freeing what's left: %s", newheader);
+ freez(newheader);
+ }
+ }
+ }
+ log_error(LOG_LEVEL_RE_FILTER, " ...produced %d hits (new size %d).", current_hits, size);
+ hits += current_hits;
+ }
+ }
+ }
+ }
+
+ if ( 0 == size )
+ {
+ 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);
+
+}
+
+
/*********************************************************************
*
* Function : crumble
*********************************************************************/
jb_err crumble(struct client_state *csp, char **header)
{
- log_error(LOG_LEVEL_HEADER, "crunch!");
+ log_error(LOG_LEVEL_HEADER, "crumble crunched: %s!", *header);
freez(*header);
return JB_ERR_OK;
}
+/*********************************************************************
+ *
+ * Function : crunch_server_header
+ *
+ * Description : Crunch server header if it matches a string supplied by the
+ * user. Called from `sed'.
+ *
+ * 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 crunch_server_header(struct client_state *csp, char **header)
+{
+ const char *crunch_pattern;
+ /*Is there a header to crunch*/
+
+ if ((csp->action->flags & ACTION_CRUNCH_SERVER_HEADER))
+ {
+ crunch_pattern = csp->action->string[ACTION_STRING_SERVER_HEADER];
+ /*Is the current header the lucky one?*/
+ if (strstr(*header, crunch_pattern))
+ {
+ log_error(LOG_LEVEL_HEADER, "Crunching server header: %s (contains: %s)", *header, crunch_pattern);
+ freez(*header);
+ }
+ }
+
+ return JB_ERR_OK;
+}
/*********************************************************************
*
* Function : server_content_type
*********************************************************************/
jb_err server_content_type(struct client_state *csp, char **header)
{
+ const char *newval;
+
+ newval = csp->action->string[ACTION_STRING_CONTENT_TYPE];
+
if (csp->content_type != CT_TABOO)
{
if ((strstr(*header, " text/") && !strstr(*header, "plain"))
+ || strstr(*header, "xml")
|| strstr(*header, "application/x-javascript"))
csp->content_type = CT_TEXT;
else if (strstr(*header, " image/gif"))
else
csp->content_type = 0;
}
-
+ /*
+ * Are we enabling text mode by force?
+ */
+ if (csp->action->flags & ACTION_FORCE_TEXT_MODE)
+ {
+ /*
+ * Do we really have to?
+ */
+ if (csp->content_type == CT_TEXT)
+ {
+ log_error(LOG_LEVEL_HEADER, "Text mode is already enabled.");
+ }
+ else
+ {
+ csp->content_type = CT_TEXT;
+ log_error(LOG_LEVEL_HEADER, "Text mode enabled by force. Take cover!");
+ }
+ }
+ /*
+ * Are we messing with the content type?
+ */
+ if (csp->action->flags & ACTION_CONTENT_TYPE_OVERWRITE)
+ {
+ /*
+ * Make sure the user doesn't accidently
+ * change the content type of binary documents.
+ */
+ if (csp->content_type == CT_TEXT)
+ {
+ freez(*header);
+ *header = strdup("Content-Type: ");
+ string_append(header, newval);
+
+ if (header == NULL)
+ {
+ log_error(LOG_LEVEL_HEADER, "Insufficient memory. Conten-Type crunched without replacement!");
+ return JB_ERR_MEMORY;
+ }
+ log_error(LOG_LEVEL_HEADER, "Modified: %s!", *header);
+ }
+ else
+ {
+ log_error(LOG_LEVEL_HEADER, "%s not replaced. It doesn't look like text. "
+ "Enable force-text-mode if you know what you're doing.", *header);
+ }
+ }
return JB_ERR_OK;
}
{
freez(*header);
*header = strdup("Transfer-Encoding: identity");
+ log_error(LOG_LEVEL_HEADER, "Set: %s", *header);
return (header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
}
}
*********************************************************************/
jb_err server_content_length(struct client_state *csp, char **header)
{
- if (csp->content_length != 0) /* Content length has been modified */
+ if (csp->content_length != 0) /* Content length could have been modified */
{
+ /*
+ * XXX: Shouldn't we check if csp->content_length
+ * is different than the original value?
+ */
freez(*header);
*header = (char *) zalloc(100);
if (*header == NULL)
return JB_ERR_OK;
}
+/*********************************************************************
+ *
+ * Function : server_content_disposition
+ *
+ * Description : If enabled, blocks or modifies the "content-disposition" header.
+ * Called from `sed'.
+ *
+ * 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, or
+ * JB_ERR_MEMORY on out-of-memory error.
+ *
+ *********************************************************************/
+jb_err server_content_disposition(struct client_state *csp, char **header)
+{
+ const char *newval;
+
+ /*
+ * Are we messing with the content-disposition header?
+ */
+ if ((csp->action->flags & ACTION_HIDE_CONTENT_DISPOSITION) == 0)
+ {
+ /*Me tinks not*/
+ return JB_ERR_OK;
+ }
+
+ newval = csp->action->string[ACTION_STRING_CONTENT_DISPOSITION];
+
+ if ((newval == NULL) || (0 == strcmpic(newval, "block")) )
+ {
+ /*
+ * Blocking content-disposition header
+ */
+ log_error(LOG_LEVEL_HEADER, "Crunching %s!", *header);
+ freez(*header);
+ return JB_ERR_OK;
+ }
+ else
+ {
+ /*
+ * Replacing content-disposition header
+ */
+ freez(*header);
+ *header = strdup("content-disposition: ");
+ string_append(header, newval);
+
+ if (*header == NULL)
+ {
+ log_error(LOG_LEVEL_HEADER, "Insufficent memory. content-disposition header not fully replaced.");
+ }
+ else
+ {
+ log_error(LOG_LEVEL_HEADER, "content-disposition header crunched and replaced with: %s", *header);
+ }
+ }
+ return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
+}
+
+/*********************************************************************
+ *
+ * Function : server_last_modified
+ *
+ * Description : Changes Last-Modified header to the actual date
+ * to help hide-if-modified-since.
+ * Called from `sed'.
+ *
+ * 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, or
+ * JB_ERR_MEMORY on out-of-memory error.
+ *
+ *********************************************************************/
+jb_err server_last_modified(struct client_state *csp, char **header)
+{
+ const char *newval;
+ char buf[BUFFER_SIZE];
+
+ char newheader[50];
+ struct tm *timeptr;
+ time_t now, last_modified;
+ long int rtime;
+ long int days, hours, minutes, seconds;
+
+ /*
+ * Are we messing with the Last-Modified header?
+ */
+ if ((csp->action->flags & ACTION_OVERWRITE_LAST_MODIFIED) == 0)
+ {
+ /*Nope*/
+ return JB_ERR_OK;
+ }
+
+ newval = csp->action->string[ACTION_STRING_LAST_MODIFIED];
+
+ if (0 == strcmpic(newval, "block") )
+ {
+ /*
+ * Blocking Last-Modified header. Useless but why not.
+ */
+ log_error(LOG_LEVEL_HEADER, "Crunching %s!", *header);
+ freez(*header);
+ return JB_ERR_OK;
+ }
+ else if (0 == strcmpic(newval, "reset-to-request-time"))
+ {
+ /*
+ * Setting Last-Modified Header to now.
+ */
+ get_http_time(0, buf);
+ freez(*header);
+ *header = strdup("Last-Modified: ");
+ string_append(header, buf);
+
+ if (*header == NULL)
+ {
+ log_error(LOG_LEVEL_HEADER, "Insufficent memory. Last-Modified header got lost, boohoo.");
+ }
+ else
+ {
+ log_error(LOG_LEVEL_HEADER, "Reset to present time: %s", *header);
+ }
+ }
+ else if (0 == strcmpic(newval, "randomize"))
+ {
+ 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)
+ {
+ 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 = random() % rtime + 1;
+ last_modified += rtime;
+ timeptr = gmtime(&last_modified);
+ strftime(newheader, sizeof(newheader), "%a, %d %b %Y %T GMT", timeptr);
+ freez(*header);
+ *header = strdup("Last-Modified: ");
+ string_append(header, newheader);
+
+ if (*header == NULL)
+ {
+ log_error(LOG_LEVEL_ERROR, " Insufficent memory, header crunched without replacement.");
+ return JB_ERR_MEMORY;
+ }
+
+ if(LOG_LEVEL_HEADER & debug) /* Save cycles if the user isn't interested. */
+ {
+ days = rtime / (3600 * 24);
+ hours = rtime / 3600 % 24;
+ minutes = rtime / 60 % 60;
+ seconds = rtime % 60;
+
+ log_error(LOG_LEVEL_HEADER, "Randomized: %s (added %d da%s %d hou%s %d minut%s %d second%s",
+ *header, days, (days == 1) ? "y" : "ys", hours, (hours == 1) ? "r" : "rs",
+ minutes, (minutes == 1) ? "e" : "es", seconds, (seconds == 1) ? ")" : "s)");
+ }
+ }
+ else
+ {
+ log_error(LOG_LEVEL_HEADER, "Randomized ... or not. No time difference to work with.");
+ }
+ }
+ }
+
+ return JB_ERR_OK;
+}
/*********************************************************************
*
jb_err client_referrer(struct client_state *csp, char **header)
{
const char *newval;
-
+ const char *host;
+ char *referer;
+ int hostlenght;
+
#ifdef FEATURE_FORCE_LOAD
/* Since the referrer can include the prefix even
- * even if the request itself is non-forced, we must
+ * if the request itself is non-forced, we must
* clean it unconditionally
*/
strclean(*header, FORCE_PREFIX);
return JB_ERR_OK;
}
- freez(*header);
-
newval = csp->action->string[ACTION_STRING_REFERER];
+ if ((0 != strcmpic(newval, "conditional-block")))
+ {
+ freez(*header);
+ }
if ((newval == NULL) || (0 == strcmpic(newval, "block")) )
{
/*
* Blocking referer
*/
- log_error(LOG_LEVEL_HEADER, "crunch!");
+ log_error(LOG_LEVEL_HEADER, "Referer crunched!");
return JB_ERR_OK;
}
- else if (0 == strncmpic(newval, "http://", 7))
+ else if (0 == strcmpic(newval, "conditional-block"))
{
/*
- * We have a specific (fixed) referer we want to send.
+ * Block referer if host has changed.
*/
- log_error(LOG_LEVEL_HEADER, "modified");
+ if (NULL == (host = strdup(csp->http->hostport)))
+ {
+ freez(*header);
+ log_error(LOG_LEVEL_HEADER, "Referer crunched! Couldn't allocate memory for temporary host copy.");
+ return JB_ERR_MEMORY;
+ }
+ if (NULL == (referer = strdup(*header)))
+ {
+ freez(*header);
+ freez(host);
+ log_error(LOG_LEVEL_HEADER, "Referer crunched! Couldn't allocate memory for temporary referer copy.");
+ return JB_ERR_MEMORY;
+ }
+ hostlenght = strlen(host);
+ if ( hostlenght < (strlen(referer)-17) ) /*referer begins with 'Referer: http[s]://'*/
+ {
+ /*Shorten referer to make sure the referer is blocked
+ *if www.example.org/www.example.com-shall-see-the-referer/
+ *links to www.example.com/
+ */
+ referer[hostlenght+17] = '\n';
+ }
+ if ( 0 == strstr(referer, host)) /*Host has changed*/
+ {
+ log_error(LOG_LEVEL_HEADER, "New host is: %s. Crunching %s!", host, *header);
+ freez(*header);
+ }
+ else
+ {
+ log_error(LOG_LEVEL_HEADER, "%s (not modified, still on %s)", *header, host);
+ }
+ freez(referer);
+ freez(host);
+ return JB_ERR_OK;
+ }
+ else if (0 != strcmpic(newval, "forge"))
+ {
+ /*
+ * We have a specific (fixed) referer we want to send.
+ */
+ if ((0 != strncmpic(newval, "http://", 7)) && (0 != strncmpic(newval, "https://", 8)))
+ {
+ log_error(LOG_LEVEL_HEADER, "Parameter: +referrer{%s} is a bad idea, but I don't care.", newval);
+ }
*header = strdup("Referer: ");
string_append(header, newval);
+ log_error(LOG_LEVEL_HEADER, "Referer overwritten with: %s", *header);
return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
}
* Forge a referer as http://[hostname:port of REQUEST]/
* to fool stupid checks for in-site links
*/
- if (0 != strcmpic(newval, "forge"))
- {
- /*
- * Invalid choice - but forge is probably the best default.
- */
- log_error(LOG_LEVEL_ERROR, "Bad parameter: +referer{%s}", newval);
- }
*header = strdup("Referer: http://");
string_append(header, csp->http->hostport);
string_append(header, "/");
- log_error(LOG_LEVEL_HEADER, "crunch+forge to %s", *header);
+ log_error(LOG_LEVEL_HEADER, "Referer forged to: %s", *header);
return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
}
}
+/*********************************************************************
+ *
+ * Function : client_accept_language
+ *
+ * Description : Handle the "Accept-Language" config setting properly.
+ * Called from `sed'.
+ *
+ * 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, or
+ * JB_ERR_MEMORY on out-of-memory error.
+ *
+ *********************************************************************/
+jb_err client_accept_language(struct client_state *csp, char **header)
+{
+ const char *newval;
+
+ /*
+ * Are we messing with the Accept-Language?
+ */
+ if ((csp->action->flags & ACTION_HIDE_ACCEPT_LANGUAGE) == 0)
+ {
+ /*I don't think so*/
+ return JB_ERR_OK;
+ }
+
+ newval = csp->action->string[ACTION_STRING_LANGUAGE];
+
+ if ((newval == NULL) || (0 == strcmpic(newval, "block")) )
+ {
+ /*
+ * Blocking Accept-Language header
+ */
+ log_error(LOG_LEVEL_HEADER, "Crunching Accept-Language!");
+ freez(*header);
+ return JB_ERR_OK;
+ }
+ else
+ {
+ /*
+ * Replacing Accept-Language header
+ */
+ freez(*header);
+ *header = strdup("Accept-Language: ");
+ string_append(header, newval);
+
+ if (*header == NULL)
+ {
+ log_error(LOG_LEVEL_ERROR, " Insufficent memory. Accept-Language header crunched without replacement.");
+ }
+ else
+ {
+ log_error(LOG_LEVEL_HEADER, "Accept-Language header crunched and replaced with: %s", *header);
+ }
+ }
+ return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
+}
+
+/*********************************************************************
+ *
+ * Function : crunch_client_header
+ *
+ * Description : Crunch client header if it matches a string supplied by the
+ * user. Called from `sed'.
+ *
+ * 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 crunch_client_header(struct client_state *csp, char **header)
+{
+ const char *crunch_pattern;
+ /*Is there a header to crunch*/
+
+ if ((csp->action->flags & ACTION_CRUNCH_CLIENT_HEADER))
+ {
+ crunch_pattern = csp->action->string[ACTION_STRING_CLIENT_HEADER];
+
+ /*Is the current header the lucky one?*/
+ if (strstr(*header, crunch_pattern))
+ {
+ log_error(LOG_LEVEL_HEADER, "Crunching client header: %s (contains: %s)", *header, crunch_pattern);
+ freez(*header);
+ }
+ }
+ return JB_ERR_OK;
+}
+
/*********************************************************************
*
return JB_ERR_OK;
}
- log_error(LOG_LEVEL_HEADER, "modified");
-
freez(*header);
*header = strdup("User-Agent: ");
string_append(header, newval);
+ log_error(LOG_LEVEL_HEADER, "Modified: %s", *header);
+
return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
}
-
/*********************************************************************
*
* Function : client_ua
{
if ((csp->action->flags & ACTION_HIDE_USER_AGENT) != 0)
{
- log_error(LOG_LEVEL_HEADER, "crunch!");
+ log_error(LOG_LEVEL_HEADER, "crunched User-Agent!");
freez(*header);
}
*/
if ((newval == NULL) || (0 == strcmpic(newval, "block")) )
{
- log_error(LOG_LEVEL_HEADER, "crunch!");
+ log_error(LOG_LEVEL_HEADER, "crunched From!");
return JB_ERR_OK;
}
else
{
freez(*header);
- log_error(LOG_LEVEL_HEADER, " crunch!");
+ log_error(LOG_LEVEL_HEADER, "crunched x-forwarded-for!");
}
return JB_ERR_OK;
return JB_ERR_OK;
}
+/*********************************************************************
+ *
+ * Function : client_if_modified_since
+ *
+ * Description : Remove or modify the If-Modified-Since header.
+ *
+ * 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, or
+ * JB_ERR_MEMORY on out-of-memory error.
+ *
+ *********************************************************************/
+jb_err client_if_modified_since(struct client_state *csp, char **header)
+{
+ char newheader[50];
+ struct tm *timeptr;
+ time_t tm = 0;
+ const char *newval;
+ time_t rtime;
+ time_t hours, minutes, seconds;
+ int negative = 0;
+ char * endptr;
+
+ if ( 0 == strcmpic(*header, "If-Modified-Since: Wed, 08 Jun 1955 12:00:00 GMT"))
+ {
+ /*
+ * The client got an error message because of a temporary problem,
+ * the problem is gone and the client now tries to revalidate our
+ * error message on the real server. The revalidation would always
+ * end with the transmission of the whole document and there is
+ * no need to expose the bogus If-Modified-Since header.
+ */
+ log_error(LOG_LEVEL_HEADER, "Crunching useless If-Modified-Since header.");
+ freez(*header);
+ }
+ else if (csp->action->flags & ACTION_HIDE_IF_MODIFIED_SINCE)
+ {
+ newval = csp->action->string[ACTION_STRING_IF_MODIFIED_SINCE];
+
+ if ((0 == strcmpic(newval, "block")))
+ {
+ log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
+ freez(*header);
+ }
+ 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)
+ {
+ 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 = random() % rtime;
+
+ if(newval[0] == '-')
+ {
+ rtime *= -1;
+ }
+ tm = timegm(timeptr) + rtime;
+ timeptr = gmtime(&tm);
+ strftime(newheader, sizeof(newheader), "%a, %d %b %Y %T GMT", timeptr);
+
+ freez(*header);
+ *header = strdup("If-Modified-Since: ");
+ string_append(header, newheader);
+
+ if (*header == NULL)
+ {
+ 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 = rtime / 3600 % 24;
+ 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",
+ minutes, (minutes == 1) ? "e" : "es", seconds, (seconds == 1) ? ")" : "s)");
+ }
+ }
+ }
+ }
+
+ return JB_ERR_OK;
+}
+
+/*********************************************************************
+ *
+ * Function : client_if_none_match
+ *
+ * Description : Remove the If-None-Match header.
+ *
+ * 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, or
+ * JB_ERR_MEMORY on out-of-memory error.
+ *
+ *********************************************************************/
+jb_err client_if_none_match(struct client_state *csp, char **header)
+{
+ if (csp->action->flags & ACTION_CRUNCH_IF_NONE_MATCH)
+ {
+ log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
+ freez(*header);
+ }
+
+ return JB_ERR_OK;
+}
+
+/*********************************************************************
+ *
+ * Function : client_x_filter
+ *
+ * Description : Disables filtering if the client set "X-Filter: No".
+ * Called from `sed'.
+ *
+ * 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
+ *
+ *********************************************************************/
+jb_err client_x_filter(struct client_state *csp, char **header)
+{
+ if ( 0 == strcmpic(*header, "X-Filter: No"))
+ {
+ if (csp->action->flags & ACTION_FORCE_TEXT_MODE)
+ {
+ log_error(LOG_LEVEL_HEADER, "force-text-mode overruled the client's request to disable filtering!");
+ }
+ else
+ {
+ csp->content_type = CT_TABOO;
+ log_error(LOG_LEVEL_HEADER, "Disabled filter mode on behalf of the client.");
+ }
+ log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
+ freez(*header);
+ }
+ return JB_ERR_OK;
+}
/* the following functions add headers directly to the header list */
*********************************************************************/
jb_err connection_close_adder(struct client_state *csp)
{
+ log_error(LOG_LEVEL_HEADER, "Adding: Connection: close");
return enlist(csp->headers, "Connection: close");
}
#ifndef PARSERS_H_INCLUDED
#define PARSERS_H_INCLUDED
-#define PARSERS_H_VERSION "$Id: parsers.h,v 1.26.2.1 2002/09/25 14:52:46 oes Exp $"
+#define PARSERS_H_VERSION "$Id: parsers.h,v 1.28 2006/07/18 14:48:47 david__schmidt Exp $"
/*********************************************************************
*
- * File : $Source: /cvsroot/ijbswa/current/Attic/parsers.h,v $
+ * File : $Source: /cvsroot/ijbswa/current/parsers.h,v $
*
* Purpose : Declares functions to parse/crunch headers and pages.
* Functions declared include:
*
* Revisions :
* $Log: parsers.h,v $
+ * 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)
+ *
* Revision 1.26.2.1 2002/09/25 14:52:46 oes
* Added basic support for OPTIONS and TRACE HTTP methods:
* - New parser function client_max_forwards which decrements
extern const struct parsers client_patterns[];
extern const struct parsers server_patterns[];
+extern const struct parsers server_patterns_light[];
extern const add_header_func_ptr add_client_headers[];
extern const add_header_func_ptr add_server_headers[];
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);
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_te (struct client_state *csp, char **header);
extern jb_err client_max_forwards (struct client_state *csp, char **header);
extern jb_err client_host(struct client_state *csp, char **header);
+extern jb_err client_if_modified_since(struct client_state *csp, char **header);
+extern jb_err client_accept_language (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 client_x_filter (struct client_state *csp, char **header);
extern jb_err client_host_adder (struct client_state *csp);
extern jb_err server_content_encoding(struct client_state *csp, char **header);
extern jb_err server_transfer_coding (struct client_state *csp, char **header);
extern jb_err server_http (struct client_state *csp, char **header);
+extern jb_err crunch_server_header (struct client_state *csp, char **header);
+extern jb_err server_last_modified (struct client_state *csp, char **header);
+extern jb_err server_content_disposition(struct client_state *csp, char **header);
#ifdef FEATURE_FORCE_LOAD
extern int strclean(const char *string, const char *substring);
extern const char parsers_rcs[];
extern const char parsers_h_rcs[];
+extern int debug;
+
#ifdef __cplusplus
} /* extern "C" */
#endif
#ifndef PROJECT_H_INCLUDED
#define PROJECT_H_INCLUDED
/** Version string. */
-#define PROJECT_H_VERSION "$Id: project.h,v 1.72.2.7 2006/01/29 23:10:56 david__schmidt Exp $"
+#define PROJECT_H_VERSION "$Id: project.h,v 1.74 2006/07/18 14:48:47 david__schmidt Exp $"
/*********************************************************************
*
- * File : $Source: /cvsroot/ijbswa/current/Attic/project.h,v $
+ * File : $Source: /cvsroot/ijbswa/current/project.h,v $
*
* Purpose : Defines data structures which are widely used in the
* project. Does not define any variables or functions
*
* Revisions :
* $Log: project.h,v $
+ * Revision 1.74 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.72.2.7 2006/01/29 23:10:56 david__schmidt
* Multiple filter file support
*
#define ACTION_JPEG_INSPECT 0x00020000UL
/** Action string index: How to deanimate GIFs */
-#define ACTION_STRING_DEANIMATE 0
+#define ACTION_STRING_DEANIMATE 0
/** Action string index: Replacement for "From:" header */
-#define ACTION_STRING_FROM 1
+#define ACTION_STRING_FROM 1
/** Action string index: How to block images */
-#define ACTION_STRING_IMAGE_BLOCKER 2
+#define ACTION_STRING_IMAGE_BLOCKER 2
/** Action string index: Replacement for "Referer:" header */
-#define ACTION_STRING_REFERER 3
+#define ACTION_STRING_REFERER 3
/** Action string index: Replacement for "User-Agent:" header */
-#define ACTION_STRING_USER_AGENT 4
+#define ACTION_STRING_USER_AGENT 4
/** Action string index: Legal CONNECT ports. */
-#define ACTION_STRING_LIMIT_CONNECT 5
+#define ACTION_STRING_LIMIT_CONNECT 5
+/** Action string index: Server headers containing this pattern are crunched*/
+#define ACTION_STRING_SERVER_HEADER 6
+/** Action string index: Client headers containing this pattern are crunched*/
+#define ACTION_STRING_CLIENT_HEADER 7
+/** Action string index: Replacement for the "Accept-Language:" header*/
+#define ACTION_STRING_LANGUAGE 8
+/** Action string index: Replacement for the "Content-Type:" header*/
+#define ACTION_STRING_CONTENT_TYPE 9
+/** Action string index: Replacement for the "content-dispostion:" header*/
+#define ACTION_STRING_CONTENT_DISPOSITION 10
+/** Action string index: Replacement for the "If-Modified-Since:" header*/
+#define ACTION_STRING_IF_MODIFIED_SINCE 11
+/** Action string index: Replacement for the "Last-Modified:" header. */
+#define ACTION_STRING_LAST_MODIFIED 12
+/** Action string index: Redirect URL */
+#define ACTION_STRING_REDIRECT 13
+/** Action string index: Decode before redirect? */
+#define ACTION_STRING_FAST_REDIRECTS 14
/** Number of string actions. */
-#define ACTION_STRING_COUNT 6
+#define ACTION_STRING_COUNT 15
+
+/*
+ * These defines really belong a few lines higher,
+ * but moving them down here makes this patch apply
+ * against Privoxy 3.0.3 as well.
+ */
+/** Action bitmap: Crunch or modify "if-modified-since" header. */
+#define ACTION_HIDE_IF_MODIFIED_SINCE 0x00040000UL
+/** Action bitmap: Overwrite Content-Type header. */
+#define ACTION_CONTENT_TYPE_OVERWRITE 0x00080000UL
+/** Action bitmap: Crunch specified server header. */
+#define ACTION_CRUNCH_SERVER_HEADER 0x00100000UL
+/** Action bitmap: Crunch specified client header */
+#define ACTION_CRUNCH_CLIENT_HEADER 0x00200000UL
+/** Action bitmap: Enable text mode by force */
+#define ACTION_FORCE_TEXT_MODE 0x00400000UL
+/** Action bitmap: Enable text mode by force */
+#define ACTION_CRUNCH_IF_NONE_MATCH 0x00800000UL
+/** Action bitmap: Enable content-dispostion crunching */
+#define ACTION_HIDE_CONTENT_DISPOSITION 0x01000000UL
+/** Action bitmap: Replace or block Last-Modified header */
+#define ACTION_OVERWRITE_LAST_MODIFIED 0x02000000UL
+/** Action bitmap: Replace or block Accept-Language header */
+#define ACTION_HIDE_ACCEPT_LANGUAGE 0x04000000UL
+/** Action bitmap: Block as empty document */
+#define ACTION_HANDLE_AS_EMPTY_DOCUMENT 0x08000000UL
+/** Action bitmap: Redirect request. */
+#define ACTION_REDIRECT 0x10000000UL
+/** Action bitmap: Answer blocked Connects verbosely */
+#define ACTION_TREAT_FORBIDDEN_CONNECTS_LIKE_BLOCKS 0x20000000UL
+/** Action bitmap: Filter headers with pcre */
+#define ACTION_FILTER_HEADERS 0x40000000UL
+
+
+/*To make the ugly hack in sed easier to understand*/
+#define CHECK_EVERY_HEADER_REMAINING 0
+
/** Index into current_action_spec::multi[] for headers to add. */
#define ACTION_MULTI_ADD_HEADER 0
#
# File : $Source: /cvsroot/ijbswa/current/standard.action,v $
#
-# $Id: standard.action,v 1.2.2.9 2003/04/01 09:49:50 oes Exp $
+# $Id: standard.action,v 1.7 2006/07/18 14:48:47 david__schmidt Exp $
#
# Purpose : Provide prefedined sets of actions, see
# http://www.privoxy.org/user-manual/actions-file.html
+crunch-incoming-cookies \
+deanimate-gifs{last} \
-downgrade-http-version \
-+fast-redirects \
++fast-redirects{check-decoded-url} \
+filter{js-annoyances} \
-filter{js-events} \
+filter{html-annoyances} \
#
# Revisions :
# $Log: edit-actions-for-url,v $
+# Revision 1.34 2006/07/18 14:49:13 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.29.2.5 2004/10/05 03:17:26 david__schmidt
# Typo: inspect_jpegs, not inspect-jpegs in form
#
name="downgrade_http_version" value="N" @downgrade-http-version-n@></td>
<td class="noc1" align="center" valign="middle"><input type="radio"
name="downgrade_http_version" value="X" @downgrade-http-version-x@></td>
- <td class="action"><a href="@user-manual@@actions-help-prefix@DOWNGRADE-HTTP-VERSION">downgrade-http-version</td>
+ <td class="action"><a href="@user-manual@@actions-help-prefix@DOWNGRADE-HTTP-VERSION"
+ >downgrade-http-version</a></td>
<td>Change HTTP/1.1 requests to HTTP/1.0. Only change if you know
what you're doing!</td>
</tr>
<td class="action"><a href="@user-manual@@actions-help-prefix@FAST-REDIRECTS">fast-redirects</a></td>
<td>Bypass some click-tracking URLs.</td>
</tr>
-
+<!--TODO: Document-->
+ <tr class="bg1" align="left" valign="top" id="fast-redirects_opts">
+ <td class="en1"> </td>
+ <td class="dis1"> </td>
+ <td class="noc1"> </td>
+ <td> </td>
+ <td>
+ <input type="radio" name="fast_redirects_mode"
+ value="simple-check" id="fast_redirects_simple_check" @fast-redirects-param-simple-check@><label
+ for="fast_redirects_simple_check">Simple check.</label>
+ <br>
+ <input type="radio" name="fast_redirects_mode" value="check-decoded-url"
+ id="fast_redirects_check_decoded_url" @fast-redirects-param-check-decoded-url@><label
+ for="fast_redirects_check_decoded_url">Decode URL before checking.</label></td>
+ </tr>
+<!--TODO: Document-->
<tr class="bg1" align="left" valign="top">
<td class="en1"> </td>
<td class="dis1" align="center" valign="middle"><input type="radio"
<td class="action"><a href="@user-manual@@actions-help-prefix@HIDE-FORWARDED-FOR-HEADERS">hide-forwarded-for-headers</a></td>
<td>Block any existing X-Forwarded-for header, and do not add a new one.</td>
</tr>
+<!--TODO: Document-->
+ <tr class="bg1" align="left" valign="top">
+ <td class="en1" align="center" valign="middle"><input type="radio"
+ name="hide_if_modified_since" value="Y" @hide-if-modified-since-y@
+ ></td>
+ <td class="dis1" align="center" valign="middle"><input type="radio"
+ name="hide_if_modified_since" value="N" @hide-if-modified-since-n@
+ ></td>
+ <td class="noc1" align="center" valign="middle"><input type="radio"
+ name="hide_if_modified_since" value="X" @hide-if-modified-since-x@
+ ></td>
+ <td class="action"><!--<a href="@user-manual@@actions-help-prefix@HIDE_IF_MODIFIED_SINCE">-->hide-if-modified-since<!--</a>--></td>
+ <td>Remove or randomize If-Modified-Since header.</td>
+ </tr>
+ <tr class="bg1" align="left" valign="top" id="hide_if-modifed-since_opts">
+ <td class="en1"> </td>
+ <td class="dis1"> </td>
+ <td class="noc1"> </td>
+ <td> </td>
+ <td><input type="radio" name="hide_if_modified_since_mode" value="block"
+ onclick="hide_if_modified_since_param_disable(true)"
+ @hide-if-modified-since-param-block@ id="hide_if_modified_since_mode_block"><label
+ for="hide_if_modified_since_mode_block">Remove without replacement.</label>
+ Useful for filter testing.<br>
+ <input type="radio" name="hide_if_modified_since_mode" value="CUSTOM"
+ onclick="hide_if_modified_since_param_disable(true)"
+ @hide-if-modified-since-param-custom@ id="hide_if_modified_since_mode_set"><label
+ for="hide_if_modified_since_mode_set">Add random amount of seconds in the range of</label>
+ <input type="text" name="hide_if_modified_since_param"
+ id="hide_if_modified_since_param" size="4"
+ value="@hide-if-modified-since-param@"> hour(s).
+ To appreciate this option a small amount of paranoia is required,
+ but at least in theory the If-Modified-Since header could be used
+ to keep track of your visits.
+ </td>
+ </tr>
+ <!-- -->
+ <tr class="bg1" align="left" valign="top">
+ <td class="en1" align="center" valign="middle"><input type="radio"
+ name="overwrite_last_modified" value="Y" @overwrite-last-modified-y@
+ ></td>
+ <td class="dis1" align="center" valign="middle"><input type="radio"
+ name="overwrite_last_modified" value="N" @overwrite-last-modified-n@
+ ></td>
+ <td class="noc1" align="center" valign="middle"><input type="radio"
+ name="overwrite_last_modified" value="X" @overwrite-last-modified-x@
+ ></td>
+ <td class="action"><!--<a href="@user-manual@@actions-help-prefix@OVERWRITE_LAST_MODIFIED">-->overwrite-last-modified<!--</a>--></td>
+ <td>Remove or randomize If-Modified-Since header.</td>
+ </tr>
+ <tr class="bg1" align="left" valign="top" id="overwrite_last_modified_opts">
+ <td class="en1"> </td>
+ <td class="dis1"> </td>
+ <td class="noc1"> </td>
+ <td> </td>
+ <td><input type="radio" name="overwrite_last_modified_mode" value="block"
+ onclick="overwrite_last_modified_param_disable(true)"
+ @overwrite-last-modified-param-block@ id="overwrite_last_modified_mode_block"><label
+ for="overwrite_last_modified_mode_block">Remove without replacement.</label>
+ <strong>Useless</strong>.<br>
+ <input type="radio" name="overwrite_last_modified_mode" value="reset-to-request-time"
+ onclick="overwrite_last_modified_param_disable(true)"
+ @overwrite-last-modified-param-reset-to-request-time@
+ id="overwrite_last_modified_mode_reset-to-request-time"><label
+ for="overwrite_last_modified_mode_reset-to-request-time">Reset to the time of the request.</label>
+ <br>
+ <input type="radio" name="overwrite_last_modified_mode" value="randomize"
+ onclick="overwrite_last_modified_param_disable(true)"
+ @overwrite-last-modified-param-randomize@
+ id="overwrite_last_modified_mode_randomize"><label
+ for="overwrite_last_modified_mode_randomize">Overwrite with random value
+ between original header value and the time of the request.</label>
+ <br>
+ <!--
+ <input type="radio" name="overwrite_last_modified_mode" value="CUSTOM"
+ onclick="overwrite_last_modified_param_disable(true)"
+ @overwrite-last-modified-param-custom@ id="overwrite_last_modified_mode_set"><label
+ for="overwrite_last_modified_mode_set">Add random amount of seconds in the range of</label>
+ <input type="text" name="overwrite_last_modified_param"
+ id="overwrite_last_modified_param" size="4"
+ value="@overwrite-last-modified-param@"> hour(s).
+ To appreciate this option a small amount of paranoia is required,
+ but at least in theory the If-Modified-Since header could be used
+ to keep track of your visits.-->
+ </td>
+ </tr>
+ <tr class="bg1" align="left" valign="top">
+ <td class="en1" align="center" valign="middle"><input type="radio"
+ name="crunch_if_none_match" value="Y" @crunch-if-none-match-y@
+ ></td>
+ <td class="dis1" align="center" valign="middle"><input type="radio"
+ name="crunch_if_none_match" value="N" @crunch-if-none-match-n@
+ ></td>
+ <td class="noc1" align="center" valign="middle"><input type="radio"
+ name="crunch_if_none_match" value="X" @crunch-if-none-match-x@
+ ></td>
+ <td class="action"><!--<a href="@user-manual@@actions-help-prefix@CRUNCH_IF_NONE_MATCH">-->crunch-if-none-match<!--</a>--></td>
+ <td>Remove If-None-Match header to circumvent browser cache. Useful for filter testing,
+ but hurts performance.</td>
+ </tr>
+ <tr class="bg1" align="left" valign="top">
+ <td class="en1" align="center" valign="middle"><input type="radio"
+ name="content_type_overwrite" value="Y" @content-type-overwrite-y@
+ ></td>
+ <td class="dis1" align="center" valign="middle"><input type="radio"
+ name="content_type_overwrite" value="N" @content-type-overwrite-n@
+ ></td>
+ <td class="noc1" align="center" valign="middle"><input type="radio"
+ name="content_type_overwrite" value="X" @content-type-overwrite-x@
+ ></td>
+ <td class="action"><!--<a href="@user-manual@@actions-help-prefix@CONTENT_TYPE_OVERWRITE">-->content-type-overwrite<!--</a>--></td>
+ <td>Replace Content-Type header. Useful to let the browser render broken
+ <abbr title="EXtensible HyperText Markup Language">XHTML</abbr> as broken
+ <abbr title="HyperText Markup Language">HTML</abbr>. By default it only applies to
+ text documents, if you know what you're doing you
+ can enable force-text-mode to modify binary content types as well.</td>
+ </tr>
+ <tr class="bg1" align="left" valign="top" id="content_type_overwrite_opts">
+ <td class="en1"> </td>
+ <td class="dis1"> </td>
+ <td class="noc1"> </td>
+ <td> </td>
+ <td>New Content-Type:<br>
+ <input type="text" name="content_type_overwrite_mode" size="40"
+ value="@content-type-overwrite-param@"></td>
+ </tr>
+
+ <tr class="bg1" align="left" valign="top">
+ <td class="en1" align="center" valign="middle"><input type="radio"
+ name="force_text_mode" value="Y" @force-text-mode-y@
+ ></td>
+ <td class="dis1" align="center" valign="middle"><input type="radio"
+ name="force_text_mode" value="N" @force-text-mode-n@
+ ></td>
+ <td class="noc1" align="center" valign="middle"><input type="radio"
+ name="force_text_mode" value="X" @force-text-mode-x@
+ ></td>
+ <td class="action"><!--<a href="@user-manual@@actions-help-prefix@FORCE_TEXT_MODE">-->force-text-mode<!--</a>--></td>
+ <td>
+ Enable filtering on documents whose Content-Type wasn't recognized as text.
+ Do think twice, nothing is alright.
+ </td>
+ </tr>
+ <tr class="bg1" align="left" valign="top">
+ <td class="en1" align="center" valign="middle"><input type="radio"
+ name="handle_as_empty_document" value="Y" @handle-as-empty-document-y@
+ ></td>
+ <td class="dis1" align="center" valign="middle"><input type="radio"
+ name="handle_as_empty_document" value="N" @handle-as-empty-document-n@
+ ></td>
+ <td class="noc1" align="center" valign="middle"><input type="radio"
+ name="handle_as_empty_document" value="X" @handle-as-empty-document-x@
+ ></td>
+ <td class="action"><!--<a href="@user-manual@@actions-help-prefix@HANDLE_AS_EMPTY_DOCUMENT">-->handle-as-empty-document<!--</a>--></td>
+ <td>
+ Block with an <em>empty</em> document instead of an Image or HTML message.
+ The <em>empty</em> document contains only a space and can safely be parsed
+ as JavaScript or Style Sheet. Use content-type-overwrite to specify the
+ Content-Type, default is <q>test/html</q>.
+ </td>
+ </tr>
+ <tr class="bg1" align="left" valign="top">
+ <td class="en1" align="center" valign="middle"><input type="radio"
+ name="treat_forbidden_connects_like_blocks" value="Y" @treat-forbidden-connects-like-blocks-y@
+ ></td>
+ <td class="dis1" align="center" valign="middle"><input type="radio"
+ name="treat_forbidden_connects_like_blocks" value="N" @treat-forbidden-connects-like-blocks-n@
+ ></td>
+ <td class="noc1" align="center" valign="middle"><input type="radio"
+ name="treat_forbidden_connects_like_blocks" value="X" @treat-forbidden-connects-like-blocks-x@
+ ></td>
+ <td class="action"><!--<a href="@user-manual@@actions-help-prefix@TREAT_FORBIDDEN_CONNECTS_LIKE_BLOCKS">-->treat-forbidden-connects-like-blocks<!--</a>--></td>
+ <td>
+ Answer forbidden Connect requests with the usual block message.
+ May be a protocol violation, but makes unblocking easier.
+ </td>
+ </tr>
+<!--crunch-client-header-->
+ <tr class="bg1" align="left" valign="top">
+ <td class="en1" align="center" valign="middle"><input type="radio"
+ name="crunch_client_header" id="crunch_client_header_y" value="Y" @crunch-client-header-y@
+ ></td>
+ <td class="dis1" align="center" valign="middle"><input type="radio"
+ name="crunch_client_header" value="N" @crunch-client-header-n@
+ ></td>
+ <td class="noc1" align="center" valign="middle"><input type="radio"
+ name="crunch_client_header" value="X" @crunch-client-header-x@
+ ></td>
+ <td class="action"><!--<a href="@user-manual@@actions-help-prefix@CRUNCH-CLIENT-HEADER">-->crunch-client-header<!--</a>--></td>
+ <td>Remove header(s) matching the supplied pattern. Together with add-header you can
+ build a custom header replacement action.</td>
+ </tr>
+ <tr class="bg1" align="left" valign="top" id="crunch_client_header_opts">
+ <td class="en1"> </td>
+ <td class="dis1"> </td>
+ <td class="noc1"> </td>
+ <td> </td>
+ <td>Header string to suppress:<br>
+ <input type="text" name="crunch_client_header_mode" size="40"
+ value="@crunch-client-header-param@"></td>
+ </tr>
+<!--/crunch-client-header-->
+<!--crunch-server-header-->
+ <tr class="bg1" align="left" valign="top">
+ <td class="en1" align="center" valign="middle"><input type="radio"
+ name="crunch_server_header" id="crunch_server_header_y" value="Y" @crunch-server-header-y@
+ ></td>
+ <td class="dis1" align="center" valign="middle"><input type="radio"
+ name="crunch_server_header" value="N" @crunch-server-header-n@
+ ></td>
+ <td class="noc1" align="center" valign="middle"><input type="radio"
+ name="crunch_server_header" value="X" @crunch-server-header-x@
+ ></td>
+ <td class="action"><!--<a href="@user-manual@@actions-help-prefix@CRUNCH-SERVER-HEADER">-->crunch-server-header<!--</a>--></td>
+ <td>Remove server header(s) matching the supplied pattern.</td>
+ </tr>
+ <tr class="bg1" align="left" valign="top" id="crunch_server_header_opts">
+ <td class="en1"> </td>
+ <td class="dis1"> </td>
+ <td class="noc1"> </td>
+ <td> </td>
+ <td>Header string to suppress:<br>
+ <input type="text" name="crunch_server_header_mode" size="40"
+ value="@crunch-server-header-param@"></td>
+ </tr>
+<!--/crunch-server-header-->
+ <tr class="bg1" align="left" valign="top">
+ <td class="en1" align="center" valign="middle"><input type="radio"
+ name="hide_accept_language" id="hide_accept_language_y" value="Y" @hide-accept-language-y@
+ onclick="show_hide_accept_language_opts(true)"></td>
+ <td class="dis1" align="center" valign="middle"><input type="radio"
+ name="hide_accept_language" id="hide_accept_language_n" value="N" @hide-accept-language-n@
+ onclick="show_hide_accept_language_opts(false)"></td>
+ <td class="noc1" align="center" valign="middle"><input type="radio"
+ name="hide_accept_language" id="hide_accept_language_x" value="X" @hide-accept-language-x@
+ onclick="show_hide_accept_language_opts(false)"
+ ></td>
+ <td class="action"><!--<a href="@user-manual@@actions-help-prefix@HIDE-ACCEPT-LANGUAGE">-->hide-accept-language<!--</a>--></td>
+ <td>Pretend to have different language settings. (Makes a fake User-Agent more believable,
+ but can lead to foreign content.)</td>
+ </tr>
+ <tr class="bg1" align="left" valign="top" id="hide_accept-language_opts">
+ <td class="en1"> </td>
+ <td class="dis1"> </td>
+ <td class="noc1"> </td>
+ <td> </td>
+ <td><input type="radio" name="hide_accept_language_mode" value="block"
+ onclick="hide_accept_language_param_disable(true)"
+ @hide-accept-language-param-block@ id="hide_accept_language_mode_block"><label
+ for="hide_accept_language_mode_block">Remove Accept-Language header without replacement.</label>
+ This isn't the option you're looking for.<br>
+ <input type="radio" name="hide_accept_language_mode" value="CUSTOM"
+ onclick="hide_accept_language_param_disable(false)"
+ @hide-accept-language-param-custom@ id="hide_accept_language_mode_set"><label
+ for="hide_accept_language_mode_set">Fake these language settings:</label><br>
+ <input type="text" name="hide_accept_language_param"
+ id="hide_accept_language_param" size="40"
+ value="@hide-accept-language-param@"><br>
+ </td>
+<!--content-dispostion-->
+ </tr> <tr class="bg1" align="left" valign="top">
+ <td class="en1" align="center" valign="middle"><input type="radio"
+ name="hide_content_disposition" id="hide_content_disposition_y" value="Y" @hide-content-disposition-y@
+ onclick="show_hide_content_disposition_opts(true)"></td>
+ <td class="dis1" align="center" valign="middle"><input type="radio"
+ name="hide_content_disposition" id="hide_content_disposition_n" value="N" @hide-content-disposition-n@
+ onclick="show_hide_content_disposition_opts(false)"></td>
+ <td class="noc1" align="center" valign="middle"><input type="radio"
+ name="hide_content_disposition" id="hide_content_disposition_x" value="X" @hide-content-disposition-x@
+ onclick="show_hide_content_disposition_opts(false)"
+ ></td>
+ <td class="action"><!--<a href="@user-manual@@actions-help-prefix@HIDE-CONTENT-DISPOSITION">-->hide-content-disposition<!--</a>--></td>
+ <td>Block or overwrite the content-disposition header. Useful to view a document inside the browser,
+ even if you were supposed to save it first, or to change the suggested file name.</td>
+ </tr>
+ <tr class="bg1" align="left" valign="top" id="hide_content_disposition_opts">
+ <td class="en1"> </td>
+ <td class="dis1"> </td>
+ <td class="noc1"> </td>
+ <td> </td>
+ <td><input type="radio" name="hide_content_disposition_mode" value="block"
+ onclick="hide_content_disposition_param_disable(true)"
+ @hide-content-disposition-param-block@ id="hide_content_disposition_mode_block"><label
+ for="hide_content_disposition_mode_block">Remove content-disposition header without replacement.</label>
+ <br>
+ <input type="radio" name="hide_content_disposition_mode" value="CUSTOM"
+ onclick="hide_content_disposition_param_disable(false)"
+ @hide-content-disposition-param-custom@ id="hide_content_disposition_mode_set"><label
+ for="hide_content_disposition_mode_set">Overwrite content-dispostion header with:</label><br>
+ <input type="text" name="hide_content_disposition_param"
+ id="hide_content_disposition_param" size="40"
+ value="@hide-content-disposition-param@"><br>
+ </td>
+ </tr>
+ <tr class="bg1" align="left" valign="top">
+ <td class="en1" align="center" valign="middle"><input type="radio"
+ name="redirect" value="Y" @redirect-y@
+ ></td>
+ <td class="dis1" align="center" valign="middle"><input type="radio"
+ name="redirect" value="N" @redirect-n@
+ ></td>
+ <td class="noc1" align="center" valign="middle"><input type="radio"
+ name="redirect" value="X" @redirect-x@
+ ></td>
+ <td class="action"><!--<a href="@user-manual@@actions-help-prefix@REDIRECT">-->redirect<!--</a>--></td>
+ <td>Redirect to another address.
+ </tr>
+ <tr class="bg1" align="left" valign="top" id="redirect_opts">
+ <td class="en1"> </td>
+ <td class="dis1"> </td>
+ <td class="noc1"> </td>
+ <td> </td>
+ <td>Address to redirect to:<br>
+ <input type="text" name="redirect_mode" size="40"
+ value="@redirect-param@"></td>
+ </tr>
+
+ <tr class="bg1" align="left" valign="top">
+ <td class="en1" align="center" valign="middle"><input type="radio"
+ name="filter_headers" value="Y" @filter-headers-y@
+ ></td>
+ <td class="dis1" align="center" valign="middle"><input type="radio"
+ name="filter_headers" value="N" @filter-headers-n@
+ ></td>
+ <td class="noc1" align="center" valign="middle"><input type="radio"
+ name="filter_headers" value="X" @filter-headers-x@
+ ></td>
+ <td class="action"><!--<a href="@user-manual@@actions-help-prefix@FILTER-HEADERS">-->filter-headers<!--</a>--></td>
+ <td>Apply filters to the headers as well. <strong>Only enable this if you know what you're doing.</strong></td>
+ </tr>
+
+
+
+<!--TODO: Document-->
<tr class="bg1" align="left" valign="top">
<td class="en1" align="center" valign="middle"><input type="radio"
name="hide_from_header" id="hide_from_header_y" value="Y" @hide-from-header-y@
for="hide_referrer_mode_set">Fake as this web address:</label><br>
<input type="text" name="hide_referrer_param"
id="hide_referrer_param" size="40"
- value="@hide-referrer-param@"></td>
+ value="@hide-referrer-param@"><br>
+<!--TODO: Document-->
+ <input type="radio" name="hide_referrer_mode" value="conditional-block"
+ onclick="hide_referrer_param_disable(true)"
+ @hide-referrer-param-conditional-block@ id="hide_referrer_mode_conditional-block"><label
+ for="hide_referrer_mode_conditional-block">Remove completely if host has changed,
+ but don't touch in-site referrers.
+ Less suspicious than the options above.</label><br></td>
+<!--TODO: Document-->
</tr>
<tr class="bg1" align="left" valign="top">
<td class="en1" align="center" valign="middle"><input type="radio"
<td class="noc1" align="center" valign="middle"><input type="radio"
name="kill_popups" value="X" @kill-popups-x@
></td>
- <td class="action"><a href="@user-manual@@actions-help-prefix@KILL-POPUPS">kill-popups</td>
+ <td class="action"><a href="@user-manual@@actions-help-prefix@KILL-POPUPS">kill-popups</a></td>
<td>Filter the website through a built-in filter to disable many JavaScript
pop-up windows.</td>
</tr>