-const char filters_rcs[] = "$Id: filters.c,v 1.32 2001/09/16 13:21:27 jongfoster Exp $";
+const char filters_rcs[] = "$Id: filters.c,v 1.36 2001/10/10 16:44:16 oes Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/filters.c,v $
*
* Revisions :
* $Log: filters.c,v $
+ * Revision 1.36 2001/10/10 16:44:16 oes
+ * Added match_portlist function
+ *
+ * Revision 1.35 2001/10/07 15:41:23 oes
+ * Replaced 6 boolean members of csp with one bitmap (csp->flags)
+ *
+ * New function remove_chunked_transfer_coding that strips chunked
+ * transfer coding to plain and is called by pcrs_filter_response
+ * and gif_deanimate_response if neccessary
+ *
+ * Improved handling of zero-change re_filter runs
+ *
+ * pcrs_filter_response and gif_deanimate_response now remove
+ * chunked transfer codeing before processing the body.
+ *
+ * Revision 1.34 2001/09/20 15:49:36 steudten
+ *
+ * Fix BUG: Change int size to size_t size in pcrs_filter_response().
+ * See cgi.c fill_template().
+ *
+ * Revision 1.33 2001/09/16 17:05:14 jongfoster
+ * Removing unused #include showarg.h
+ *
* Revision 1.32 2001/09/16 13:21:27 jongfoster
* Changes to use new list functions.
*
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
+#include <assert.h>
#ifndef _WIN32
#include <unistd.h>
#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
rsp->body = template_load(csp, "blocked");
template_fill(&rsp->body, exports);
free_map(exports);
-
+
+ /* FIXME */
+#ifdef __EMX__
+ /*
+ * The entire OS/2 community will hit the stupid Netscape bug
+ * (all three of us! :-) so we'll just keep ourselves out
+ * of this contentious debate and special-case ourselves.
+ * The problem is... a this point in parsing, we don't know
+ * what the csp->http->user_agent is (yet). So we can't use
+ * it to decide if we should work around the NS bug or not.
+ */
+ rsp->status = strdup("200 Request for blocked URL");
+#else
/*
* Workaround for stupid Netscape bug which prevents
* pages from being displayed if loading a referenced
{
rsp->status = strdup("404 Request for blocked URL");
}
-
+#endif /* __EMX__ */
}
return(finish_http_response(rsp));
* Description : Apply all the pcrs jobs from the joblist (re_filterfile)
* to the text buffer that's been accumulated in
* csp->iob->buf and set csp->content_length to the modified
- * size.
+ * size and raise the CSP_FLAG_MODIFIED flag if appropriate.
*
* Parameters :
* 1 : csp = Current client state (buffers, headers, etc...)
char *pcrs_filter_response(struct client_state *csp)
{
int hits=0;
- int size = csp->iob->eod - csp->iob->cur;
+ size_t size;
char *old = csp->iob->cur, *new = NULL;
pcrs_job *job;
struct file_list *fl;
struct re_filterfile_spec *b;
- /* Sanity first ;-) */
- if (size <= 0)
+ /* Sanity first */
+ if (csp->iob->cur >= csp->iob->eod)
{
return(NULL);
}
+ size = 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_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;
+ }
if ( ( NULL == (fl = csp->rlist) ) || ( NULL == (b = fl->f) ) )
{
log_error(LOG_LEVEL_RE_FILTER, " produced %d hits (new size %d).", hits, size);
- csp->content_length = size;
+ /*
+ * If there were no hits, destroy our copy and let
+ * chat() use the original in csp->iob
+ */
+ if (!hits)
+ {
+ free(new);
+ return(NULL);
+ }
- /* fwiw, reset the iob */
+ csp->flags |= CSP_FLAG_MODIFIED;
+ csp->content_length = size;
IOB_RESET(csp);
+
return(new);
}
* Function : gif_deanimate_response
*
* Description : Deanimate the GIF image that has been accumulated in
- * csp->iob->buf and set csp->content_length to the modified
- * size.
+ * csp->iob->buf, set csp->content_length to the modified
+ * size and raise the CSP_FLAG_MODIFIED flag.
*
* Parameters :
* 1 : csp = Current client state (buffers, headers, etc...)
char *p;
int size = 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))) )
{
{
log_error(LOG_LEVEL_DEANIMATE, "Success! GIF shrunk from %d bytes to %d.", size, out->offset);
csp->content_length = out->offset;
+ csp->flags |= CSP_FLAG_MODIFIED;
p = out->buffer;
free(in);
free(out);
}
+/*********************************************************************
+ *
+ * Function : remove_chunked_transfer_coding
+ *
+ * Description : In-situ remove the "chunked" transfer coding as defined
+ * in rfc2616 from a buffer.
+ *
+ * Parameters :
+ * 1 : buffer = Pointer to the text buffer
+ * 2 : size = Number of bytes to be processed
+ *
+ * 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
+ *
+ *********************************************************************/
+int remove_chunked_transfer_coding(char *buffer, const size_t size)
+{
+ size_t newsize = 0;
+ unsigned int chunksize = 0;
+ char *from_p, *to_p;
+
+ assert(buffer);
+ from_p = to_p = buffer;
+
+ if (sscanf(buffer, "%x", &chunksize) != 1)
+ {
+ log_error(LOG_LEVEL_ERROR, "Invalid first chunksize while stripping \"chunked\" transfer coding");
+ return(0);
+ }
+
+ 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);
+ }
+ newsize += chunksize;
+ from_p += 2;
+
+ memmove(to_p, from_p, (size_t) chunksize);
+ to_p = buffer + newsize;
+ from_p += chunksize + 2;
+
+ if (sscanf(from_p, "%x", &chunksize) != 1)
+ {
+ log_error(LOG_LEVEL_ERROR, "Parse error while stripping \"chunked\" transfer coding");
+ return(0);
+ }
+ }
+
+ /* 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);
+
+}
+
+
/*********************************************************************
*
* Function : url_actions