-const char filters_rcs[] = "$Id: filters.c,v 1.85 2007/03/21 12:24:47 fabiankeil Exp $";
+const char filters_rcs[] = "$Id: filters.c,v 1.98 2008/01/04 17:43:45 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/filters.c,v $
*
* Revisions :
* $Log: filters.c,v $
+ * 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
+ * clients differently (for example based on User-Agent or request
+ * origin).
+ *
+ * Revision 1.87 2007/04/30 15:53:10 fabiankeil
+ * Make sure filters with dynamic jobs actually use them.
+ *
+ * Revision 1.86 2007/04/30 15:03:28 fabiankeil
+ * - Introduce dynamic pcrs jobs that can resolve variables.
+ * - Don't run redirect functions more than once,
+ * unless they are activated more than once.
+ *
* Revision 1.85 2007/03/21 12:24:47 fabiankeil
* - Log the content size after decompression in decompress_iob()
* instead of pcrs_filter_response().
#include "list.h"
#include "deanimate.h"
#include "urlmatch.h"
+#include "loaders.h"
#ifdef _WIN32
#include "win32.h"
*/
#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
/*********************************************************************
*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)
{
#endif /* def FEATURE_ACL */
-/*********************************************************************
- *
- * Function : match_portlist
- *
- * Description : Check if a given number is covered by a comma
- * separated list of numbers and ranges (a,b-c,d,..)
- *
- * Parameters :
- * 1 : portlist = String with list
- * 2 : port = port to check
- *
- * Returns : 0 => no match
- * 1 => match
- *
- *********************************************************************/
-int match_portlist(const char *portlist, int port)
-{
- 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;
-
-}
-
-
/*********************************************************************
*
* Function : block_url
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++)
{
prev_size = size;
/* Apply all jobs from the joblist */
- for (job = b->joblist; NULL != job; job = job->next)
+ for (job = joblist; NULL != job; job = job->next)
{
job_number++;
job_hits = pcrs_execute(job, old, size, &new, &size);
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);
}
* or NULL in case something went wrong.
*
*********************************************************************/
-char *jpeg_inspect_response(struct client_state *csp)
+static char *jpeg_inspect_response(struct client_state *csp)
{
struct binbuffer *in = NULL;
struct binbuffer *out = NULL;
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 )))
{
log_error(LOG_LEVEL_DEANIMATE, "failed! (jpeg no mem 1)");
if (jpeg_inspect(in, out))
{
log_error(LOG_LEVEL_DEANIMATE, "failed! (jpeg 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 : get_filter_function
+ *
+ * Description : Decides which content filter function has
+ * to be applied (if any).
+ *
+ * XXX: Doesn't handle filter_popups()
+ * because of the different prototype. Probably
+ * we should ditch filter_popups() anyway, it's
+ * even less reliable than popup blocking based
+ * on pcrs filters.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : The content filter function to run, or
+ * NULL if no content filter is active
+ *
+ *********************************************************************/
+filter_function_ptr get_filter_function(struct client_state *csp)
+{
+ filter_function_ptr filter_function = 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 ((csp->content_type & CT_TEXT) &&
+ (csp->rlist != NULL) &&
+ (!list_is_empty(csp->action->multi[ACTION_MULTI_FILTER])))
+ {
+ filter_function = pcrs_filter_response;
+ }
+ else if ((csp->content_type & CT_GIF) &&
+ (csp->action->flags & ACTION_DEANIMATE))
+ {
+ filter_function = gif_deanimate_response;
+ }
+ else if ((csp->content_type & CT_JPEG) &&
+ (csp->action->flags & ACTION_JPEG_INSPECT))
+ {
+ filter_function = jpeg_inspect_response;
+ }
+
+ return filter_function;
+}
+
+
/*********************************************************************
*
* Function : remove_chunked_transfer_coding
*
* 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;
}
}
- /* 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);
+#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;
+ }
+
+ if (0 == csp->iob->eod - csp->iob->cur)
+ {
+ /*
+ * Clown alarm: chunked and/or compressed nothing delivered.
+ */
+ return NULL;
+ }
+
+ return ((*content_filter)(csp));
}
}
+/*********************************************************************
+ *
+ * Function : get_forward_override_settings
+ *
+ * Description : Returns forward settings as specified with the
+ * forward-override{} action. forward-override accepts
+ * forward lines similar to the one used in the
+ * configuration file, but without the URL pattern.
+ *
+ * For example:
+ *
+ * forward / .
+ *
+ * in the configuration file can be replaced with
+ * the action section:
+ *
+ * {+forward-override{forward .}}
+ * /
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : Pointer to forwarding structure in case of success.
+ * Invalid syntax is fatal.
+ *
+ *********************************************************************/
+static const 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];
+ char *http_parent = NULL;
+ /* variable names were chosen for consistency reasons. */
+ struct forward_spec *fwd = NULL;
+ int vec_count;
+ char *vec[3];
+
+ assert(csp->action->flags & ACTION_FORWARD_OVERRIDE);
+ /* Should be enforced by load_one_actions_file() */
+ assert(strlen(forward_override_line) < sizeof(forward_settings) - 1);
+
+ /* Create a copy ssplit can modify */
+ strlcpy(forward_settings, forward_override_line, sizeof(forward_settings));
+
+ if (NULL != csp->fwd)
+ {
+ /*
+ * XXX: Currently necessary to prevent memory
+ * leaks when the show-url-info cgi page is visited.
+ */
+ unload_forward_spec(csp->fwd);
+ }
+
+ /*
+ * allocate a new forward node, valid only for
+ * the lifetime of this request. Save its location
+ * in csp as well, so sweep() can free it later on.
+ */
+ fwd = csp->fwd = zalloc(sizeof(*fwd));
+ if (NULL == fwd)
+ {
+ log_error(LOG_LEVEL_FATAL,
+ "can't allocate memory for forward-override{%s}", forward_override_line);
+ /* Never get here - LOG_LEVEL_FATAL causes program exit */
+ }
+
+ vec_count = ssplit(forward_settings, " \t", vec, SZ(vec), 1, 1);
+ if ((vec_count == 2) && !strcasecmp(vec[0], "forward"))
+ {
+ fwd->type = SOCKS_NONE;
+
+ /* Parse the parent HTTP proxy host:port */
+ http_parent = vec[1];
+
+ }
+ else if (vec_count == 3)
+ {
+ char *socks_proxy = NULL;
+
+ if (!strcasecmp(vec[0], "forward-socks4"))
+ {
+ fwd->type = SOCKS_4;
+ socks_proxy = vec[1];
+ }
+ else if (!strcasecmp(vec[0], "forward-socks4a"))
+ {
+ 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)
+ {
+ /* Parse the SOCKS proxy host[:port] */
+ fwd->gateway_host = strdup(socks_proxy);
+
+ if (NULL != (socks_proxy = strchr(fwd->gateway_host, ':')))
+ {
+ *socks_proxy++ = '\0';
+ fwd->gateway_port = strtol(socks_proxy, NULL, 0);
+ }
+
+ if (fwd->gateway_port <= 0)
+ {
+ fwd->gateway_port = 1080;
+ }
+
+ http_parent = vec[2];
+ }
+ }
+
+ if (NULL == http_parent)
+ {
+ log_error(LOG_LEVEL_FATAL,
+ "Invalid forward-override syntax in: %s", forward_override_line);
+ /* Never get here - LOG_LEVEL_FATAL causes program exit */
+ }
+
+ /* Parse http forwarding settings */
+ if (strcmp(http_parent, ".") != 0)
+ {
+ fwd->forward_host = strdup(http_parent);
+
+ if (NULL != (http_parent = strchr(fwd->forward_host, ':')))
+ {
+ *http_parent++ = '\0';
+ fwd->forward_port = strtol(http_parent, NULL, 0);
+ }
+
+ if (fwd->forward_port <= 0)
+ {
+ fwd->forward_port = 8000;
+ }
+ }
+
+ assert (NULL != fwd);
+
+ log_error(LOG_LEVEL_CONNECT,
+ "Overriding forwarding settings based on \'%s\'", forward_override_line);
+
+ 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...)
static const struct forward_spec fwd_default[1] = { FORWARD_SPEC_INITIALIZER };
struct forward_spec *fwd = csp->config->forward;
+ if (csp->action->flags & ACTION_FORWARD_OVERRIDE)
+ {
+ return get_forward_override_settings(csp);
+ }
+
if (fwd == NULL)
{
return fwd_default;
}
+/*********************************************************************
+ *
+ * Function : content_filters_enabled
+ *
+ * Description : Checks whether there are any content filters
+ * enabled for the current request.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : TRUE for yes, FALSE otherwise
+ *
+ *********************************************************************/
+inline int content_filters_enabled(const struct client_state *csp)
+{
+ return (((csp->rlist != NULL) &&
+ (!list_is_empty(csp->action->multi[ACTION_MULTI_FILTER]))) ||
+ (csp->action->flags & (ACTION_DEANIMATE|ACTION_JPEG_INSPECT|ACTION_NO_POPUPS)));
+}
+
/*
Local Variables:
tab-width: 3