From: André Malo Date: Wed, 20 Aug 2003 16:41:27 +0000 (+0000) Subject: now drop the old code X-Git-Tag: pre_ajp_proxy~1253 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e5e25dfa94213070d51e5eb2a39700e846486a55;p=apache now drop the old code git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@101037 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/filters/mod_include.c b/modules/filters/mod_include.c index 6a56606eef..26cb2f57cf 100644 --- a/modules/filters/mod_include.c +++ b/modules/filters/mod_include.c @@ -128,7 +128,6 @@ typedef struct { int undefinedEchoLen; } include_server_config; -#ifdef MOD_INCLUDE_REDESIGN /* main parser states */ typedef enum { PARSE_PRE_HEAD, @@ -186,8 +185,6 @@ typedef struct { strlen((ctx)->error_str), (ctx)->pool, \ (f)->c->bucket_alloc)) -#endif /* MOD_INCLUDE_REDESIGN */ - #ifdef XBITHACK #define DEFAULT_XBITHACK xbithack_full #else @@ -378,465 +375,6 @@ static apr_size_t bndm(const char *n, apr_size_t nl, const char *h, 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 . 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. @@ -951,7 +489,6 @@ otilde\365oslash\370ugrave\371uacute\372yacute\375" /* 6 */ #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) { @@ -986,119 +523,6 @@ static void ap_ssi_get_tag_and_value(include_ctx_t *ctx, char **tag, 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 @@ -3015,7 +2439,6 @@ static int handle_printenv(include_ctx_t *ctx, apr_bucket_brigade **bb, /* -------------------------- 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) @@ -4009,367 +3432,6 @@ static apr_status_t send_parsed_content(ap_filter_t *f, apr_bucket_brigade *bb) 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