-const char filters_rcs[] = "$Id: filters.c,v 1.122 2009/06/08 16:48:09 fabiankeil Exp $";
+const char filters_rcs[] = "$Id: filters.c,v 1.140 2011/03/03 14:47:28 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/filters.c,v $
* `execute_single_pcrs_command', `rewrite_url',
* `get_last_url'
*
- * Copyright : Written by and Copyright (C) 2001, 2004-2009 the
+ * Copyright : Written by and Copyright (C) 2001-2010 the
* Privoxy team. http://www.privoxy.org/
*
* Based on the Internet Junkbuster originally written
#include <string.h>
#include <assert.h>
-#ifdef HAVE_RFC2553
-#include <netdb.h>
-#include <sys/socket.h>
-#endif /* def HAVE_RFC2553 */
-
#ifndef _WIN32
#ifndef __OS2__
#include <unistd.h>
*/
#define ijb_isdigit(__X) isdigit((int)(unsigned char)(__X))
+typedef char *(*filter_function_ptr)();
+static filter_function_ptr get_filter_function(const struct client_state *csp);
static jb_err remove_chunked_transfer_coding(char *buffer, size_t *size);
static jb_err prepare_for_filtering(struct client_state *csp);
{
return(0);
}
+ else
+ {
+ return(1);
+ }
}
else if (
#ifdef HAVE_RFC2553
hints.ai_socktype = SOCK_STREAM;
i = getaddrinfo(acl_spec, ((p) ? ++p : NULL), &hints, &result);
- freez(acl_spec);
if (i != 0)
{
log_error(LOG_LEVEL_ERROR, "Can not resolve [%s]:%s: %s",
acl_spec, p, gai_strerror(i));
+ freez(acl_spec);
return(-1);
}
+ freez(acl_spec);
/* TODO: Allow multihomed hostnames */
memcpy(&(aca->addr), result->ai_addr, result->ai_addrlen);
{
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")))
return cgi_error_memory();
}
}
-
else if (0 == strcmpic(p, "blank"))
{
rsp->status = strdup("403 Request blocked by Privoxy");
return cgi_error_memory();
}
}
-
else
{
rsp->status = strdup("302 Local Redirect from Privoxy");
}
}
-#else /* Following code is disabled for now */
-
- /* and handle accordingly: */
- if ((p == NULL) || (0 == strcmpic(p, "pattern")))
- {
- p = CGI_PREFIX "send-banner?type=pattern";
- }
- else if (0 == strcmpic(p, "blank"))
- {
- p = CGI_PREFIX "send-banner?type=blank";
- }
- rsp->status = strdup("302 Local Redirect from Privoxy");
- if (rsp->status == NULL)
- {
- free_http_response(rsp);
- return cgi_error_memory();
- }
-
- if (enlist_unique_header(rsp->headers, "Location", p))
- {
- free_http_response(rsp);
- return cgi_error_memory();
- }
-#endif /* Preceeding code is disabled for now */
}
- else if(csp->action->flags & ACTION_HANDLE_AS_EMPTY_DOCUMENT)
+ else
+#endif /* def FEATURE_IMAGE_BLOCKING */
+ if(csp->action->flags & ACTION_HANDLE_AS_EMPTY_DOCUMENT)
{
/*
* Send empty document.
rsp->body = strdup(" ");
rsp->content_length = 1;
- rsp->status = strdup("403 Request blocked by Privoxy");
+ if (csp->config->feature_flags & RUNTIME_FEATURE_EMPTY_DOC_RETURNS_OK)
+ {
+ /*
+ * Workaround for firefox bug 492459
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=492459
+ * Return a 200 OK status for pages blocked with +handle-as-empty-document
+ * if the "handle-as-empty-doc-returns-ok" runtime config option is set.
+ */
+ rsp->status = strdup("200 Request blocked by Privoxy");
+ }
+ else
+ {
+ rsp->status = strdup("403 Request blocked by Privoxy");
+ }
+
if (rsp->status == NULL)
{
free_http_response(rsp);
}
}
else
-#endif /* def FEATURE_IMAGE_BLOCKING */
/*
* Else, generate an HTML "blocked" message:
&& !strstr(p, "compatible") /* MSIE */
&& !strstr(p, "Opera")) /* and Opera. */
{
- rsp->status = strdup("200 Request for blocked URL");
+ rsp->status = strdup("200 Request blocked by Privoxy");
}
else
{
- rsp->status = strdup("403 Request for blocked URL");
+ rsp->status = strdup("403 Request blocked by Privoxy");
}
if (rsp->status == NULL)
return cgi_error_memory();
}
}
- rsp->reason = RSP_REASON_BLOCKED;
+ rsp->crunch_reason = BLOCKED;
return finish_http_response(csp, rsp);
free_http_response(rsp);
return cgi_error_memory();
}
- rsp->reason = RSP_REASON_UNTRUSTED;
+ rsp->crunch_reason = UNTRUSTED;
return finish_http_response(csp, rsp);
}
dummy = pcrs_compile_dynamic_command(pattern->str, variables, &error);
if (NULL == dummy)
{
- assert(error < 0);
log_error(LOG_LEVEL_ERROR,
- "Adding filter job \'%s\' to dynamic filter %s failed: %s",
- pattern->str, b->name, pcrs_strerror(error));
+ "Compiling dynamic pcrs job '%s' for '%s' failed with error code %d: %s",
+ pattern->str, b->name, error, pcrs_strerror(error));
continue;
}
else
free_http_response(rsp);
return cgi_error_memory();
}
- rsp->reason = RSP_REASON_REDIRECTED;
+ rsp->crunch_reason = REDIRECTED;
freez(new_url);
return finish_http_response(csp, rsp);
*********************************************************************/
static char *pcrs_filter_response(struct client_state *csp)
{
- int hits=0;
+ int hits = 0;
+ int i;
size_t size, prev_size;
char *old = NULL;
struct re_filterfile_spec *b;
struct list_entry *filtername;
- int i, found_filters = 0;
-
/*
* Sanity first
*/
return(NULL);
}
- /*
- * Need to check the set of re_filterfiles...
- */
- for (i = 0; i < MAX_AF_FILES; i++)
- {
- fl = csp->rlist[i];
- if (NULL != fl)
- {
- if (NULL != fl->f)
- {
- found_filters = 1;
- break;
- }
- }
- }
-
- if (0 == found_filters)
+ if (filters_available(csp) == FALSE)
{
log_error(LOG_LEVEL_ERROR, "Inconsistent configuration: "
"content filtering enabled, but no content filters available.");
* NULL if no content filter is active
*
*********************************************************************/
-filter_function_ptr get_filter_function(struct client_state *csp)
+static filter_function_ptr get_filter_function(const struct client_state *csp)
{
filter_function_ptr filter_function = NULL;
- if ((csp->content_type & CT_TABOO)
- && !(csp->action->flags & ACTION_FORCE_TEXT_MODE))
- {
- return NULL;
- }
-
- /*
- * 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!");
- }
- }
-
- if (!(csp->content_type & CT_DECLARED))
- {
- /*
- * The server didn't bother to declare a MIME-Type.
- * Assume it's text that can be filtered.
- *
- * This also regulary happens with 304 responses,
- * therefore logging anything here would cause
- * too much noise.
- */
- csp->content_type |= CT_TEXT;
- }
-
/*
* Choose the applying filter function based on
* the content type and action settings.
if ((newsize += chunksize) >= *size)
{
+ /*
+ * XXX: The message is a bit confusing. Isn't the real problem that
+ * the specified chunk size is greater than the number of bytes
+ * left in the buffer? This probably means the connection got
+ * closed prematurely. To be investigated after 3.0.17 is out.
+ */
log_error(LOG_LEVEL_ERROR,
- "Chunk size %d exceeds buffer size %d in \"chunked\" transfer coding",
+ "Chunk size %d exceeds buffer size %d in \"chunked\" transfer coding",
chunksize, *size);
return JB_ERR_PARSE;
}
/*********************************************************************
*
- * Function : execute_content_filter
+ * Function : execute_content_filters
*
* Description : Executes a given content filter.
*
* Parameters :
* 1 : csp = Current client state (buffers, headers, etc...)
- * 2 : content_filter = The filter function to execute
*
* Returns : Pointer to the modified buffer, or
* NULL if filtering failed or wasn't necessary.
*
*********************************************************************/
-char *execute_content_filter(struct client_state *csp, filter_function_ptr content_filter)
+char *execute_content_filters(struct client_state *csp)
{
+ filter_function_ptr content_filter;
+
+ assert(content_filters_enabled(csp->action));
+
if (0 == csp->iob->eod - csp->iob->cur)
{
/*
return NULL;
}
+ content_filter = get_filter_function(csp);
+
return ((*content_filter)(csp));
}
}
rsp->is_static = 1;
- rsp->reason = RSP_REASON_UNSUPPORTED;
+ rsp->crunch_reason = UNSUPPORTED;
return(finish_http_response(csp, rsp));
}
}
+/*********************************************************************
+ *
+ * Function : content_requires_filtering
+ *
+ * Description : Checks whether there are any content filters
+ * enabled for the current request and if they
+ * can actually be applied..
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : TRUE for yes, FALSE otherwise
+ *
+ *********************************************************************/
+int content_requires_filtering(struct client_state *csp)
+{
+ if ((csp->content_type & CT_TABOO)
+ && !(csp->action->flags & ACTION_FORCE_TEXT_MODE))
+ {
+ return FALSE;
+ }
+
+ /*
+ * 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!");
+ }
+ }
+
+ if (!(csp->content_type & CT_DECLARED))
+ {
+ /*
+ * The server didn't bother to declare a MIME-Type.
+ * Assume it's text that can be filtered.
+ *
+ * This also regulary happens with 304 responses,
+ * therefore logging anything here would cause
+ * too much noise.
+ */
+ csp->content_type |= CT_TEXT;
+ }
+
+ /*
+ * Choose the applying filter function based on
+ * the content type and action settings.
+ */
+ if ((csp->content_type & CT_TEXT) &&
+ (csp->rlist != NULL) &&
+ (!list_is_empty(csp->action->multi[ACTION_MULTI_FILTER])))
+ {
+ return TRUE;
+ }
+ else if ((csp->content_type & CT_GIF) &&
+ (csp->action->flags & ACTION_DEANIMATE))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+
/*********************************************************************
*
* Function : content_filters_enabled
!list_is_empty(action->multi[ACTION_MULTI_FILTER]));
}
+
+/*********************************************************************
+ *
+ * Function : filters_available
+ *
+ * Description : Checks whether there are any filters available.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : TRUE for yes, FALSE otherwise.
+ *
+ *********************************************************************/
+int filters_available(const struct client_state *csp)
+{
+ int i;
+ for (i = 0; i < MAX_AF_FILES; i++)
+ {
+ const struct file_list *fl = csp->rlist[i];
+ if ((NULL != fl) && (NULL != fl->f))
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
/*
Local Variables:
tab-width: 3