int undefinedEchoLen;
} include_server_config;
-#ifdef MOD_INCLUDE_REDESIGN
/* main parser states */
typedef enum {
PARSE_PRE_HEAD,
strlen((ctx)->error_str), (ctx)->pool, \
(f)->c->bucket_alloc))
-#endif /* MOD_INCLUDE_REDESIGN */
-
#ifdef XBITHACK
#define DEFAULT_XBITHACK xbithack_full
#else
return hl;
}
-#ifndef MOD_INCLUDE_REDESIGN
-/* We've now found a start sequence tag... */
-static apr_bucket* found_start_sequence(apr_bucket *dptr,
- include_ctx_t *ctx,
- apr_size_t tagStart,
- apr_size_t len)
-{
- /* We want to split the bucket at the '<'. */
- ctx->state = PARSE_DIRECTIVE;
- ctx->tag_length = 0;
- ctx->parse_pos = 0;
-
- /* If tagStart indexes the end of the bucket, then tag_start_bucket
- * should be the next bucket
- */
- if (tagStart < len) {
- ctx->tag_start_bucket = dptr;
- ctx->tag_start_index = tagStart;
- }
- else {
- ctx->tag_start_bucket = APR_BUCKET_NEXT(dptr);
- ctx->tag_start_index = 0;
- }
-
- if (ctx->head_start_index > 0) {
- apr_bucket *tmp_bkt;
-
- /* Split the bucket with the start of the tag in it */
- apr_bucket_split(ctx->head_start_bucket, ctx->head_start_index);
- tmp_bkt = APR_BUCKET_NEXT(ctx->head_start_bucket);
- /* If it was a one bucket match */
- if ((tagStart < len) && (dptr == ctx->head_start_bucket)) {
- ctx->tag_start_bucket = tmp_bkt;
- ctx->tag_start_index = tagStart - ctx->head_start_index;
- }
- ctx->head_start_bucket = tmp_bkt;
- ctx->head_start_index = 0;
- }
- return ctx->head_start_bucket;
-}
-
-/* This function returns either a pointer to the split bucket containing the
- * first byte of the BEGINNING_SEQUENCE (after finding a complete match) or it
- * returns NULL if no match found.
- */
-static apr_bucket *find_start_sequence(apr_bucket *dptr, include_ctx_t *ctx,
- apr_bucket_brigade *bb, int *do_cleanup)
-{
- apr_size_t len;
- const char *c;
- const char *buf;
- const char *str = ctx->start_seq ;
- apr_size_t slen = ctx->start_seq_len;
- apr_size_t pos;
-
- *do_cleanup = 0;
-
- do {
- apr_status_t rv = 0;
- int read_done = 0;
-
- if (APR_BUCKET_IS_EOS(dptr)) {
- break;
- }
-
-#if 0
- /* XXX the bucket flush support is commented out for now
- * because it was causing a segfault */
- if (APR_BUCKET_IS_FLUSH(dptr)) {
- apr_bucket *old = dptr;
- dptr = APR_BUCKET_NEXT(old);
- APR_BUCKET_REMOVE(old);
- ctx->output_now = 1;
- ctx->output_flush = 1;
- }
- else
-#endif /* 0 */
- if (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD) {
- ctx->output_now = 1;
- }
- else if (ctx->bytes_parsed > 0) {
- rv = apr_bucket_read(dptr, &buf, &len, APR_NONBLOCK_READ);
- read_done = 1;
- if (APR_STATUS_IS_EAGAIN(rv)) {
- ctx->output_now = 1;
- }
- }
-
- if (ctx->output_now) {
- apr_bucket *start_bucket;
- if (ctx->head_start_index > 0) {
- start_bucket = ctx->head_start_bucket;
- apr_bucket_split(start_bucket, ctx->head_start_index);
- start_bucket = APR_BUCKET_NEXT(start_bucket);
- ctx->head_start_index = 0;
- ctx->head_start_bucket = start_bucket;
- ctx->parse_pos = 0;
- ctx->state = PRE_HEAD;
- }
- else {
- start_bucket = dptr;
- }
- return start_bucket;
- }
-
- if (!read_done) {
- rv = apr_bucket_read(dptr, &buf, &len, APR_BLOCK_READ);
- }
- if (!APR_STATUS_IS_SUCCESS(rv)) {
- ctx->status = rv;
- return NULL;
- }
-
- if (len == 0) { /* end of pipe? */
- dptr = APR_BUCKET_NEXT(dptr);
- continue;
- }
-
- /* Set our buffer to use. */
- c = buf;
-
- /* The last bucket had a left over partial match that we need to
- * complete.
- */
- if (ctx->state == PARSE_HEAD)
- {
- apr_size_t tmpLen;
- tmpLen = (len < (slen - 1)) ? len : (slen - 1);
-
- while (c < buf + tmpLen && *c == str[ctx->parse_pos])
- {
- c++;
- ctx->parse_pos++;
- }
-
- if (str[ctx->parse_pos] == '\0')
- {
- ctx->bytes_parsed += c - buf;
- return found_start_sequence(dptr, ctx, c - buf, len);
- }
- else if (c == buf + tmpLen) {
- dptr = APR_BUCKET_NEXT(dptr);
- continue;
- }
-
- /* False alarm...
- */
- APR_BRIGADE_PREPEND(bb, ctx->ssi_tag_brigade);
-
- /* We know we are at the beginning of this bucket so
- * we can just prepend the saved bytes from the
- * ssi_tag_brigade (which empties the ssi_tag_brigade)
- * and continue processing.
- * We do not need to set do_cleanup beacuse the
- * prepend takes care of that.
- */
- ctx->state = PRE_HEAD;
- ctx->head_start_bucket = NULL;
- ctx->head_start_index = 0;
- }
-
- if (len)
- {
- pos = bndm(str, slen, buf, len, ctx->start_seq_pat);
- if (pos != len)
- {
- ctx->head_start_bucket = dptr;
- ctx->head_start_index = pos;
- ctx->bytes_parsed += pos + slen;
- return found_start_sequence(dptr, ctx, pos + slen, len);
- }
- }
-
- /* Consider the case where we have <!-- at the end of the bucket. */
- if (len > slen) {
- ctx->bytes_parsed += (len - slen);
- c = buf + len - slen;
- }
- else {
- c = buf;
- }
- ctx->parse_pos = 0;
-
- while (c < buf + len)
- {
- if (*c == str[ctx->parse_pos]) {
- if (ctx->state == PRE_HEAD) {
- ctx->state = PARSE_HEAD;
- ctx->head_start_bucket = dptr;
- ctx->head_start_index = c - buf;
- }
- ctx->parse_pos++;
- c++;
- ctx->bytes_parsed++;
- }
- else if (ctx->parse_pos != 0)
- {
- /* DO NOT INCREMENT c IN THIS BLOCK!
- * Don't increment bytes_parsed either.
- * This block is just to reset the indexes and
- * pointers related to parsing the tag start_sequence.
- * The value c needs to be checked again to handle
- * the case where we find "<<!--#". We are now
- * looking at the second "<" and need to restart
- * the start_sequence checking from parse_pos = 0.
- * do_cleanup causes the stored bytes in ssi_tag_brigade
- * to be forwarded on and cleaned up. We may not be
- * able to just prepend the ssi_tag_brigade because
- * we may have advanced too far before we noticed this
- * case, so just flag it and clean it up later.
- */
- *do_cleanup = 1;
- ctx->parse_pos = 0;
- ctx->state = PRE_HEAD;
- ctx->head_start_bucket = NULL;
- ctx->head_start_index = 0;
- }
- else {
- c++;
- ctx->bytes_parsed++;
- }
- }
- dptr = APR_BUCKET_NEXT(dptr);
- } while (dptr != APR_BRIGADE_SENTINEL(bb));
-
-
- return NULL;
-}
-
-static apr_bucket *find_end_sequence(apr_bucket *dptr, include_ctx_t *ctx,
- apr_bucket_brigade *bb)
-{
- apr_size_t len;
- const char *c;
- const char *buf;
- const char *str = ctx->end_seq;
- const char *start;
-
- do {
- apr_status_t rv = 0;
- int read_done = 0;
-
- if (APR_BUCKET_IS_EOS(dptr)) {
- break;
- }
-#if 0
- /* XXX the bucket flush support is commented out for now
- * because it was causing a segfault */
- if (APR_BUCKET_IS_FLUSH(dptr)) {
- apr_bucket *old = dptr;
- dptr = APR_BUCKET_NEXT(old);
- APR_BUCKET_REMOVE(old);
- ctx->output_now = 1;
- ctx->output_flush = 1;
- }
- else
-#endif /* 0 */
- if (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD) {
- ctx->output_now = 1;
- }
- else if (ctx->bytes_parsed > 0) {
- rv = apr_bucket_read(dptr, &buf, &len, APR_NONBLOCK_READ);
- read_done = 1;
- if (APR_STATUS_IS_EAGAIN(rv)) {
- ctx->output_now = 1;
- }
- }
-
- if (ctx->output_now) {
- if (ctx->state == PARSE_DIRECTIVE) {
- /* gonna start over parsing the directive next time through */
- ctx->directive_length = 0;
- ctx->tag_length = 0;
- }
- return dptr;
- }
-
- if (!read_done) {
- rv = apr_bucket_read(dptr, &buf, &len, APR_BLOCK_READ);
- }
- if (!APR_STATUS_IS_SUCCESS(rv)) {
- ctx->status = rv;
- return NULL;
- }
-
- if (len == 0) { /* end of pipe? */
- dptr = APR_BUCKET_NEXT(dptr);
- continue;
- }
- if (dptr == ctx->tag_start_bucket) {
- c = buf + ctx->tag_start_index;
- }
- else {
- c = buf;
- }
- start = c;
- while (c < buf + len) {
- if (*c == str[ctx->parse_pos]) {
- if (ctx->state != PARSE_TAIL) {
- ctx->state = PARSE_TAIL;
- ctx->tail_start_bucket = dptr;
- ctx->tail_start_index = c - buf;
- }
- ctx->parse_pos++;
- if (str[ctx->parse_pos] == '\0') {
- apr_bucket *tmp_buck = dptr;
-
- /* We want to split the bucket at the '>'. The
- * end of the END_SEQUENCE is in the current bucket.
- * The beginning might be in a previous bucket.
- */
- c++;
- ctx->bytes_parsed += (c - start);
- ctx->state = PARSED;
- apr_bucket_split(dptr, c - buf);
- tmp_buck = APR_BUCKET_NEXT(dptr);
- return (tmp_buck);
- }
- }
- else {
- if (ctx->state == PARSE_DIRECTIVE) {
- if (ctx->tag_length == 0) {
- if (!apr_isspace(*c)) {
- const char *tmp = c;
- ctx->tag_start_bucket = dptr;
- ctx->tag_start_index = c - buf;
- do {
- c++;
- } while ((c < buf + len) && !apr_isspace(*c) &&
- *c != *str);
- ctx->tag_length = ctx->directive_length = c - tmp;
- continue;
- }
- }
- else {
- if (!apr_isspace(*c)) {
- ctx->directive_length++;
- }
- else {
- ctx->state = PARSE_TAG;
- }
- ctx->tag_length++;
- }
- }
- else if (ctx->state == PARSE_TAG) {
- const char *tmp = c;
- do {
- c++;
- } while ((c < buf + len) && (*c != *str));
- ctx->tag_length += (c - tmp);
- continue;
- }
- else {
- if (ctx->parse_pos != 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 parse_pos was already 0 then we already checked
- * this.
- */
- ctx->tag_length += ctx->parse_pos;
-
- if (*c == str[0]) {
- ctx->state = PARSE_TAIL;
- ctx->tail_start_bucket = dptr;
- ctx->tail_start_index = c - buf;
- ctx->parse_pos = 1;
- }
- else {
- ctx->tag_length++;
- if (ctx->tag_length > ctx->directive_length) {
- ctx->state = PARSE_TAG;
- }
- else {
- ctx->state = PARSE_DIRECTIVE;
- ctx->directive_length += ctx->parse_pos;
- }
- ctx->tail_start_bucket = NULL;
- ctx->tail_start_index = 0;
- ctx->parse_pos = 0;
- }
- }
- }
- }
- c++;
- }
- ctx->bytes_parsed += (c - start);
- dptr = APR_BUCKET_NEXT(dptr);
- } while (dptr != APR_BRIGADE_SENTINEL(bb));
- return NULL;
-}
-
-/* This function culls through the buckets that have been set aside in the
- * ssi_tag_brigade and copies just the directive part of the SSI tag (none
- * of the start and end delimiter bytes are copied).
- */
-static apr_status_t get_combined_directive (include_ctx_t *ctx,
- request_rec *r,
- apr_bucket_brigade *bb,
- char *tmp_buf,
- apr_size_t tmp_buf_size)
-{
- int done = 0;
- apr_bucket *dptr;
- const char *tmp_from;
- apr_size_t tmp_from_len;
-
- /* If the tag length is longer than the tmp buffer, allocate space. */
- if (ctx->tag_length > tmp_buf_size-1) {
- if ((ctx->combined_tag = apr_pcalloc(r->pool,
- ctx->tag_length + 1)) == NULL) {
- return (APR_ENOMEM);
- }
- } /* Else, just use the temp buffer. */
- else {
- ctx->combined_tag = tmp_buf;
- }
-
- /* Prime the pump. Start at the beginning of the tag... */
- dptr = ctx->tag_start_bucket;
- /* Read the bucket... */
- apr_bucket_read (dptr, &tmp_from, &tmp_from_len, 0);
-
- /* Adjust the pointer to start at the tag within the bucket... */
- if (dptr == ctx->tail_start_bucket) {
- tmp_from_len -= (tmp_from_len - ctx->tail_start_index);
- }
- tmp_from = &tmp_from[ctx->tag_start_index];
- tmp_from_len -= ctx->tag_start_index;
- ctx->curr_tag_pos = ctx->combined_tag;
-
- /* Loop through the buckets from the tag_start_bucket until before
- * the tail_start_bucket copying the contents into the buffer.
- */
- do {
- memcpy (ctx->curr_tag_pos, tmp_from, tmp_from_len);
- ctx->curr_tag_pos += tmp_from_len;
-
- if (dptr == ctx->tail_start_bucket) {
- done = 1;
- }
- else {
- dptr = APR_BUCKET_NEXT (dptr);
- apr_bucket_read (dptr, &tmp_from, &tmp_from_len, 0);
- /* Adjust the count to stop at the beginning of the tail. */
- if (dptr == ctx->tail_start_bucket) {
- tmp_from_len -= (tmp_from_len - ctx->tail_start_index);
- }
- }
- } while ((!done) &&
- (ctx->curr_tag_pos < ctx->combined_tag + ctx->tag_length));
-
- ctx->combined_tag[ctx->tag_length] = '\0';
- ctx->curr_tag_pos = ctx->combined_tag;
-
- return (APR_SUCCESS);
-}
-#endif /* !MOD_INCLUDE_REDESIGN */
-
/*
* decodes a string containing html entities or numeric character references.
* 's' is overwritten with the decoded string.
#define SKIP_TAG_WHITESPACE(ptr) while ((*ptr != '\0') && (apr_isspace (*ptr))) ptr++
-#ifdef MOD_INCLUDE_REDESIGN
static void ap_ssi_get_tag_and_value(include_ctx_t *ctx, char **tag,
char **tag_val, int dodecode)
{
return;
}
-#endif /* MOD_INCLUDE_REDESIGN */
-
-#ifndef MOD_INCLUDE_REDESIGN
-static void ap_ssi_get_tag_and_value(include_ctx_t *ctx, char **tag,
- char **tag_val, int dodecode)
-{
- char *c = ctx->curr_tag_pos;
- int shift_val = 0;
- char term = '\0';
-
- *tag_val = NULL;
- if (ctx->curr_tag_pos > ctx->combined_tag + ctx->tag_length) {
- *tag = NULL;
- return;
- }
- SKIP_TAG_WHITESPACE(c);
- *tag = c; /* First non-whitespace character (could be NULL). */
-
- while (apr_islower(*c)) {
- c++; /* Optimization for the common case where the tag */
- } /* is already lowercase */
-
- while ((*c != '=') && (!apr_isspace(*c)) && (*c != '\0')) {
- *c = apr_tolower(*c); /* find end of tag, lowercasing as we go... */
- c++;
- }
-
- if ((*c == '\0') || (**tag == '=')) {
- if ((**tag == '\0') || (**tag == '=')) {
- *tag = NULL;
- }
- ctx->curr_tag_pos = c;
- return; /* We have found the end of the buffer. */
- } /* We might have a tag, but definitely no value. */
-
- if (*c == '=') {
- *c++ = '\0'; /* Overwrite the '=' with a terminating byte after tag. */
- }
- else { /* Try skipping WS to find the '='. */
- *c++ = '\0'; /* Terminate the tag... */
- SKIP_TAG_WHITESPACE(c);
-
- /* There needs to be an equal sign if there's a value. */
- if (*c != '=') {
- ctx->curr_tag_pos = c;
- return; /* There apparently was no value. */
- }
- else {
- c++; /* Skip the equals sign. */
- }
- }
-
- SKIP_TAG_WHITESPACE(c);
- if (*c == '"' || *c == '\'' || *c == '`') {
- /* Allow quoted values for space inclusion.
- * NOTE: This does not pass the quotes on return.
- */
- term = *c++;
- }
-
- *tag_val = c;
- if (!term) {
- while (!apr_isspace(*c) && (*c != '\0')) {
- c++;
- }
- }
- else {
- while ((*c != term) && (*c != '\0') && (*c != '\\')) {
- /* Quickly scan past the string until we reach
- * either the end of the tag or a backslash. If
- * we find a backslash, we have to switch to the
- * more complicated parser loop that follows.
- */
- c++;
- }
- if (*c == '\\') {
- do {
- /* Accept \" (or ' or `) as valid quotation of string.
- */
- if (*c == '\\') {
- /* Overwrite the "\" during the embedded
- * escape sequence of '"'. "\'" or '`'.
- * Shift bytes from here to next delimiter.
- */
- c++;
- if (*c == term) {
- shift_val++;
- }
- if (shift_val > 0) {
- *(c-shift_val) = *c;
- }
- if (*c == '\0') {
- break;
- }
- }
-
- c++;
- if (shift_val > 0) {
- *(c-shift_val) = *c;
- }
- } while ((*c != term) && (*c != '\0'));
- }
- }
-
- *(c-shift_val) = '\0'; /* Overwrites delimiter (term or WS) with NULL. */
- ctx->curr_tag_pos = ++c;
- if (dodecode) {
- decodehtml(*tag_val);
- }
-
- return;
-}
-#endif /* !MOD_INCLUDE_REDESIGN */
/* initial buffer size for power-of-two allocator in ap_ssi_parse_string */
#define PARSE_STRING_INITIAL_SIZE 64
/* -------------------------- The main function --------------------------- */
-#ifdef MOD_INCLUDE_REDESIGN
/*
* returns the index position of the first byte of start_seq (or the len of
* the buffer as non-match)
apr_brigade_destroy(pass_bb);
return rv;
}
-#endif /* MOD_INCLUDE_REDESIGN */
-
-#ifndef MOD_INCLUDE_REDESIGN
-static apr_status_t send_parsed_content(apr_bucket_brigade **bb,
- request_rec *r, ap_filter_t *f)
-{
- include_ctx_t *ctx = f->ctx;
- apr_bucket *dptr = APR_BRIGADE_FIRST(*bb);
- apr_bucket *tmp_dptr;
- apr_bucket_brigade *tag_and_after;
- apr_status_t rv = APR_SUCCESS;
-
- if (r->args) { /* add QUERY stuff to env cause it ain't yet */
- char *arg_copy = apr_pstrdup(r->pool, r->args);
-
- apr_table_setn(r->subprocess_env, "QUERY_STRING", r->args);
- ap_unescape_url(arg_copy);
- apr_table_setn(r->subprocess_env, "QUERY_STRING_UNESCAPED",
- ap_escape_shell_cmd(r->pool, arg_copy));
- }
-
- while (dptr != APR_BRIGADE_SENTINEL(*bb) && !APR_BUCKET_IS_EOS(dptr)) {
- /* State to check for the STARTING_SEQUENCE. */
- if ((ctx->state == PRE_HEAD) || (ctx->state == PARSE_HEAD)) {
- int do_cleanup = 0;
- apr_size_t cleanup_bytes = ctx->parse_pos;
-
- tmp_dptr = find_start_sequence(dptr, ctx, *bb, &do_cleanup);
- if (!APR_STATUS_IS_SUCCESS(ctx->status)) {
- return ctx->status;
- }
-
- /* The few bytes stored in the ssi_tag_brigade turned out not to
- * be a tag after all. This can only happen if the starting
- * tag actually spans brigades. This should be very rare.
- */
- if ((do_cleanup) && (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade))) {
- apr_bucket *tmp_bkt;
-
- tmp_bkt = apr_bucket_immortal_create(ctx->start_seq,
- cleanup_bytes,
- r->connection->bucket_alloc);
- APR_BRIGADE_INSERT_HEAD(*bb, tmp_bkt);
- apr_brigade_cleanup(ctx->ssi_tag_brigade);
- }
-
- /* If I am inside a conditional (if, elif, else) that is false
- * then I need to throw away anything contained in it.
- */
- if ((!(ctx->flags & FLAG_PRINTING)) &&
- (dptr != APR_BRIGADE_SENTINEL(*bb))) {
- apr_bucket *stop = (!tmp_dptr && ctx->state == PARSE_HEAD)
- ? ctx->head_start_bucket
- : tmp_dptr;
-
- while ((dptr != APR_BRIGADE_SENTINEL(*bb)) && (dptr != stop)) {
- apr_bucket *free_bucket = dptr;
-
- dptr = APR_BUCKET_NEXT(dptr);
- if (!APR_BUCKET_IS_METADATA(free_bucket)) {
- apr_bucket_delete(free_bucket);
- }
- }
- }
-
- /* Adjust the current bucket position based on what was found... */
- if ((tmp_dptr != NULL) && (ctx->state == PARSE_DIRECTIVE)) {
- if (ctx->tag_start_bucket != NULL) {
- dptr = ctx->tag_start_bucket;
- }
- else {
- dptr = APR_BRIGADE_SENTINEL(*bb);
- }
- }
- else if ((tmp_dptr != NULL) &&
- (ctx->output_now ||
- (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD))) {
- /* Send the large chunk of pre-tag bytes... */
- tag_and_after = apr_brigade_split(*bb, tmp_dptr);
- if (ctx->output_flush) {
- APR_BRIGADE_INSERT_TAIL(*bb, apr_bucket_flush_create((*bb)->bucket_alloc));
- }
-
- rv = ap_pass_brigade(f->next, *bb);
- if (rv != APR_SUCCESS) {
- return rv;
- }
- *bb = tag_and_after;
- dptr = tmp_dptr;
- ctx->output_flush = 0;
- ctx->bytes_parsed = 0;
- ctx->output_now = 0;
- }
- else if (tmp_dptr == NULL) {
- /* There was no possible SSI tag in the
- * remainder of this brigade... */
- dptr = APR_BRIGADE_SENTINEL(*bb);
- }
- }
-
- /* State to check for the ENDING_SEQUENCE. */
- if (((ctx->state == PARSE_DIRECTIVE) ||
- (ctx->state == PARSE_TAG) ||
- (ctx->state == PARSE_TAIL)) &&
- (dptr != APR_BRIGADE_SENTINEL(*bb))) {
- tmp_dptr = find_end_sequence(dptr, ctx, *bb);
- if (!APR_STATUS_IS_SUCCESS(ctx->status)) {
- return ctx->status;
- }
-
- if (tmp_dptr != NULL) {
- dptr = tmp_dptr; /* Adjust bucket pos... */
-
- /* If some of the tag has already been set aside then set
- * aside remainder of tag. Now the full tag is in
- * ssi_tag_brigade.
- * If none has yet been set aside, then leave it all where it
- * is.
- * In any event after this the entire set of tag buckets will
- * be in one place or another.
- */
- if (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade)) {
- tag_and_after = apr_brigade_split(*bb, dptr);
- APR_BRIGADE_CONCAT(ctx->ssi_tag_brigade, *bb);
- *bb = tag_and_after;
- }
- else if (ctx->output_now ||
- (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD)) {
- SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx, f->next, rv);
- if (rv != APR_SUCCESS) {
- return rv;
- }
- ctx->output_flush = 0;
- ctx->output_now = 0;
- }
- }
- else {
- /* remainder of this brigade... */
- dptr = APR_BRIGADE_SENTINEL(*bb);
- }
- }
-
- /* State to processed the directive... */
- if (ctx->state == PARSED) {
- apr_bucket *content_head = NULL, *tmp_bkt;
- apr_size_t tmp_i;
- char tmp_buf[TMP_BUF_SIZE];
- int (*handle_func)(include_ctx_t *, apr_bucket_brigade **,
- request_rec *, ap_filter_t *, apr_bucket *,
- apr_bucket **);
-
- /* By now the full tag (all buckets) should either be set aside into
- * ssi_tag_brigade or contained within the current bb. All tag
- * processing from here on can assume that.
- */
-
- /* At this point, everything between ctx->head_start_bucket and
- * ctx->tail_start_bucket is an SSI
- * directive, we just have to deal with it now.
- */
- if (get_combined_directive(ctx, r, *bb, tmp_buf,
- TMP_BUF_SIZE) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "mod_include: error copying directive in %s",
- r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_bkt, dptr, content_head);
-
- /* DO CLEANUP HERE!!!!! */
- tmp_dptr = ctx->head_start_bucket;
- if (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade)) {
- apr_brigade_cleanup(ctx->ssi_tag_brigade);
- }
- else {
- do {
- tmp_bkt = tmp_dptr;
- tmp_dptr = APR_BUCKET_NEXT (tmp_dptr);
- apr_bucket_delete(tmp_bkt);
- } while ((tmp_dptr != dptr) &&
- (tmp_dptr != APR_BRIGADE_SENTINEL(*bb)));
- }
-
- return APR_SUCCESS;
- }
-
- /* Can't destroy the tag buckets until I'm done processing
- * because the combined_tag might just be pointing to
- * the contents of a single bucket!
- */
-
- /* Retrieve the handler function to be called for this directive
- * from the functions registered in the hash table.
- * Need to lower case the directive for proper matching. Also need
- * to have it NULL terminated for proper hash matching.
- */
- for (tmp_i = 0; tmp_i < ctx->directive_length; tmp_i++) {
- ctx->combined_tag[tmp_i] =
- apr_tolower(ctx->combined_tag[tmp_i]);
- }
- ctx->combined_tag[ctx->directive_length] = '\0';
- ctx->curr_tag_pos = &ctx->combined_tag[ctx->directive_length+1];
-
- handle_func =
- (include_handler_fn_t *)apr_hash_get(include_hash,
- ctx->combined_tag,
- ctx->directive_length);
- if (handle_func != NULL) {
- rv = (*handle_func)(ctx, bb, r, f, dptr, &content_head);
- if ((rv != 0) && (rv != 1)) {
- return (rv);
- }
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "unknown directive \"%s\" in parsed doc %s",
- ctx->combined_tag, r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_bkt, dptr, content_head);
- }
-
- /* This chunk of code starts at the first bucket in the chain
- * of tag buckets (assuming that by this point the bucket for
- * the STARTING_SEQUENCE has been split) and loops through to
- * the end of the tag buckets freeing them all.
- *
- * Remember that some part of this may have been set aside
- * into the ssi_tag_brigade and the remainder (possibly as
- * little as one byte) will be in the current brigade.
- *
- * The value of dptr should have been set during the
- * PARSE_TAIL state to the first bucket after the
- * ENDING_SEQUENCE.
- *
- * The value of content_head may have been set during processing
- * of the directive. If so, the content was inserted in front
- * of the dptr bucket. The inserted buckets should not be thrown
- * away here, but they should also not be parsed later.
- */
- if (content_head == NULL) {
- content_head = dptr;
- }
- tmp_dptr = ctx->head_start_bucket;
- if (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade)) {
- apr_brigade_cleanup(ctx->ssi_tag_brigade);
- }
- else {
- do {
- tmp_bkt = tmp_dptr;
- tmp_dptr = APR_BUCKET_NEXT (tmp_dptr);
- apr_bucket_delete(tmp_bkt);
- } while ((tmp_dptr != content_head) &&
- (tmp_dptr != APR_BRIGADE_SENTINEL(*bb)));
- }
- if (ctx->combined_tag == tmp_buf) {
- ctx->combined_tag = NULL;
- }
-
- /* Don't reset the flags or the nesting level!!! */
- ctx->parse_pos = 0;
- ctx->head_start_bucket = NULL;
- ctx->head_start_index = 0;
- ctx->tag_start_bucket = NULL;
- ctx->tag_start_index = 0;
- ctx->tail_start_bucket = NULL;
- ctx->tail_start_index = 0;
- ctx->curr_tag_pos = NULL;
- ctx->tag_length = 0;
- ctx->directive_length = 0;
-
- if (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade)) {
- apr_brigade_cleanup(ctx->ssi_tag_brigade);
- }
-
- ctx->state = PRE_HEAD;
- }
- }
-
- /* We have nothing more to send, stop now. */
- if (dptr != APR_BRIGADE_SENTINEL(*bb) &&
- APR_BUCKET_IS_EOS(dptr)) {
- /* We might have something saved that we never completed, but send
- * down unparsed. This allows for <!-- at the end of files to be
- * sent correctly. */
- if (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade)) {
- APR_BRIGADE_CONCAT(ctx->ssi_tag_brigade, *bb);
- return ap_pass_brigade(f->next, ctx->ssi_tag_brigade);
- }
- return ap_pass_brigade(f->next, *bb);
- }
-
- /* If I am in the middle of parsing an SSI tag then I need to set aside
- * the pertinent trailing buckets and pass on the initial part of the
- * brigade. The pertinent parts of the next brigades will be added to
- * these set aside buckets to form the whole tag and will be processed
- * once the whole tag has been found.
- */
- if (ctx->state == PRE_HEAD) {
- if (!APR_BRIGADE_EMPTY(*bb)) {
- /* pass it along... */
- rv = ap_pass_brigade(f->next, *bb);
- if (rv != APR_SUCCESS) {
- return rv;
- }
- ctx->bytes_parsed = 0;
- }
- }
- else if (ctx->state == PARSED) { /* Invalid internal condition... */
- apr_bucket *content_head = NULL, *tmp_bkt;
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Invalid mod_include state during file %s", r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_bkt, APR_BRIGADE_FIRST(*bb), content_head);
- }
- else { /* Entire brigade is middle chunk of SSI tag... */
- if (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade)) {
- APR_BRIGADE_CONCAT(ctx->ssi_tag_brigade, *bb);
- }
- else { /* End of brigade contains part of SSI tag... */
- apr_bucket *last;
- if (ctx->head_start_index > 0) {
- apr_bucket_split(ctx->head_start_bucket, ctx->head_start_index);
- ctx->head_start_bucket =
- APR_BUCKET_NEXT(ctx->head_start_bucket);
- ctx->head_start_index = 0;
- }
- /* Set aside tag, pass pre-tag... */
- tag_and_after = apr_brigade_split(*bb, ctx->head_start_bucket);
- rv = ap_pass_brigade(f->next, *bb);
- if (rv != APR_SUCCESS) {
- return rv;
- }
-
- /* Set aside the partial tag
- * Exception: if there's an EOS at the end of this brigade,
- * the tag will never be completed, so send an error and EOS
- */
- last = APR_BRIGADE_LAST(tag_and_after);
- if (APR_BUCKET_IS_EOS(last)) {
- /* Remove everything before the EOS (i.e., the partial tag)
- * and replace it with an error msg */
- apr_bucket *b;
- apr_bucket *err_bucket = NULL;
- for (b = APR_BRIGADE_FIRST(tag_and_after);
- !APR_BUCKET_IS_EOS(b);
- b = APR_BRIGADE_FIRST(tag_and_after)) {
- APR_BUCKET_REMOVE(b);
- apr_bucket_destroy(b);
- }
- CREATE_ERROR_BUCKET(ctx, err_bucket, b, err_bucket);
- rv = ap_pass_brigade(f->next, tag_and_after);
- }
- else {
- ap_save_brigade(f, &ctx->ssi_tag_brigade,
- &tag_and_after, r->pool);
- }
- if (rv != APR_SUCCESS) {
- return rv;
- }
- ctx->bytes_parsed = 0;
- }
- }
- return APR_SUCCESS;
-}
-#endif /* !MOD_INCLUDE_REDESIGN */
static void *create_includes_dir_config(apr_pool_t *p, char *dummy)
{
static apr_status_t includes_filter(ap_filter_t *f, apr_bucket_brigade *b)
{
request_rec *r = f->r;
-#ifdef MOD_INCLUDE_REDESIGN
ssi_ctx_t *ctx = f->ctx;
-#else
- include_ctx_t *ctx = f->ctx;
-#endif
request_rec *parent;
include_dir_config *conf =
(include_dir_config *)ap_get_module_config(r->per_dir_config,
}
if (!f->ctx) {
-#ifdef MOD_INCLUDE_REDESIGN
/* create context for this filter */
f->ctx = ctx = apr_palloc(f->c->pool, sizeof(*ctx));
ctx->ctx = apr_pcalloc(f->c->pool, sizeof(*ctx->ctx));
else {
ctx->ctx->bytes_parsed = 0;
}
-#else /* MOD_INCLUDE_REDESIGN */
- f->ctx = ctx = apr_pcalloc(f->c->pool, sizeof(*ctx));
- ctx->state = PRE_HEAD;
- ctx->flags = (FLAG_PRINTING | FLAG_COND_TRUE);
- if (ap_allow_options(r) & OPT_INCNOEXEC) {
- ctx->flags |= FLAG_NO_EXEC;
- }
- ctx->ssi_tag_brigade = apr_brigade_create(f->c->pool,
- f->c->bucket_alloc);
- ctx->status = APR_SUCCESS;
-
- ctx->error_str = conf->default_error_msg;
- ctx->time_str = conf->default_time_fmt;
- ctx->pool = f->c->pool;
- ctx->start_seq_pat = &sconf->start_seq_pat;
- ctx->start_seq = sconf->default_start_tag;
- ctx->start_seq_len = sconf->start_tag_len;
- ctx->end_seq = sconf->default_end_tag;
- }
- else {
- ctx->bytes_parsed = 0;
- }
-#endif /* !MOD_INCLUDE_REDESIGN */
if ((parent = ap_get_module_config(r->request_config, &include_module))) {
/* Kludge --- for nested includes, we want to keep the subprocess
apr_table_unset(f->r->headers_out, "Last-Modified");
}
-#ifdef MOD_INCLUDE_REDESIGN
/* add QUERY stuff to env cause it ain't yet */
if (r->args) {
char *arg_copy = apr_pstrdup(r->pool, r->args);
}
return send_parsed_content(f, b);
-#else
- return send_parsed_content(&b, r, f);
-#endif
}
static void ap_register_include_handler(char *tag, include_handler_fn_t *func)