From 4363b681cf9d4ba06bdc61ce80ba3ea9ac25e5e3 Mon Sep 17 00:00:00 2001 From: Ryan Bloom Date: Wed, 13 Sep 2000 02:07:40 +0000 Subject: [PATCH] First pass at mod_include as a filter. This is at an incredibly alpha stage, but it should compile for everybody now. I have experienced a few seg faults that I haven't been able to track down yet, but it should compile on all platforms, which is better than before this patch. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86211 13f79535-47bb-0310-9956-ffa450edef68 --- modules/filters/mod_include.c | 533 +++++++++++++++++----------------- 1 file changed, 273 insertions(+), 260 deletions(-) diff --git a/modules/filters/mod_include.c b/modules/filters/mod_include.c index eddedf1efe..fc4af31685 100644 --- a/modules/filters/mod_include.c +++ b/modules/filters/mod_include.c @@ -89,6 +89,7 @@ #else #include "apr_strings.h" #include "ap_config.h" +#include "util_filter.h" #include "httpd.h" #include "http_config.h" #include "http_request.h" @@ -112,6 +113,7 @@ #define STARTING_SEQUENCE "" + #define DEFAULT_ERROR_MSG "[an error occurred while processing this directive]" #define DEFAULT_TIME_FORMAT "%A, %d-%b-%Y %H:%M:%S %Z" #define SIZEFMT_BYTES 0 @@ -179,100 +181,55 @@ static void add_include_vars(request_rec *r, char *timefmt) /* --------------------------- Parser functions --------------------------- */ #define OUTBUFSIZE 4096 -/* PUT_CHAR and FLUSH_BUF currently only work within the scope of - * find_string(); they are hacks to avoid calling rputc for each and - * every character output. A common set of buffering calls for this - * type of output SHOULD be implemented. - */ -#define PUT_CHAR(c,r) \ - { \ - outbuf[outind++] = c; \ - if (outind == OUTBUFSIZE) { \ - FLUSH_BUF(r) \ - }; \ - } - -/* there SHOULD be some error checking on the return value of - * rwrite, however it is unclear what the API for rwrite returning - * errors is and little can really be done to help the error in - * any case. - */ -#define FLUSH_BUF(r) \ - { \ - ap_rwrite(outbuf, outind, r); \ - outind = 0; \ - } -/* - * f: file handle being read from - * c: character to read into - * ret: return value to use if input fails - * r: current request_rec - * - * This macro is redefined after find_string() for historical reasons - * to avoid too many code changes. This is one of the many things - * that should be fixed. - */ -#define GET_CHAR(f,c,ret,r) \ - { \ - apr_status_t status = apr_getc(&c, f); \ - if (status != APR_SUCCESS) { /* either EOF or error -- needs error handling if latter */ \ - if (status != APR_EOF) { \ - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, \ - "encountered error in GET_CHAR macro, " \ - "mod_include."); \ - } \ - FLUSH_BUF(r); \ - apr_close(f); \ - return ret; \ - } \ - } - -static int find_string(apr_file_t *in, const char *str, request_rec *r, int printing) +static ap_bucket *find_string(ap_bucket *dptr, const char *str, ap_bucket *end) { - int x, l = strlen(str), p; - char outbuf[OUTBUFSIZE]; - int outind = 0; - char c; + int len; + const char *c; + const char *buf; + int state = 0; - p = 0; - while (1) { - GET_CHAR(in, c, 1, r); - if (c == str[p]) { - if ((++p) == l) { - FLUSH_BUF(r); - return 0; - } + do { + if (dptr->read(dptr, &buf, &len, 0) == AP_END_OF_BRIGADE) { + break; } - else { - if (printing) { - for (x = 0; x < p; x++) { - PUT_CHAR(str[x], r); + c = buf; + while (c - buf != len) { + if (*c == str[state]) { + state++; + } + else { + if (str[state] == '\0') { + /* We want to split the bucket at the '<' and '>' + * respectively. That means adjusting where we split based + * on what we are searching for. + */ + if (str[0] == '<') { + dptr->split(dptr, c - buf - strlen(str)); + } + else { + dptr->split(dptr, c - buf); + } + return AP_BUCKET_NEXT(dptr); + } + else { + state = 0; + /* The reason for this, is that we need to make sure + * that we catch cases like <<--#. This makes the + * second check after the original check fails. + */ + if (*c == buf[state]) { + state++; + } } - PUT_CHAR(c, r); } - p = 0; + c++; } - } + dptr = AP_BUCKET_NEXT(dptr); + } while (AP_BUCKET_PREV(dptr) != end); + return NULL; } -#undef FLUSH_BUF -#undef PUT_CHAR -#undef GET_CHAR -#define GET_CHAR(f,c,r,p) \ - { \ - apr_status_t status = apr_getc(&c, f); \ - if (status != APR_SUCCESS) { /* either EOF or error -- needs error handling if latter */ \ - if (status != APR_EOF) { \ - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, \ - "encountered error in GET_CHAR macro, " \ - "mod_include."); \ - } \ - apr_close(f); \ - return r; \ - } \ - } - /* * decodes a string containing html entities or numeric character references. * 's' is overwritten with the decoded string. @@ -373,26 +330,51 @@ otilde\365oslash\370ugrave\371uacute\372yacute\375" /* 6 */ * the tag value is html decoded if dodecode is non-zero */ -static char *get_tag(apr_pool_t *p, apr_file_t *in, char *tag, int tagbuf_len, int dodecode) +static char *get_tag(apr_pool_t *p, ap_bucket *in, char *tag, int tagbuf_len, int dodecode, apr_off_t *offset) { - char *t = tag, *tag_val, c, term; + ap_bucket *dptr = in; + const char *c; + const char *str; + int length; + char *t = tag, *tag_val, term; + int len; /* makes code below a little less cluttered */ --tagbuf_len; - do { /* skip whitespace */ - GET_CHAR(in, c, NULL, p); - } while (apr_isspace(c)); + /* Remove all whitespace */ + while (dptr) { + dptr->read(dptr, &str, &length, 0); + c = str + *offset; + while (c - str < length) { + if (!apr_isspace(*c)) { + break; + } + } + if (!apr_isspace(*c)) { + break; + } + dptr = AP_BUCKET_NEXT(dptr); + } /* tags can't start with - */ - if (c == '-') { - GET_CHAR(in, c, NULL, p); - if (c == '-') { + if (*c == '-') { + c++; + if (c == '\0') { + dptr->read(dptr, &str, &length, 0); + c = str; + } + if (*c == '-') { do { - GET_CHAR(in, c, NULL, p); - } while (apr_isspace(c)); - if (c == '>') { + c++; + if (c == '\0') { + dptr->read(dptr, &str, &length, 0); + c = str; + } + } while (apr_isspace(*c)); + if (*c == '>') { apr_cpystrn(tag, "done", tagbuf_len); + *offset = c - str; return tag; } } @@ -405,85 +387,127 @@ static char *get_tag(apr_pool_t *p, apr_file_t *in, char *tag, int tagbuf_len, i *t = '\0'; return NULL; } - if (c == '=' || apr_isspace(c)) { + if (*c == '=' || apr_isspace(*c)) { break; } - *(t++) = apr_tolower(c); - GET_CHAR(in, c, NULL, p); + *(t++) = apr_tolower(*c); + c++; + if (c == '\0') { + dptr->read(dptr, &str, &length, 0); + c = str; + } } *t++ = '\0'; tag_val = t; - while (apr_isspace(c)) { - GET_CHAR(in, c, NULL, p); /* space before = */ + while (apr_isspace(*c)) { + c++; + if (c == '\0') { + dptr->read(dptr, &str, &length, 0); + c = str; + } } - if (c != '=') { - apr_ungetc(c, in); + if (*c != '=') { + *c--; return NULL; } do { - GET_CHAR(in, c, NULL, p); /* space after = */ - } while (apr_isspace(c)); + c++; + if (c == '\0') { + dptr->read(dptr, &str, &length, 0); + c = str; + } + } while (apr_isspace(*c)); /* we should allow a 'name' as a value */ - if (c != '"' && c != '\'') { + if (*c != '"' && *c != '\'') { return NULL; } - term = c; + term = *c; while (1) { - GET_CHAR(in, c, NULL, p); + c++; + if (c == '\0') { + dptr->read(dptr, &str, &length, 0); + c = str; + } if (t - tag == tagbuf_len) { *t = '\0'; return NULL; } /* Want to accept \" as a valid character within a string. */ - if (c == '\\') { - *(t++) = c; /* Add backslash */ - GET_CHAR(in, c, NULL, p); - if (c == term) { /* Only if */ - *(--t) = c; /* Replace backslash ONLY for terminator */ + if (*c == '\\') { + *(t++) = *c; /* Add backslash */ + c++; + if (c == '\0') { + dptr->read(dptr, &str, &length, 0); + c = str; + } + if (*c == term) { /* Only if */ + *(--t) = *c; /* Replace backslash ONLY for terminator */ } } - else if (c == term) { + else if (*c == term) { break; } - *(t++) = c; + *(t++) = *c; } *t = '\0'; if (dodecode) { decodehtml(tag_val); } + *offset = c - str; return apr_pstrdup(p, tag_val); } -static int get_directive(apr_file_t *in, char *dest, size_t len, apr_pool_t *p) +static int get_directive(ap_bucket *in, char *dest, size_t len, apr_pool_t *p) { + ap_bucket *dptr = in; char *d = dest; - char c; + const char *c; + const char *str; + int length; /* make room for nul terminator */ --len; - /* skip initial whitespace */ - while (1) { - GET_CHAR(in, c, 1, p); - if (!apr_isspace(c)) { + while (dptr) { + dptr->read(dptr, &str, &length, 0); + /* need to start past the