-const char parsers_rcs[] = "$Id: parsers.c,v 1.97 2007/04/15 16:39:21 fabiankeil Exp $";
+const char parsers_rcs[] = "$Id: parsers.c,v 1.104 2007/07/14 07:38:19 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/parsers.c,v $
*
* Revisions :
* $Log: parsers.c,v $
+ * Revision 1.104 2007/07/14 07:38:19 fabiankeil
+ * Move the ACTION_FORCE_TEXT_MODE check out of
+ * server_content_type(). Signal other functions
+ * whether or not a content type has been declared.
+ * Part of the fix for BR#1750917.
+ *
+ * Revision 1.103 2007/06/01 16:31:54 fabiankeil
+ * Change sed() to return a jb_err in preparation for forward-override{}.
+ *
+ * Revision 1.102 2007/05/27 12:39:32 fabiankeil
+ * Adjust "X-Filter: No" to disable dedicated header filters.
+ *
+ * Revision 1.101 2007/05/14 10:16:41 fabiankeil
+ * Streamline client_cookie_adder().
+ *
+ * Revision 1.100 2007/04/30 15:53:11 fabiankeil
+ * Make sure filters with dynamic jobs actually use them.
+ *
+ * Revision 1.99 2007/04/30 15:06:26 fabiankeil
+ * - Introduce dynamic pcrs jobs that can resolve variables.
+ * - Remove unnecessary update_action_bits_for_all_tags() call.
+ *
+ * Revision 1.98 2007/04/17 18:32:10 fabiankeil
+ * - Make tagging based on tags set by earlier taggers
+ * of the same kind possible.
+ * - Log whether or not new tags cause action bits updates
+ * (in which case a matching tag-pattern section exists).
+ * - Log if the user tries to set a tag that is already set.
+ *
* Revision 1.97 2007/04/15 16:39:21 fabiankeil
* Introduce tags as alternative way to specify which
* actions apply to a request. At the moment tags can be
#include "miscutil.h"
#include "list.h"
#include "actions.h"
+#include "filters.h"
#ifndef HAVE_STRPTIME
#include "strptime.h"
#define ijb_isupper(__X) isupper((int)(unsigned char)(__X))
#define ijb_tolower(__X) tolower((int)(unsigned char)(__X))
-jb_err header_tagger(struct client_state *csp, char *header);
-jb_err scan_headers(struct client_state *csp);
+static jb_err scan_headers(struct client_state *csp);
+static jb_err header_tagger(struct client_state *csp, char *header);
+static jb_err parse_header_time(const char *header_time, time_t *result);
+
+static jb_err crumble (struct client_state *csp, char **header);
+static jb_err connection (struct client_state *csp, char **header);
+static jb_err filter_header (struct client_state *csp, char **header);
+static jb_err client_referrer (struct client_state *csp, char **header);
+static jb_err client_uagent (struct client_state *csp, char **header);
+static jb_err client_ua (struct client_state *csp, char **header);
+static jb_err client_from (struct client_state *csp, char **header);
+static jb_err client_send_cookie (struct client_state *csp, char **header);
+static jb_err client_x_forwarded (struct client_state *csp, char **header);
+static jb_err client_accept_encoding (struct client_state *csp, char **header);
+static jb_err client_te (struct client_state *csp, char **header);
+static jb_err client_max_forwards (struct client_state *csp, char **header);
+static jb_err client_host (struct client_state *csp, char **header);
+static jb_err client_if_modified_since (struct client_state *csp, char **header);
+static jb_err client_accept_language (struct client_state *csp, char **header);
+static jb_err client_if_none_match (struct client_state *csp, char **header);
+static jb_err crunch_client_header (struct client_state *csp, char **header);
+static jb_err client_x_filter (struct client_state *csp, char **header);
+static jb_err server_set_cookie (struct client_state *csp, char **header);
+static jb_err server_content_type (struct client_state *csp, char **header);
+static jb_err server_content_length (struct client_state *csp, char **header);
+static jb_err server_content_md5 (struct client_state *csp, char **header);
+static jb_err server_content_encoding (struct client_state *csp, char **header);
+static jb_err server_transfer_coding (struct client_state *csp, char **header);
+static jb_err server_http (struct client_state *csp, char **header);
+static jb_err crunch_server_header (struct client_state *csp, char **header);
+static jb_err server_last_modified (struct client_state *csp, char **header);
+static jb_err server_content_disposition(struct client_state *csp, char **header);
+
+static jb_err client_host_adder (struct client_state *csp);
+static jb_err client_cookie_adder (struct client_state *csp);
+static jb_err client_xtra_adder (struct client_state *csp);
+static jb_err client_x_forwarded_adder(struct client_state *csp);
+static jb_err connection_close_adder (struct client_state *csp);
const struct parsers client_patterns[] = {
{ "referer:", 8, client_referrer },
* Returns : JB_ERR_OK
*
*********************************************************************/
-jb_err scan_headers(struct client_state *csp)
+static jb_err scan_headers(struct client_state *csp)
{
struct list_entry *h; /* Header */
jb_err err = JB_ERR_OK;
err = header_tagger(csp, h->str);
}
- /*
- * header_tagger already updated the action bits
- * for every new tag, but unless I'm confused,
- * updating them again after all tags are collected,
- * should give us another level of indirection when
- * it comes to tagging based on tags which were set
- * by tag sections which were active because of other
- * tag sections themselves (or something like this).
- */
- update_action_bits_for_all_tags(csp);
-
return err;
}
* headers (client or server)
* 3 : csp = Current client state (buffers, headers, etc...)
*
- * Returns : Single pointer to a fully formed header, or NULL
- * on out-of-memory error.
+ * Returns : JB_ERR_OK in case off success, or
+ * JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-char *sed(const struct parsers pats[],
- const add_header_func_ptr more_headers[],
- struct client_state *csp)
+jb_err sed(const struct parsers pats[],
+ const add_header_func_ptr more_headers[],
+ struct client_state *csp)
{
struct list_entry *p;
const struct parsers *v;
}
}
- if (err != JB_ERR_OK)
- {
- return NULL;
- }
-
- return list_to_text(csp->headers);
+ return err;
}
* Returns : JB_ERR_OK on success and always succeeds
*
*********************************************************************/
-jb_err header_tagger(struct client_state *csp, char *header)
+static jb_err header_tagger(struct client_state *csp, char *header)
{
int wanted_filter_type;
int multi_action_index;
char *modified_tag = NULL;
char *tag = header;
size_t size = header_length;
+ pcrs_job *joblist = b->joblist;
- if (NULL == b->joblist)
+ if (b->dynamic) joblist = compile_dynamic_pcrs_job_list(csp, b);
+
+ if (NULL == joblist)
{
log_error(LOG_LEVEL_RE_FILTER,
"Tagger %s has empty joblist. Nothing to do.", b->name);
}
/* execute their pcrs_joblist on the header. */
- for (job = b->joblist; NULL != job; job = job->next)
+ for (job = joblist; NULL != job; job = job->next)
{
const int hits = pcrs_execute(job, tag, size, &modified_tag, &size);
}
}
+ if (b->dynamic) pcrs_free_joblist(joblist);
+
/* If this tagger matched */
if (tag != header)
{
* Returns : JB_ERR_OK on success and always succeeds
*
*********************************************************************/
-jb_err filter_header(struct client_state *csp, char **header)
+static jb_err filter_header(struct client_state *csp, char **header)
{
int hits=0;
int matches;
int wanted_filter_type;
int multi_action_index;
+ if (csp->flags & CSP_FLAG_NO_FILTERING)
+ {
+ return JB_ERR_OK;
+ }
+
if (csp->flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
{
wanted_filter_type = FT_SERVER_HEADER_FILTER;
if (strcmp(b->name, filtername->str) == 0)
{
int current_hits = 0;
+ pcrs_job *joblist = b->joblist;
- if ( NULL == b->joblist )
+ if (b->dynamic) joblist = compile_dynamic_pcrs_job_list(csp, b);
+
+ if (NULL == joblist)
{
log_error(LOG_LEVEL_RE_FILTER, "Filter %s has empty joblist. Nothing to do.", b->name);
continue;
*header, size, b->name);
/* Apply all jobs from the joblist */
- for (job = b->joblist; NULL != job; job = job->next)
+ for (job = joblist; NULL != job; job = job->next)
{
matches = pcrs_execute(job, *header, size, &newheader, &size);
if ( 0 < matches )
}
}
}
+
+ if (b->dynamic) pcrs_free_joblist(joblist);
+
log_error(LOG_LEVEL_RE_FILTER, "... produced %d hits (new size %d).", current_hits, size);
hits += current_hits;
}
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err connection(struct client_state *csp, char **header)
+static jb_err connection(struct client_state *csp, char **header)
{
char *old_header = *header;
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err crumble(struct client_state *csp, char **header)
+static jb_err crumble(struct client_state *csp, char **header)
{
log_error(LOG_LEVEL_HEADER, "crumble crunched: %s!", *header);
freez(*header);
* Returns : JB_ERR_OK on success and always succeeds
*
*********************************************************************/
-jb_err crunch_server_header(struct client_state *csp, char **header)
+static jb_err crunch_server_header(struct client_state *csp, char **header)
{
const char *crunch_pattern;
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err server_content_type(struct client_state *csp, char **header)
+static jb_err server_content_type(struct client_state *csp, char **header)
{
/* Remove header if it isn't the first Content-Type header */
- if(csp->content_type && (csp->content_type != CT_TABOO))
+ if ((csp->content_type & CT_DECLARED))
{
/*
* Another, slightly slower, way to see if
return JB_ERR_OK;
}
+ /*
+ * Signal that the Content-Type has been set.
+ */
+ csp->content_type |= CT_DECLARED;
+
if (!(csp->content_type & CT_TABOO))
{
if ((strstr(*header, " text/") && !strstr(*header, "plain"))
{
csp->content_type |= CT_JPEG;
}
- 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?
*/
"Enable force-text-mode if you know what you're doing.", *header);
}
}
+
return JB_ERR_OK;
}
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err server_transfer_coding(struct client_state *csp, char **header)
+static jb_err server_transfer_coding(struct client_state *csp, char **header)
{
/*
* Turn off pcrs and gif filtering if body compressed
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err server_content_encoding(struct client_state *csp, char **header)
+static jb_err server_content_encoding(struct client_state *csp, char **header)
{
#ifdef FEATURE_ZLIB
if ((csp->flags & CSP_FLAG_MODIFIED)
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err server_content_length(struct client_state *csp, char **header)
+static jb_err server_content_length(struct client_state *csp, char **header)
{
const size_t max_header_length = 80;
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err server_content_md5(struct client_state *csp, char **header)
+static jb_err server_content_md5(struct client_state *csp, char **header)
{
if (csp->flags & CSP_FLAG_MODIFIED)
{
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err server_content_disposition(struct client_state *csp, char **header)
+static jb_err server_content_disposition(struct client_state *csp, char **header)
{
const char *newval;
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err server_last_modified(struct client_state *csp, char **header)
+static jb_err server_last_modified(struct client_state *csp, char **header)
{
const char *newval;
char buf[BUFFER_SIZE];
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err client_accept_encoding(struct client_state *csp, char **header)
+static jb_err client_accept_encoding(struct client_state *csp, char **header)
{
if ((csp->action->flags & ACTION_NO_COMPRESSION) != 0)
{
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err client_te(struct client_state *csp, char **header)
+static jb_err client_te(struct client_state *csp, char **header)
{
if ((csp->action->flags & ACTION_NO_COMPRESSION) != 0)
{
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err client_referrer(struct client_state *csp, char **header)
+static jb_err client_referrer(struct client_state *csp, char **header)
{
const char *newval;
const char *host;
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err client_accept_language(struct client_state *csp, char **header)
+static jb_err client_accept_language(struct client_state *csp, char **header)
{
const char *newval;
return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
}
+
/*********************************************************************
*
* Function : crunch_client_header
* Returns : JB_ERR_OK on success and always succeeds
*
*********************************************************************/
-jb_err crunch_client_header(struct client_state *csp, char **header)
+static jb_err crunch_client_header(struct client_state *csp, char **header)
{
const char *crunch_pattern;
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err client_uagent(struct client_state *csp, char **header)
+static jb_err client_uagent(struct client_state *csp, char **header)
{
const char *newval;
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err client_ua(struct client_state *csp, char **header)
+static jb_err client_ua(struct client_state *csp, char **header)
{
if ((csp->action->flags & ACTION_HIDE_USER_AGENT) != 0)
{
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err client_from(struct client_state *csp, char **header)
+static jb_err client_from(struct client_state *csp, char **header)
{
const char *newval;
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err client_send_cookie(struct client_state *csp, char **header)
+static jb_err client_send_cookie(struct client_state *csp, char **header)
{
if (csp->action->flags & ACTION_NO_COOKIE_READ)
{
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err client_max_forwards(struct client_state *csp, char **header)
+static jb_err client_max_forwards(struct client_state *csp, char **header)
{
int max_forwards;
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err client_host(struct client_state *csp, char **header)
+static jb_err client_host(struct client_state *csp, char **header)
{
char *p, *q;
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err client_if_modified_since(struct client_state *csp, char **header)
+static jb_err client_if_modified_since(struct client_state *csp, char **header)
{
char newheader[50];
#ifdef HAVE_GMTIME_R
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err client_if_none_match(struct client_state *csp, char **header)
+static jb_err client_if_none_match(struct client_state *csp, char **header)
{
if (csp->action->flags & ACTION_CRUNCH_IF_NONE_MATCH)
{
}
else
{
- csp->content_type = CT_TABOO;
- csp->action->flags &= ~ACTION_FILTER_SERVER_HEADERS;
- csp->action->flags &= ~ACTION_FILTER_CLIENT_HEADERS;
+ csp->content_type = CT_TABOO; /* XXX: This hack shouldn't be necessary */
+ csp->flags |= CSP_FLAG_NO_FILTERING;
log_error(LOG_LEVEL_HEADER, "Accepted the client's request to fetch without filtering.");
}
log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err client_host_adder(struct client_state *csp)
+static jb_err client_host_adder(struct client_state *csp)
{
char *p;
jb_err err;
*
* Function : client_cookie_adder
*
- * Description : Used in the add_client_headers list. Called from `sed'.
- *
- * XXX: Remove csp->cookie_list which is no longer used.
+ * Description : Used in the add_client_headers list to add "wafers".
+ * Called from `sed'.
*
* Parameters :
* 1 : csp = Current client state (buffers, headers, etc...)
*********************************************************************/
jb_err client_cookie_adder(struct client_state *csp)
{
- struct list_entry *lst;
char *tmp;
- struct list_entry *list1 = csp->cookie_list->first;
- struct list_entry *list2 = csp->action->multi[ACTION_MULTI_WAFER]->first;
- int first_cookie = 1;
+ struct list_entry *wafer;
+ struct list_entry *wafer_list = csp->action->multi[ACTION_MULTI_WAFER]->first;
jb_err err;
- if ((list1 == NULL) && (list2 == NULL))
+ if (NULL == wafer_list)
{
/* Nothing to do */
return JB_ERR_OK;
tmp = strdup("Cookie: ");
- for (lst = list1; lst ; lst = lst->next)
+ for (wafer = wafer_list; (NULL != tmp) && (NULL != wafer); wafer = wafer->next)
{
- if (first_cookie)
- {
- first_cookie = 0;
- }
- else
- {
- string_append(&tmp, "; ");
- }
- string_append(&tmp, lst->str);
- }
-
- for (lst = list2; lst ; lst = lst->next)
- {
- if (first_cookie)
- {
- first_cookie = 0;
- }
- else
+ if (wafer != wafer_list)
{
+ /* As this isn't the first wafer, we need a delimiter. */
string_append(&tmp, "; ");
}
- string_join(&tmp, cookie_encode(lst->str));
+ string_join(&tmp, cookie_encode(wafer->str));
}
if (tmp == NULL)
return err;
}
-
+#if 0
/*********************************************************************
*
* Function : client_accept_encoding_adder
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err client_accept_encoding_adder(struct client_state *csp)
+static jb_err client_accept_encoding_adder(struct client_state *csp)
{
- assert(0); /* Not in use */
-
if ( ((csp->action->flags & ACTION_NO_COMPRESSION) != 0)
&& (!strcmpic(csp->http->ver, "HTTP/1.1")) )
{
return JB_ERR_OK;
}
-
+#endif
/*********************************************************************
*
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err client_xtra_adder(struct client_state *csp)
+static jb_err client_xtra_adder(struct client_state *csp)
{
struct list_entry *lst;
jb_err err;
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err client_x_forwarded_adder(struct client_state *csp)
+static jb_err client_x_forwarded_adder(struct client_state *csp)
{
char *p = NULL;
jb_err err;
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err connection_close_adder(struct client_state *csp)
+static jb_err connection_close_adder(struct client_state *csp)
{
const unsigned int flags = csp->flags;
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err server_http(struct client_state *csp, char **header)
+static jb_err server_http(struct client_state *csp, char **header)
{
sscanf(*header, "HTTP/%*d.%*d %d", &(csp->http->status));
if (csp->http->status == 206)
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-jb_err server_set_cookie(struct client_state *csp, char **header)
+static jb_err server_set_cookie(struct client_state *csp, char **header)
{
time_t now;
time_t cookie_time;
* JB_ERR_PARSE otherwise.
*
*********************************************************************/
-jb_err parse_header_time(const char *header_time, time_t *result)
+static jb_err parse_header_time(const char *header_time, time_t *result)
{
struct tm gmt;