From 8728cdead13a06cddc650bedd58e299d8cc78314 Mon Sep 17 00:00:00 2001 From: Fabian Keil Date: Sat, 29 Sep 2007 10:21:16 +0000 Subject: [PATCH] - Move get_filter_function() from jcc.c to filters.c so the filter functions can be static. - Don't bother filtering body-less responses. --- filters.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++---- filters.h | 15 +++++-- jcc.c | 89 +++------------------------------------ 3 files changed, 131 insertions(+), 94 deletions(-) diff --git a/filters.c b/filters.c index a4757be3..c3a7fdfa 100644 --- a/filters.c +++ b/filters.c @@ -1,4 +1,4 @@ -const char filters_rcs[] = "$Id: filters.c,v 1.91 2007/09/02 15:31:20 fabiankeil Exp $"; +const char filters_rcs[] = "$Id: filters.c,v 1.92 2007/09/28 16:38:55 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/filters.c,v $ @@ -40,6 +40,15 @@ const char filters_rcs[] = "$Id: filters.c,v 1.91 2007/09/02 15:31:20 fabiankeil * * Revisions : * $Log: filters.c,v $ + * 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. @@ -1740,7 +1749,7 @@ int is_untrusted_url(const struct client_state *csp) * 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; @@ -1926,7 +1935,7 @@ char *pcrs_filter_response(struct client_state *csp) * 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; @@ -1985,7 +1994,7 @@ char *gif_deanimate_response(struct client_state *csp) * 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; @@ -2034,6 +2043,87 @@ char *jpeg_inspect_response(struct client_state *csp) } +/********************************************************************* + * + * 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 @@ -2154,6 +2244,12 @@ static jb_err prepare_for_filtering(struct client_state *csp) */ 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) @@ -2188,12 +2284,21 @@ static jb_err prepare_for_filtering(struct client_state *csp) * 1 : csp = Current client state (buffers, headers, etc...) * 2 : content_filter = The filter function to execute * - * Returns : JB_ERR_OK for success, - * JB_ERR_PARSE otherwise + * 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)) { /* @@ -2205,7 +2310,9 @@ char *execute_content_filter(struct client_state *csp, filter_function_ptr conte if (0 == csp->iob->eod - csp->iob->cur) { - /* Empty buffer, nothing to do. */ + /* + * Clown alarm: chunked and/or compressed nothing delivered. + */ return NULL; } diff --git a/filters.h b/filters.h index 09d47f80..12bfdd74 100644 --- a/filters.h +++ b/filters.h @@ -1,6 +1,6 @@ #ifndef FILTERS_H_INCLUDED #define FILTERS_H_INCLUDED -#define FILTERS_H_VERSION "$Id: filters.h,v 1.28 2007/09/02 15:31:20 fabiankeil Exp $" +#define FILTERS_H_VERSION "$Id: filters.h,v 1.29 2007/09/28 16:38:55 fabiankeil Exp $" /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/filters.h,v $ @@ -39,6 +39,15 @@ * * Revisions : * $Log: filters.h,v $ + * Revision 1.29 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.28 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. @@ -301,9 +310,7 @@ extern const struct forward_spec *forward_url(struct http_request *http, struct typedef char *(*filter_function_ptr)(); extern char *execute_content_filter(struct client_state *csp, filter_function_ptr content_filter); -extern char *pcrs_filter_response(struct client_state *csp); -extern char *gif_deanimate_response(struct client_state *csp); -extern char *jpeg_inspect_response(struct client_state *csp); +extern filter_function_ptr get_filter_function(struct client_state *csp); extern char *execute_single_pcrs_command(char *subject, const char *pcrs_command, int *hits); extern char *rewrite_url(char *old_url, const char *pcrs_command); extern char *get_last_url(char *subject, const char *redirect_mode); diff --git a/jcc.c b/jcc.c index e454d0e7..7266e1aa 100644 --- a/jcc.c +++ b/jcc.c @@ -1,4 +1,4 @@ -const char jcc_rcs[] = "$Id: jcc.c,v 1.149 2007/09/04 15:08:48 fabiankeil Exp $"; +const char jcc_rcs[] = "$Id: jcc.c,v 1.150 2007/09/28 16:39:29 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jcc.c,v $ @@ -33,6 +33,9 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.149 2007/09/04 15:08:48 fabiankeil Exp $" * * Revisions : * $Log: jcc.c,v $ + * Revision 1.150 2007/09/28 16:39:29 fabiankeil + * Execute content filters through execute_content_filter(). + * * Revision 1.149 2007/09/04 15:08:48 fabiankeil * Initialize req to NULL to make sure it's defined if the * first read_socket() call fails. Reported by icmp30. @@ -1114,6 +1117,7 @@ static const char NO_SERVER_DATA_RESPONSE[] = "Empty server or forwarder response.\r\n" "The connection was closed without sending any data.\r\n"; +#if 0 /* XXX: should be a template */ static const char NULL_BYTE_RESPONSE[] = "HTTP/1.0 400 Bad request received from browser\r\n" @@ -1121,6 +1125,7 @@ static const char NULL_BYTE_RESPONSE[] = "Content-Type: text/plain\r\n" "Connection: close\r\n\r\n" "Bad request. Null byte(s) before end of request.\r\n"; +#endif /* XXX: should be a template */ static const char MESSED_UP_REQUEST_RESPONSE[] = @@ -1148,7 +1153,6 @@ struct cruncher }; static int crunch_response_triggered(struct client_state *csp, const struct cruncher crunchers[]); -static filter_function_ptr get_filter_function(struct client_state *csp); /* Complete list of cruncher functions */ static const struct cruncher crunchers_all[] = { @@ -1813,87 +1817,6 @@ static jb_err change_request_destination(struct client_state *csp) } -/********************************************************************* - * - * 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 - * - *********************************************************************/ -static 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 : chat -- 2.39.2