-const char filters_rcs[] = "$Id: filters.c,v 1.88 2007/06/01 16:41:11 fabiankeil Exp $";
+const char filters_rcs[] = "$Id: filters.c,v 1.107 2008/05/04 17:52:56 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/filters.c,v $
* `filter_popups', `forward_url', 'redirect_url',
* `ij_untrusted_url', `intercept_url', `pcrs_filter_respose',
* `ijb_send_banner', `trust_url', `gif_deanimate_response',
- * `jpeg_inspect_response', `execute_single_pcrs_command',
- * `rewrite_url', `get_last_url'
+ * `execute_single_pcrs_command', `rewrite_url',
+ * `get_last_url'
*
- * Copyright : Written by and Copyright (C) 2001, 2004-2007 the SourceForge
+ * Copyright : Written by and Copyright (C) 2001, 2004-2008 the SourceForge
* Privoxy team. http://www.privoxy.org/
*
* Based on the Internet Junkbuster originally written
*
* Revisions :
* $Log: filters.c,v $
+ * Revision 1.107 2008/05/04 17:52:56 fabiankeil
+ * Adjust parse_http_url() call to new prototype.
+ *
+ * Revision 1.106 2008/05/03 16:40:44 fabiankeil
+ * Change content_filters_enabled()'s parameter from
+ * csp->action to action so it can be also used in the
+ * CGI code. Don't bother checking if there are filters
+ * loaded, as that's somewhat besides the point.
+ *
+ * Revision 1.105 2008/03/28 15:13:39 fabiankeil
+ * Remove inspect-jpegs action.
+ *
+ * Revision 1.104 2008/03/27 18:27:24 fabiankeil
+ * Remove kill-popups action.
+ *
+ * Revision 1.103 2008/03/06 16:33:45 fabiankeil
+ * If limit-connect isn't used, don't limit CONNECT requests to port 443.
+ *
+ * Revision 1.102 2008/03/01 14:00:44 fabiankeil
+ * Let the block action take the reason for the block
+ * as argument and show it on the "blocked" page.
+ *
+ * Revision 1.101 2008/02/23 16:57:12 fabiankeil
+ * Rename url_actions() to get_url_actions() and let it
+ * use the standard parameter ordering.
+ *
+ * Revision 1.100 2008/02/23 16:33:43 fabiankeil
+ * Let forward_url() use the standard parameter ordering
+ * and mark its second parameter immutable.
+ *
+ * Revision 1.99 2008/02/03 13:57:58 fabiankeil
+ * Add SOCKS5 support for forward-override{}.
+ *
+ * Revision 1.98 2008/01/04 17:43:45 fabiankeil
+ * Improve the warning messages that get logged if the action files
+ * "enable" filters but no filters of that type have been loaded.
+ *
+ * Revision 1.97 2007/11/30 15:37:03 fabiankeil
+ * Use freez instead of free.
+ *
+ * Revision 1.96 2007/10/19 16:53:28 fabiankeil
+ * Add helper function to check if any content filters are enabled.
+ *
+ * Revision 1.95 2007/10/17 19:31:20 fabiankeil
+ * Omitting the zero chunk that ends the chunk transfer encoding seems
+ * to be the new black. Log the problem and continue filtering anyway.
+ *
+ * Revision 1.94 2007/09/29 13:20:20 fabiankeil
+ * Remove two redundant and one useless log messages.
+ *
+ * Revision 1.93 2007/09/29 10:21:16 fabiankeil
+ * - Move get_filter_function() from jcc.c to filters.c
+ * so the filter functions can be static.
+ * - Don't bother filtering body-less responses.
+ *
+ * Revision 1.92 2007/09/28 16:38:55 fabiankeil
+ * - Execute content filters through execute_content_filter().
+ * - Add prepare_for_filtering() so filter functions don't have to
+ * care about de-chunking and decompression. As a side effect this enables
+ * decompression for gif_deanimate_response() and jpeg_inspect_response().
+ * - Change remove_chunked_transfer_coding()'s return type to jb_err.
+ * Some clowns feel like chunking empty responses in which case
+ * (size == 0) is valid but previously would be interpreted as error.
+ *
+ * Revision 1.91 2007/09/02 15:31:20 fabiankeil
+ * Move match_portlist() from filter.c to urlmatch.c.
+ * It's used for url matching, not for filtering.
+ *
+ * Revision 1.90 2007/09/02 12:44:17 fabiankeil
+ * Remove newline at the end of a log_error() message.
+ *
+ * Revision 1.89 2007/08/05 13:42:23 fabiankeil
+ * #1763173 from Stefan Huehner: declare some more functions static.
+ *
* Revision 1.88 2007/06/01 16:41:11 fabiankeil
* Add forward-override{} to change the forwarding settings through
* action sections. This is mainly interesting to forward different
*/
#define ijb_isdigit(__X) isdigit((int)(unsigned char)(__X))
+static jb_err remove_chunked_transfer_coding(char *buffer, size_t *size);
+static jb_err prepare_for_filtering(struct client_state *csp);
#ifdef FEATURE_ACL
/*********************************************************************
* Returns : 0 = FALSE (don't block) and 1 = TRUE (do block)
*
*********************************************************************/
-int block_acl(struct access_control_addr *dst, struct client_state *csp)
+int block_acl(const struct access_control_addr *dst, const struct client_state *csp)
{
struct access_control_list *acl = csp->config->acl;
*p++ = '\0';
if (ijb_isdigit(*p) == 0)
{
- free(acl_spec);
+ freez(acl_spec);
return(-1);
}
masklength = atoi(p);
if ((masklength < 0) || (masklength > 32))
{
- free(acl_spec);
+ freez(acl_spec);
return(-1);
}
if (port <= 0 || port > 65535 || *endptr != '\0')
{
- free(acl_spec);
+ freez(acl_spec);
return(-1);
}
}
aca->port = (unsigned long)port;
aca->addr = ntohl(resolve_hostname_to_ip(acl_spec));
- free(acl_spec);
+ freez(acl_spec);
if (aca->addr == INADDR_NONE)
{
/*********************************************************************
*
- * Function : match_portlist
+ * Function : connect_port_is_forbidden
*
- * Description : Check if a given number is covered by a comma
- * separated list of numbers and ranges (a,b-c,d,..)
+ * Description : Check to see if CONNECT requests to the destination
+ * port of this request are forbidden. The check is
+ * independend of the actual request method.
*
* Parameters :
- * 1 : portlist = String with list
- * 2 : port = port to check
+ * 1 : csp = Current client state (buffers, headers, etc...)
*
- * Returns : 0 => no match
- * 1 => match
+ * Returns : True if yes, false otherwise.
*
*********************************************************************/
-int match_portlist(const char *portlist, int port)
+int connect_port_is_forbidden(const struct client_state *csp)
{
- char *min, *max, *next, *portlist_copy;
-
- min = next = portlist_copy = strdup(portlist);
-
- /*
- * Zero-terminate first item and remember offset for next
- */
- if (NULL != (next = strchr(portlist_copy, (int) ',')))
- {
- *next++ = '\0';
- }
-
- /*
- * Loop through all items, checking for match
- */
- while(min)
- {
- if (NULL == (max = strchr(min, (int) '-')))
- {
- /*
- * No dash, check for equality
- */
- if (port == atoi(min))
- {
- free(portlist_copy);
- return(1);
- }
- }
- else
- {
- /*
- * This is a range, so check if between min and max,
- * or, if max was omitted, between min and 65K
- */
- *max++ = '\0';
- if(port >= atoi(min) && port <= (atoi(max) ? atoi(max) : 65535))
- {
- free(portlist_copy);
- return(1);
- }
-
- }
-
- /*
- * Jump to next item
- */
- min = next;
-
- /*
- * Zero-terminate next item and remember offset for n+1
- */
- if ((NULL != next) && (NULL != (next = strchr(next, (int) ','))))
- {
- *next++ = '\0';
- }
- }
-
- free(portlist_copy);
- return 0;
-
+ return ((csp->action->flags & ACTION_LIMIT_CONNECT) &&
+ !match_portlist(csp->action->string[ACTION_STRING_LIMIT_CONNECT],
+ csp->http->port));
}
if (!err) err = map(exports, "hostport", 1, html_encode(csp->http->hostport), 0);
if (!err) err = map(exports, "path", 1, html_encode(csp->http->path), 0);
if (!err) err = map(exports, "path-ue", 1, url_encode(csp->http->path), 0);
-
+ if (!err)
+ {
+ const char *block_reason;
+ if (csp->action->string[ACTION_STRING_BLOCK] != NULL)
+ {
+ block_reason = csp->action->string[ACTION_STRING_BLOCK];
+ }
+ else
+ {
+ assert(connect_port_is_forbidden(csp));
+ block_reason = "Forbidden CONNECT port.";
+ }
+ err = map(exports, "block-reason", 1, html_encode(block_reason), 0);
+ }
if (err)
{
free_map(exports);
/*
* If not, do we maybe trust its referrer?
*/
- err = parse_http_url(referer, rhttp, csp);
+ err = parse_http_url(referer, rhttp, REQUIRE_PROTOCOL);
if (err)
{
return 1;
log_error(LOG_LEVEL_ERROR, "Failed to append \'%s\' to trustfile \'%s\': %E",
new_entry, csp->config->trustfile);
}
- free(new_entry);
+ freez(new_entry);
}
else
{
* Function : pcrs_filter_response
*
* Description : Execute all text substitutions from all applying
- * +filter actions on the text buffer that's been accumulated
- * in csp->iob->buf. If this changes the contents, set
- * csp->content_length to the modified size and raise the
- * CSP_FLAG_MODIFIED flag.
- *
- * XXX: Currently pcrs_filter_response is also responsible
- * for dechunking and decompressing. Both should be
- * done in separate functions so other content modifiers
- * profit as well, even if pcrs filtering is disabled.
+ * +filter actions on the text buffer that's been
+ * accumulated in csp->iob->buf.
*
* Parameters :
* 1 : csp = Current client state (buffers, headers, etc...)
* or NULL if there were no hits or something went wrong
*
*********************************************************************/
-char *pcrs_filter_response(struct client_state *csp)
+static char *pcrs_filter_response(struct client_state *csp)
{
int hits=0;
size_t size, prev_size;
- char *old = csp->iob->cur, *new = NULL;
+ char *old = NULL;
+ char *new = NULL;
pcrs_job *job;
struct file_list *fl;
{
return(NULL);
}
- size = (size_t)(csp->iob->eod - csp->iob->cur);
/*
* Need to check the set of re_filterfiles...
if (0 == found_filters)
{
- log_error(LOG_LEVEL_ERROR, "Unable to get current state of regexp filtering.");
+ log_error(LOG_LEVEL_ERROR, "Inconsistent configuration: "
+ "content filtering enabled, but no content filters available.");
return(NULL);
}
- /*
- * If the body has a "chunked" transfer-encoding,
- * get rid of it first, adjusting size and iob->eod
- */
- if (csp->flags & CSP_FLAG_CHUNKED)
- {
- log_error(LOG_LEVEL_RE_FILTER, "Need to de-chunk first");
- if (0 == (size = remove_chunked_transfer_coding(csp->iob->cur, size)))
- {
- return(NULL);
- }
- csp->iob->eod = csp->iob->cur + size;
- csp->flags |= CSP_FLAG_MODIFIED;
- }
-
-#ifdef FEATURE_ZLIB
- /*
- * If the body has a compressed transfer-encoding,
- * uncompress it first, adjusting size and iob->eod.
- * Note that decompression occurs after de-chunking.
- */
- if (csp->content_type & (CT_GZIP | CT_DEFLATE))
- {
- /* Notice that we at least tried to decompress. */
- if (JB_ERR_OK != decompress_iob(csp))
- {
- /*
- * We failed to decompress the data; there's no point
- * in continuing since we can't filter.
- *
- * XXX: Actually the Accept-Encoding header may
- * just be incorrect in which case we could continue
- * with filtering.
- *
- * Unset CT_GZIP and CT_DEFLATE to remember not
- * to modify the Content-Encoding header later.
- */
- csp->content_type &= ~CT_GZIP;
- csp->content_type &= ~CT_DEFLATE;
- return(NULL);
- }
-
- /*
- * Decompression gives us a completely new iob,
- * so we need to update.
- */
- size = (size_t)(csp->iob->eod - csp->iob->cur);
- old = csp->iob->cur;
-
- csp->flags |= CSP_FLAG_MODIFIED;
- csp->content_type &= ~CT_TABOO;
- }
-#endif
+ size = (size_t)(csp->iob->eod - csp->iob->cur);
+ old = csp->iob->cur;
for (i = 0; i < MAX_AF_FILES; i++)
{
current_hits += job_hits;
if (old != csp->iob->cur)
{
- free(old);
+ freez(old);
}
old = new;
}
*/
if (!hits)
{
- free(new);
+ freez(new);
return(NULL);
}
* or NULL in case something went wrong.
*
*********************************************************************/
-char *gif_deanimate_response(struct client_state *csp)
+static char *gif_deanimate_response(struct client_state *csp)
{
struct binbuffer *in, *out;
char *p;
size = (size_t)(csp->iob->eod - csp->iob->cur);
- /*
- * If the body has a "chunked" transfer-encoding,
- * get rid of it first, adjusting size and iob->eod
- */
- if (csp->flags & CSP_FLAG_CHUNKED)
- {
- log_error(LOG_LEVEL_DEANIMATE, "Need to de-chunk first");
- if (0 == (size = remove_chunked_transfer_coding(csp->iob->cur, size)))
- {
- return(NULL);
- }
- csp->iob->eod = csp->iob->cur + size;
- csp->flags |= CSP_FLAG_MODIFIED;
- }
-
if ( (NULL == (in = (struct binbuffer *)zalloc(sizeof *in )))
|| (NULL == (out = (struct binbuffer *)zalloc(sizeof *out))) )
{
if (gif_deanimate(in, out, strncmp("last", csp->action->string[ACTION_STRING_DEANIMATE], 4)))
{
log_error(LOG_LEVEL_DEANIMATE, "failed! (gif parsing)");
- free(in);
+ freez(in);
buf_free(out);
return(NULL);
}
csp->content_length = out->offset;
csp->flags |= CSP_FLAG_MODIFIED;
p = out->buffer;
- free(in);
- free(out);
+ freez(in);
+ freez(out);
return(p);
}
/*********************************************************************
*
- * Function : jpeg_inspect_response
+ * Function : get_filter_function
*
- * Description :
+ * Description : Decides which content filter function has
+ * to be applied (if any).
*
* Parameters :
* 1 : csp = Current client state (buffers, headers, etc...)
*
- * Returns : a pointer to the (newly allocated) modified buffer
- * or NULL in case something went wrong.
+ * Returns : The content filter function to run, or
+ * NULL if no content filter is active
*
*********************************************************************/
-char *jpeg_inspect_response(struct client_state *csp)
+filter_function_ptr get_filter_function(struct client_state *csp)
{
- struct binbuffer *in = NULL;
- struct binbuffer *out = NULL;
- char *p = NULL;
- size_t size;
-
- size = (size_t)(csp->iob->eod - csp->iob->cur);
+ filter_function_ptr filter_function = NULL;
/*
- * If the body has a "chunked" transfer-encoding,
- * get rid of it first, adjusting size and iob->eod
+ * Are we enabling text mode by force?
*/
- if (csp->flags & CSP_FLAG_CHUNKED)
+ if (csp->action->flags & ACTION_FORCE_TEXT_MODE)
{
- log_error(LOG_LEVEL_DEANIMATE, "Need to de-chunk first");
- if (0 == (size = remove_chunked_transfer_coding(csp->iob->cur, size)))
+ /*
+ * Do we really have to?
+ */
+ if (csp->content_type & CT_TEXT)
{
- return(NULL);
+ 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!");
}
- csp->iob->eod = csp->iob->cur + size;
- csp->flags |= CSP_FLAG_MODIFIED;
- }
-
- if (NULL == (in = (struct binbuffer *)zalloc(sizeof *in )))
- {
- log_error(LOG_LEVEL_DEANIMATE, "failed! (jpeg no mem 1)");
- return NULL;
}
- if (NULL == (out = (struct binbuffer *)zalloc(sizeof *out)))
+ if (!(csp->content_type & CT_DECLARED))
{
- log_error(LOG_LEVEL_DEANIMATE, "failed! (jpeg no mem 2)");
- return NULL;
+ /*
+ * 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;
}
- in->buffer = csp->iob->cur;
- in->size = size;
-
/*
- * Calling jpeg_inspect has the side-effect of creating and
- * modifying the image buffer of "out" directly.
+ * Choose the applying filter function based on
+ * the content type and action settings.
*/
- if (jpeg_inspect(in, out))
+ if ((csp->content_type & CT_TEXT) &&
+ (csp->rlist != NULL) &&
+ (!list_is_empty(csp->action->multi[ACTION_MULTI_FILTER])))
{
- log_error(LOG_LEVEL_DEANIMATE, "failed! (jpeg parsing)");
- free(in);
- buf_free(out);
- return(NULL);
-
+ filter_function = pcrs_filter_response;
}
- else
+ else if ((csp->content_type & CT_GIF) &&
+ (csp->action->flags & ACTION_DEANIMATE))
{
- csp->content_length = out->offset;
- csp->flags |= CSP_FLAG_MODIFIED;
- p = out->buffer;
- free(in);
- free(out);
- return(p);
+ filter_function = gif_deanimate_response;
}
+ return filter_function;
}
*
* Parameters :
* 1 : buffer = Pointer to the text buffer
- * 2 : size = Number of bytes to be processed
+ * 2 : size = In: Number of bytes to be processed,
+ * Out: Number of bytes after de-chunking.
+ * (undefined in case of errors)
*
- * Returns : The new size, i.e. the number of bytes from buffer which
- * are occupied by the stripped body, or 0 in case something
- * went wrong
+ * Returns : JB_ERR_OK for success,
+ * JB_ERR_PARSE otherwise
*
*********************************************************************/
-size_t remove_chunked_transfer_coding(char *buffer, const size_t size)
+static jb_err remove_chunked_transfer_coding(char *buffer, size_t *size)
{
size_t newsize = 0;
unsigned int chunksize = 0;
if (sscanf(buffer, "%x", &chunksize) != 1)
{
log_error(LOG_LEVEL_ERROR, "Invalid first chunksize while stripping \"chunked\" transfer coding");
- return(0);
+ return JB_ERR_PARSE;
}
while (chunksize > 0)
if (NULL == (from_p = strstr(from_p, "\r\n")))
{
log_error(LOG_LEVEL_ERROR, "Parse error while stripping \"chunked\" transfer coding");
- return(0);
+ return JB_ERR_PARSE;
}
- if ((newsize += chunksize) >= size)
+ if ((newsize += chunksize) >= *size)
{
log_error(LOG_LEVEL_ERROR, "Chunksize exceeds buffer in \"chunked\" transfer coding");
- return(0);
+ return JB_ERR_PARSE;
}
from_p += 2;
if (sscanf(from_p, "%x", &chunksize) != 1)
{
- log_error(LOG_LEVEL_ERROR, "Parse error while stripping \"chunked\" transfer coding");
- return(0);
+ log_error(LOG_LEVEL_INFO, "Invalid \"chunked\" transfer encoding detected and ignored.");
+ break;
+ }
+ }
+
+ /* XXX: Should get its own loglevel. */
+ log_error(LOG_LEVEL_RE_FILTER, "De-chunking successful. Shrunk from %d to %d", *size, newsize);
+
+ *size = newsize;
+
+ return JB_ERR_OK;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : prepare_for_filtering
+ *
+ * Description : If necessary, de-chunks and decompresses
+ * the content so it can get filterd.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : JB_ERR_OK for success,
+ * JB_ERR_PARSE otherwise
+ *
+ *********************************************************************/
+static jb_err prepare_for_filtering(struct client_state *csp)
+{
+ jb_err err = JB_ERR_OK;
+
+ /*
+ * If the body has a "chunked" transfer-encoding,
+ * get rid of it, adjusting size and iob->eod
+ */
+ if (csp->flags & CSP_FLAG_CHUNKED)
+ {
+ size_t size = (size_t)(csp->iob->eod - csp->iob->cur);
+
+ log_error(LOG_LEVEL_RE_FILTER, "Need to de-chunk first");
+ err = remove_chunked_transfer_coding(csp->iob->cur, &size);
+ if (JB_ERR_OK == err)
+ {
+ csp->iob->eod = csp->iob->cur + size;
+ csp->flags |= CSP_FLAG_MODIFIED;
+ }
+ else
+ {
+ return JB_ERR_PARSE;
+ }
+ }
+
+#ifdef FEATURE_ZLIB
+ /*
+ * If the body has a supported transfer-encoding,
+ * decompress it, adjusting size and iob->eod.
+ */
+ if (csp->content_type & (CT_GZIP|CT_DEFLATE))
+ {
+ if (0 == csp->iob->eod - csp->iob->cur)
+ {
+ /* Nothing left after de-chunking. */
+ return JB_ERR_OK;
+ }
+
+ err = decompress_iob(csp);
+
+ if (JB_ERR_OK == err)
+ {
+ csp->flags |= CSP_FLAG_MODIFIED;
+ csp->content_type &= ~CT_TABOO;
}
+ else
+ {
+ /*
+ * Unset CT_GZIP and CT_DEFLATE to remember not
+ * to modify the Content-Encoding header later.
+ */
+ csp->content_type &= ~CT_GZIP;
+ csp->content_type &= ~CT_DEFLATE;
+ }
+ }
+#endif
+
+ return err;
+}
+
+
+/*********************************************************************
+ *
+ * Function : execute_content_filter
+ *
+ * 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)
+{
+ if (0 == csp->iob->eod - csp->iob->cur)
+ {
+ /*
+ * No content (probably status code 301, 302 ...),
+ * no filtering necessary.
+ */
+ return NULL;
+ }
+
+ if (JB_ERR_OK != prepare_for_filtering(csp))
+ {
+ /*
+ * failed to de-chunk or decompress.
+ */
+ return NULL;
}
- /* FIXME: Should this get its own loglevel? */
- log_error(LOG_LEVEL_RE_FILTER, "De-chunking successful. Shrunk from %d to %d\n", size, newsize);
- return(newsize);
+ if (0 == csp->iob->eod - csp->iob->cur)
+ {
+ /*
+ * Clown alarm: chunked and/or compressed nothing delivered.
+ */
+ return NULL;
+ }
+ return ((*content_filter)(csp));
}
/*********************************************************************
*
- * Function : url_actions
+ * Function : get_url_actions
*
* Description : Gets the actions for this URL.
*
* Parameters :
- * 1 : http = http_request request for blocked URLs
- * 2 : csp = Current client state (buffers, headers, etc...)
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ * 2 : http = http_request request for blocked URLs
*
* Returns : N/A
*
*********************************************************************/
-void url_actions(struct http_request *http,
- struct client_state *csp)
+void get_url_actions(struct client_state *csp, struct http_request *http)
{
struct file_list *fl;
struct url_actions *b;
* Invalid syntax is fatal.
*
*********************************************************************/
-static const struct forward_spec *get_forward_override_settings(struct client_state *csp)
+const static struct forward_spec *get_forward_override_settings(struct client_state *csp)
{
const char *forward_override_line = csp->action->string[ACTION_STRING_FORWARD_OVERRIDE];
char forward_settings[BUFFER_SIZE];
fwd->type = SOCKS_4A;
socks_proxy = vec[1];
}
+ else if (!strcasecmp(vec[0], "forward-socks5"))
+ {
+ fwd->type = SOCKS_5;
+ socks_proxy = vec[1];
+ }
if (NULL != socks_proxy)
{
return fwd;
}
+
/*********************************************************************
*
* Function : forward_url
*
* Description : Should we forward this to another proxy?
*
- * XXX: Should be changed to make use of csp->fwd.
- *
* Parameters :
- * 1 : http = http_request request for current URL
- * 2 : csp = Current client state (buffers, headers, etc...)
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ * 2 : http = http_request request for current URL
*
* Returns : Pointer to forwarding information.
*
*********************************************************************/
-const struct forward_spec * forward_url(struct http_request *http,
- struct client_state *csp)
+const struct forward_spec *forward_url(struct client_state *csp,
+ const struct http_request *http)
{
static const struct forward_spec fwd_default[1] = { FORWARD_SPEC_INITIALIZER };
struct forward_spec *fwd = csp->config->forward;
}
+/*********************************************************************
+ *
+ * Function : content_filters_enabled
+ *
+ * Description : Checks whether there are any content filters
+ * enabled for the current request.
+ *
+ * Parameters :
+ * 1 : action = Action spec to check.
+ *
+ * Returns : TRUE for yes, FALSE otherwise
+ *
+ *********************************************************************/
+int content_filters_enabled(const struct current_action_spec *action)
+{
+ return ((action->flags & ACTION_DEANIMATE) ||
+ !list_is_empty(action->multi[ACTION_MULTI_FILTER]));
+}
+
/*
Local Variables:
tab-width: 3