]> git.pld-linux.org Git - packages/apache.git/commitdiff
- obsolete
authorJakub Bogusz <qboosh@pld-linux.org>
Sat, 20 Mar 2004 13:16:27 +0000 (13:16 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    apache-posix_syntax -> 1.2
    httpd-2.0.45-davfs.patch -> 1.2
    httpd-2.0.45-proxy.patch -> 1.2
    httpd-2.0.46-davbadfrag.patch -> 1.2
    httpd-2.0.46-execfail.patch -> 1.2
    httpd-2.0.46-graceful.patch -> 1.2
    httpd-2.0.46-logtimez.patch -> 1.2
    httpd-2.0.46-metharray.patch -> 1.2
    httpd-2.0.46-sslerr.patch -> 1.2
    httpd-2.0.46-sslio.patch -> 1.2
    httpd-2.0.47-ldapshm.patch -> 1.2
    httpd-2.0.48-CAN-2003-0020.patch -> 1.2
    httpd-2.0.48-abench.patch -> 1.2
    httpd-2.0.48-autoindex.patch -> 1.2
    httpd-2.0.48-include.patch -> 1.2
    httpd-2.0.48-proxy11.patch -> 1.2
    httpd-2.0.48-sslvars.patch -> 1.2
    httpd-2.0.48-status.patch -> 1.2
    httpd-2.0.48-usertrack.patch -> 1.2
    httpd-2.0.48-worker.patch -> 1.2

20 files changed:
apache-posix_syntax [deleted file]
httpd-2.0.45-davfs.patch [deleted file]
httpd-2.0.45-proxy.patch [deleted file]
httpd-2.0.46-davbadfrag.patch [deleted file]
httpd-2.0.46-execfail.patch [deleted file]
httpd-2.0.46-graceful.patch [deleted file]
httpd-2.0.46-logtimez.patch [deleted file]
httpd-2.0.46-metharray.patch [deleted file]
httpd-2.0.46-sslerr.patch [deleted file]
httpd-2.0.46-sslio.patch [deleted file]
httpd-2.0.47-ldapshm.patch [deleted file]
httpd-2.0.48-CAN-2003-0020.patch [deleted file]
httpd-2.0.48-abench.patch [deleted file]
httpd-2.0.48-autoindex.patch [deleted file]
httpd-2.0.48-include.patch [deleted file]
httpd-2.0.48-proxy11.patch [deleted file]
httpd-2.0.48-sslvars.patch [deleted file]
httpd-2.0.48-status.patch [deleted file]
httpd-2.0.48-usertrack.patch [deleted file]
httpd-2.0.48-worker.patch [deleted file]

diff --git a/apache-posix_syntax b/apache-posix_syntax
deleted file mode 100644 (file)
index 5b149de..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
---- httpd-2.0.48/srclib/apr/build/buildcheck.sh.org    2003-06-16 20:47:21.000000000 +0000
-+++ httpd-2.0.48/srclib/apr/build/buildcheck.sh        2004-01-07 22:30:54.000000000 +0000
-@@ -3,7 +3,7 @@
- echo "buildconf: checking installation..."
- # autoconf 2.13 or newer
--ac_version=`${AUTOCONF:-autoconf} --version 2>/dev/null|head -1|sed -e 's/^[^0-9]*//' -e 's/[a-z]* *$//'`
-+ac_version=`${AUTOCONF:-autoconf} --version 2>/dev/null|head -n1|sed -e 's/^[^0-9]*//' -e 's/[a-z]* *$//'`
- if test -z "$ac_version"; then
- echo "buildconf: autoconf not found."
- echo "           You need autoconf version 2.13 or newer installed"
-@@ -22,7 +22,7 @@
- # libtool 1.3.3 or newer
- libtool=`build/PrintPath glibtool libtool`
--lt_pversion=`$libtool --version 2>/dev/null|head -1|sed -e 's/^[^0-9]*//' -e 's/[- ].*//'`
-+lt_pversion=`$libtool --version 2>/dev/null|head -n 1|sed -e 's/^[^0-9]*//' -e 's/[- ].*//'`
- if test -z "$lt_pversion"; then
- echo "buildconf: libtool not found."
- echo "           You need libtool version 1.3.3 or newer installed"
diff --git a/httpd-2.0.45-davfs.patch b/httpd-2.0.45-davfs.patch
deleted file mode 100644 (file)
index 4612001..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-
-Fix for http://nagoya.apache.org/bugzilla/show_bug.cgi?id=14969
-
---- httpd-2.0.45/modules/dav/fs/dbm.c.davfs    2003-05-19 14:33:22.000000000 +0100
-+++ httpd-2.0.45/modules/dav/fs/dbm.c  2003-05-19 14:33:33.000000000 +0100
-@@ -599,7 +599,7 @@
-     ** we don't know the namespace yet, then add it to the map and to our
-     ** table of known namespaces.
-     */
--    pmap = apr_palloc(db->pool, namespaces->nelts * sizeof(*pmap));
-+    m->ns_map = pmap = apr_palloc(db->pool, namespaces->nelts * sizeof(*pmap));
-     for (i = namespaces->nelts, puri = (const char **)namespaces->elts;
-          i-- > 0;
-          ++puri, ++pmap) {
-@@ -627,7 +627,6 @@
-         }
-     }
--    m->ns_map = pmap;
-     *mapping = m;
-     return NULL;
- }
diff --git a/httpd-2.0.45-proxy.patch b/httpd-2.0.45-proxy.patch
deleted file mode 100644 (file)
index 0eeb711..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-
-Fix handling of status-line without trailing space. (2.0.49)
-
-Fix leak in reverse proxy request body handling. (2.0.49)
-
---- httpd-2.0.46/modules/proxy/proxy_http.c.proxy
-+++ httpd-2.0.46/modules/proxy/proxy_http.c
-@@ -665,7 +665,8 @@
-             }
-             /* We can't pass this EOS to the output_filters. */
--            APR_BUCKET_REMOVE(APR_BRIGADE_LAST(bb));
-+            e = APR_BRIGADE_LAST(bb);
-+            apr_bucket_delete(e);
-             seen_eos = 1;
-         }
-@@ -756,16 +757,18 @@
-             backasswards = 0;
-             keepchar = buffer[12];
--            if (keepchar == '\0') {
--                ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
--                             r->server, "proxy: bad HTTP/%d.%d status line "
--                             "returned by %s (%s)", major, minor, r->uri,
--                             r->method);
--            }
-             buffer[12] = '\0';
-             r->status = atoi(&buffer[9]);
--            buffer[12] = keepchar;
-+            if (keepchar != '\0') {
-+                buffer[12] = keepchar;
-+            } else {
-+                /* 2616 requires the space in Status-Line; the origin
-+                 * server may have sent one but ap_rgetline_core will
-+                 * have stripped it. */
-+                buffer[12] = ' ';
-+                buffer[13] = '\0';
-+            }
-             r->status_line = apr_pstrdup(p, &buffer[9]);
-             
diff --git a/httpd-2.0.46-davbadfrag.patch b/httpd-2.0.46-davbadfrag.patch
deleted file mode 100644 (file)
index 5d2904b..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
---- httpd-2.0.46/modules/dav/main/mod_dav.c.davbadfrag
-+++ httpd-2.0.46/modules/dav/main/mod_dav.c
-@@ -4537,6 +4537,16 @@
-     if (strcmp(r->handler, DAV_HANDLER_NAME) != 0)
-         return DECLINED;
-+    /* Reject requests with an unescaped hash character, as these may
-+     * be more destructive than the user intended. */
-+    if (r->parsed_uri.fragment != NULL) {
-+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-+                     "buggy client used un-escaped hash in Request-URI");
-+        return dav_error_response(r, HTTP_BAD_REQUEST, 
-+                                  "The request was invalid: the URI included "
-+                                  "an un-escaped hash character");
-+    }
-+
-     /* ### do we need to do anything with r->proxyreq ?? */
-     /*
diff --git a/httpd-2.0.46-execfail.patch b/httpd-2.0.46-execfail.patch
deleted file mode 100644 (file)
index ec931d6..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-
-Fix the inability to log errors like exec failure in
-mod_ext_filter/mod_cgi script children (e.g., exec failure).  This
-was broken after such children stopped inheriting the error log
-handle.    -- Jeff Trawick
-
---- httpd-2.0.46/modules/generators/mod_cgi.c.execfail
-+++ httpd-2.0.46/modules/generators/mod_cgi.c
-@@ -122,8 +122,6 @@
- #define DEFAULT_LOGBYTES 10385760
- #define DEFAULT_BUFBYTES 1024
--#define ERRFN_USERDATA_KEY         "CGICHILDERRFN"
--
- typedef struct {
-     const char *logname;
-     long        logbytes;
-@@ -385,13 +383,15 @@
- static void cgi_child_errfn(apr_pool_t *pool, apr_status_t err,
-                             const char *description)
- {
--    request_rec *r;
--    void *vr;
--
--    apr_pool_userdata_get(&vr, ERRFN_USERDATA_KEY, pool);
--    r = vr;
-+    apr_file_t *stderr_log;
-+    char errbuf[200];
--    ap_log_rerror(APLOG_MARK, APLOG_ERR, err, r, "%s", description);
-+    apr_file_open_stderr(&stderr_log, pool);
-+    apr_file_printf(stderr_log,
-+                    "(%d)%s: %s\n",
-+                    err,
-+                    apr_strerror(err, errbuf, sizeof(errbuf)),
-+                    description);
- }
- static apr_status_t run_cgi_child(apr_file_t **script_out,
-@@ -473,8 +473,6 @@
-                       "couldn't set child process attributes: %s", r->filename);
-     }
-     else {
--        apr_pool_userdata_set(r, ERRFN_USERDATA_KEY, apr_pool_cleanup_null, p);
--
-         procnew = apr_pcalloc(p, sizeof(*procnew));
-         if (e_info->prog_type == RUN_AS_SSI) {
-             SPLIT_AND_PASS_PRETAG_BUCKETS(*(e_info->bb), e_info->ctx,
diff --git a/httpd-2.0.46-graceful.patch b/httpd-2.0.46-graceful.patch
deleted file mode 100644 (file)
index dc4b6e8..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-
-https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=105725
-
-The number of connections to make to the POD on a graceful restart
-should be equal to the number of children which have ever been
-started; not the number of children there *could* be.
-
-Otherwise the parent is bound to get connect() timeouts. 
-
---- httpd-2.0.46/server/mpm/prefork/prefork.c.graceful
-+++ httpd-2.0.46/server/mpm/prefork/prefork.c
-@@ -1167,7 +1167,7 @@
-                   "Graceful restart requested, doing restart");
-       /* kill off the idle ones */
--        ap_mpm_pod_killpg(pod, ap_daemons_limit);
-+        ap_mpm_pod_killpg(pod, ap_max_daemons_limit);
-       /* This is mostly for debugging... so that we know what is still
-           * gracefully dealing with existing request.  This will break
diff --git a/httpd-2.0.46-logtimez.patch b/httpd-2.0.46-logtimez.patch
deleted file mode 100644 (file)
index 19efa77..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-
-  * modules/loggers/mod_log_config.c (log_request_time): Log
-  the minutes component of the timezone correctly.
-                                                                                                  
-  PR: 23642
-  Submitted by: Hong-Gunn Chew <hgbug@gunnet.org>
-
---- httpd-2.0.46/modules/loggers/mod_log_config.c.logtimez
-+++ httpd-2.0.46/modules/loggers/mod_log_config.c
-@@ -570,7 +570,7 @@
-                          "[%02d/%s/%d:%02d:%02d:%02d %c%.2d%.2d]",
-                          xt.tm_mday, apr_month_snames[xt.tm_mon],
-                          xt.tm_year+1900, xt.tm_hour, xt.tm_min, xt.tm_sec,
--                         sign, timz / (60*60), timz % (60*60));
-+                         sign, timz / (60*60), (timz % (60*60)) / 60);
-             cached_time->t_validate = t_seconds;
-             memcpy(&(request_time_cache[i]), cached_time,
-                    sizeof(*cached_time));
diff --git a/httpd-2.0.46-metharray.patch b/httpd-2.0.46-metharray.patch
deleted file mode 100644 (file)
index be2359b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-
-Build array of allowed methods with proper dimensions, fixing
-possible memory corruption.  [Jeff Trawick]
-
---- httpd-2.0.46/modules/http/http_protocol.c.metharray
-+++ httpd-2.0.46/modules/http/http_protocol.c
-@@ -2436,7 +2436,7 @@
-     ml = (ap_method_list_t *) apr_palloc(p, sizeof(ap_method_list_t));
-     ml->method_mask = 0;
--    ml->method_list = apr_array_make(p, sizeof(char *), nelts);
-+    ml->method_list = apr_array_make(p, nelts, sizeof(char *));
-     return ml;
- }
diff --git a/httpd-2.0.46-sslerr.patch b/httpd-2.0.46-sslerr.patch
deleted file mode 100644 (file)
index c4ec7b4..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-
-Fix to use load human-readable error strings and to use
-thread-safe error retrieval interface.
-
---- httpd-2.0.46/modules/ssl/ssl_engine_log.c.sslerr
-+++ httpd-2.0.46/modules/ssl/ssl_engine_log.c
-@@ -118,8 +118,8 @@
-     unsigned long e;
-     while ((e = ERR_get_error())) {
--        char *err, *annotation;
--        err = ERR_error_string(e, NULL);
-+        char err[256], *annotation;
-+        ERR_error_string_n(e, err, sizeof err);
-         annotation = ssl_log_annotation(err);
-         if (annotation) {
---- httpd-2.0.46/modules/ssl/ssl_engine_init.c.sslerr
-+++ httpd-2.0.46/modules/ssl/ssl_engine_init.c
-@@ -1260,7 +1260,6 @@
-     /*
-      * Try to kill the internals of the SSL library.
-      */
--    ERR_free_strings();
-     ERR_remove_state(0);
-     EVP_cleanup();
diff --git a/httpd-2.0.46-sslio.patch b/httpd-2.0.46-sslio.patch
deleted file mode 100644 (file)
index c2c224b..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-
-Fix false negatives on plain-HTTP-not-SSL error (Steve Henson).
-
-Fix streaming of nph- CGI scripts over SSL.
-
---- httpd-2.0.48/modules/ssl/ssl_engine_io.c.sslio
-+++ httpd-2.0.48/modules/ssl/ssl_engine_io.c
-@@ -1091,7 +1091,8 @@
-             outctx->rc = APR_EAGAIN;
-             return SSL_ERROR_WANT_READ;
-         }
--        else if (ERR_GET_REASON(ERR_peek_error()) == SSL_R_HTTP_REQUEST) {
-+        else if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_SSL &&
-+                 ERR_GET_REASON(ERR_peek_error()) == SSL_R_HTTP_REQUEST) {
-             /*
-              * The case where OpenSSL has recognized a HTTP request:
-              * This means the client speaks plain HTTP on our HTTPS port.
-@@ -1281,6 +1282,8 @@
-     apr_status_t status = APR_SUCCESS;
-     ssl_filter_ctx_t *filter_ctx = f->ctx;
-     bio_filter_in_ctx_t *inctx;
-+    bio_filter_out_ctx_t *outctx;
-+    apr_read_type_e rblock = APR_NONBLOCK_READ;
-     if (f->c->aborted) {
-         apr_brigade_cleanup(bb);
-@@ -1293,6 +1296,8 @@
-     }
-     inctx = (bio_filter_in_ctx_t *)filter_ctx->pbioRead->ptr;
-+    outctx = (bio_filter_out_ctx_t *)filter_ctx->pbioWrite->ptr;
-+
-     /* When we are the writer, we must initialize the inctx
-      * mode so that we block for any required ssl input, because
-      * output filtering is always nonblocking.
-@@ -1312,8 +1317,6 @@
-          */
-         if (APR_BUCKET_IS_EOS(bucket) || APR_BUCKET_IS_FLUSH(bucket)) {
-             if (bio_filter_out_flush(filter_ctx->pbioWrite) < 0) {
--                bio_filter_out_ctx_t *outctx = 
--                       (bio_filter_out_ctx_t *)(filter_ctx->pbioWrite->ptr);
-                 status = outctx->rc;
-                 break;
-             }
-@@ -1343,7 +1346,18 @@
-             const char *data;
-             apr_size_t len;
-             
--            status = apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
-+            status = apr_bucket_read(bucket, &data, &len, rblock);
-+
-+            if (APR_STATUS_IS_EAGAIN(status)) {
-+                /* No data available: flush... */
-+                if (bio_filter_out_flush(filter_ctx->pbioWrite) < 0) {
-+                    status = outctx->rc;
-+                    break;
-+                }
-+                rblock = APR_BLOCK_READ;
-+                continue; /* and try again with a blocking read. */
-+            }
-+            rblock = APR_NONBLOCK_READ;
-             if (!APR_STATUS_IS_EOF(status) && (status != APR_SUCCESS)) {
-                 break;
diff --git a/httpd-2.0.47-ldapshm.patch b/httpd-2.0.47-ldapshm.patch
deleted file mode 100644 (file)
index bc04d11..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-
-Use anonymous shm for ldap cache, though it's still broken.  
-
---- httpd-2.0.47/modules/experimental/util_ldap_cache.c.ldapshm
-+++ httpd-2.0.47/modules/experimental/util_ldap_cache.c
-@@ -295,14 +295,7 @@
- #if APR_HAS_SHARED_MEMORY
-     apr_status_t result;
--    result = apr_shm_create(&util_ldap_shm, reqsize, MODLDAP_SHMEM_CACHE, pool);
--    if (result == EEXIST) {
--        /*
--         * The cache could have already been created (i.e. we may be a child process).  See
--         * if we can attach to the existing shared memory
--         */
--        result = apr_shm_attach(&util_ldap_shm, MODLDAP_SHMEM_CACHE, pool);
--    } 
-+    result = apr_shm_create(&util_ldap_shm, reqsize, NULL, pool);
-     if (result != APR_SUCCESS) {
-         return result;
-     }
diff --git a/httpd-2.0.48-CAN-2003-0020.patch b/httpd-2.0.48-CAN-2003-0020.patch
deleted file mode 100644 (file)
index e782593..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
- *) SECURITY [CAN-2003-0020]: Escape arbitrary data before writing
-    into the errorlog.  [André Malo]
-
---- httpd-2.0.48/server/log.c.can0020  2003-06-23 14:03:59.000000000 +0100
-+++ httpd-2.0.48/server/log.c  2004-01-19 14:14:42.000000000 +0000
-@@ -401,7 +401,7 @@
-                            const request_rec *r, apr_pool_t *pool,
-                            const char *fmt, va_list args)
- {
--    char errstr[MAX_STRING_LEN];
-+    char errstr[MAX_STRING_LEN], scratch[MAX_STRING_LEN];
-     apr_size_t len, errstrlen;
-     apr_file_t *logf = NULL;
-     const char *referer;
-@@ -536,12 +536,17 @@
-             errstr[len] = '\0';
-         }
-     }
-+
-     errstrlen = len;
--    len += apr_vsnprintf(errstr + len, MAX_STRING_LEN - len, fmt, args);
-+    if (apr_vsnprintf(scratch, MAX_STRING_LEN - len, fmt, args)) {
-+        len += ap_escape_errorlog_item(errstr + len, scratch,
-+                                       MAX_STRING_LEN - len);
-+    }
--    if (r && (referer = apr_table_get(r->headers_in, "Referer"))) {
-+    if (   r && (referer = apr_table_get(r->headers_in, "Referer"))
-+        && ap_escape_errorlog_item(scratch, referer, MAX_STRING_LEN - len)) {
-         len += apr_snprintf(errstr + len, MAX_STRING_LEN - len,
--                            ", referer: %s", referer);
-+                            ", referer: %s", scratch);
-     }
-     /* NULL if we are logging to syslog */
---- httpd-2.0.48/server/util.c.can0020 2003-06-17 18:39:10.000000000 +0100
-+++ httpd-2.0.48/server/util.c 2004-01-19 14:14:42.000000000 +0000
-@@ -1837,6 +1837,70 @@
-     return ret;
- }
-+AP_DECLARE(apr_size_t) ap_escape_errorlog_item(char *dest, const char *source,
-+                                               apr_size_t buflen)
-+{
-+    unsigned char *d, *ep;
-+    const unsigned char *s;
-+
-+    if (!source || !buflen) { /* be safe */
-+        return 0;
-+    }
-+
-+    d = (unsigned char *)dest;
-+    s = (const unsigned char *)source;
-+    ep = d + buflen - 1;
-+
-+    for (; d < ep && *s; ++s) {
-+
-+        if (TEST_CHAR(*s, T_ESCAPE_LOGITEM)) {
-+            *d++ = '\\';
-+            if (d >= ep) {
-+                --d;
-+                break;
-+            }
-+
-+            switch(*s) {
-+            case '\b':
-+                *d++ = 'b';
-+                break;
-+            case '\n':
-+                *d++ = 'n';
-+                break;
-+            case '\r':
-+                *d++ = 'r';
-+                break;
-+            case '\t':
-+                *d++ = 't';
-+                break;
-+            case '\v':
-+                *d++ = 'v';
-+                break;
-+            case '\\':
-+                *d++ = *s;
-+                break;
-+            case '"': /* no need for this in error log */
-+                d[-1] = *s;
-+                break;
-+            default:
-+                if (d >= ep - 2) {
-+                    ep = --d; /* break the for loop as well */
-+                    break;
-+                }
-+                c2x(*s, d);
-+                *d = 'x';
-+                d += 3;
-+            }
-+        }
-+        else {
-+            *d++ = *s;
-+        }
-+    }
-+    *d = '\0';
-+
-+    return (d - (unsigned char *)dest);
-+}
-+
- AP_DECLARE(int) ap_is_directory(apr_pool_t *p, const char *path)
- {
-     apr_finfo_t finfo;
---- httpd-2.0.48/include/ap_mmn.h.can0020      2003-07-07 01:45:23.000000000 +0100
-+++ httpd-2.0.48/include/ap_mmn.h      2004-01-19 14:14:42.000000000 +0000
-@@ -114,6 +114,7 @@
-  * 20020903.2 (2.0.46-dev) add ap_escape_logitem
-  * 20020903.3 (2.0.46-dev) allow_encoded_slashes added to core_dir_config
-  * 20020903.4 (2.0.47-dev) add ap_is_recursion_limit_exceeded()
-+ * 20020903.5 (2.0.49-dev) add ap_escape_errorlog_item()
-  */
- #define MODULE_MAGIC_COOKIE 0x41503230UL /* "AP20" */
-@@ -121,7 +122,7 @@
- #ifndef MODULE_MAGIC_NUMBER_MAJOR
- #define MODULE_MAGIC_NUMBER_MAJOR 20020903
- #endif
--#define MODULE_MAGIC_NUMBER_MINOR 4                     /* 0...n */
-+#define MODULE_MAGIC_NUMBER_MINOR 5                     /* 0...n */
- /**
-  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
---- httpd-2.0.48/include/httpd.h.can0020       2004-01-19 14:14:41.000000000 +0000
-+++ httpd-2.0.48/include/httpd.h       2004-01-19 14:14:42.000000000 +0000
-@@ -1370,12 +1370,22 @@
- /**
-  * Escape a string for logging
-  * @param p The pool to allocate from
-- * @param s The string to escape
-+ * @param str The string to escape
-  * @return The escaped string
-  */
- AP_DECLARE(char *) ap_escape_logitem(apr_pool_t *p, const char *str);
- /**
-+ * Escape a string for logging into the error log (without a pool)
-+ * @param dest The buffer to write to
-+ * @param source The string to escape
-+ * @param buflen The buffer size for the escaped string (including \0)
-+ * @return The len of the escaped string (always < maxlen)
-+ */
-+AP_DECLARE(apr_size_t) ap_escape_errorlog_item(char *dest, const char *source,
-+                                               apr_size_t buflen);
-+
-+/**
-  * Construct a full hostname
-  * @param p The pool to allocate from
-  * @param hostname The hostname of the server
diff --git a/httpd-2.0.48-abench.patch b/httpd-2.0.48-abench.patch
deleted file mode 100644 (file)
index 57ad768..0000000
+++ /dev/null
@@ -1,339 +0,0 @@
-
-Update to HEAD's ab which seems to be slightly less utterly borked
-than 2.0's.
-
---- httpd-2.0.48/support/ab.c.abench
-+++ httpd-2.0.48/support/ab.c
-@@ -1,7 +1,7 @@
- /* ====================================================================
-  * The Apache Software License, Version 1.1
-  *
-- * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights
-+ * Copyright (c) 2000-2004 The Apache Software Foundation.  All rights
-  * reserved.
-  *
-  * Redistribution and use in source and binary forms, with or without
-@@ -103,9 +103,9 @@
-    ** Version 2.0.36-dev
-    **    Improvements to concurrent processing:
-    **      - Enabled non-blocking connect()s.
--   **      - Prevent blocking calls to apr_recv() (thereby allowing AB to
-+   **      - Prevent blocking calls to apr_socket_recv() (thereby allowing AB to
-    **        manage its entire set of socket descriptors).
--   **      - Any error returned from apr_recv() that is not EAGAIN or EOF
-+   **      - Any error returned from apr_socket_recv() that is not EAGAIN or EOF
-    **        is now treated as fatal.
-    **      Contributed by Aaron Bannert, April 24, 2002
-    **
-@@ -185,9 +185,30 @@
- #endif
- #if APR_HAVE_STDLIB_H
- #include <stdlib.h>
-+#endif
-+#if APR_HAVE_UNISTD_H
-+#include <unistd.h> /* for getpid() */
-+#endif
-+
-+#if !defined(WIN32) && !defined(NETWARE)
-+#include "ap_config_auto.h"
-+#endif
-+
-+#if defined(HAVE_SSLC)
-+
-+/* Libraries for RSA SSL-C */
-+#include <rsa.h>
-+#include <x509.h>
-+#include <pem.h>
-+#include <err.h>
-+#include <ssl.h>
-+#include <r_rand.h>
-+#include <sslc.h>
-+#define USE_SSL
-+#define RSAREF
-+
-+#elif defined(HAVE_OPENSSL)
--#ifdef        USE_SSL
--#if ((!(RSAREF)) && (!(SYSSSL)))
- /* Libraries on most systems.. */
- #include <openssl/rsa.h>
- #include <openssl/crypto.h>
-@@ -196,20 +217,11 @@
- #include <openssl/err.h>
- #include <openssl/ssl.h>
- #include <openssl/rand.h>
--#else
--/* Libraries for RSAref and SYSSSL */
--#include <rsa.h>
--#include <crypto.h>
--#include <x509.h>
--#include <pem.h>
--#include <err.h>
--#include <ssl.h>
--#include <rand.h>
--#endif
-+#define USE_SSL
-+
- #endif
- #include <math.h>
--#endif
- #if APR_HAVE_CTYPE_H
- #include <ctype.h>
- #endif
-@@ -227,8 +239,11 @@
- /* good old state hostname */
- #define STATE_UNCONNECTED 0
--#define STATE_CONNECTING  1
--#define STATE_READ        2
-+#define STATE_CONNECTING  1     /* TCP connect initiated, but we don't
-+                                 * know if it worked yet
-+                                 */
-+#define STATE_CONNECTED   2     /* we know TCP connect completed */
-+#define STATE_READ        3
- #define CBUFFSIZE (2048)
-@@ -463,7 +478,7 @@
-  *
-  */
- #ifdef USE_SSL
--long ssl_print_cb(BIO *bio,int cmd,const char *argp,int argi,long argl,long ret)
-+static long ssl_print_cb(BIO *bio,int cmd,const char *argp,int argi,long argl,long ret)
- {
-     BIO *out;
-@@ -505,7 +520,7 @@
-     return i;
- }
--void ssl_rand_seed()
-+static void ssl_rand_seed(void)
- {
-     int nDone = 0;
-     int n, l;
-@@ -537,9 +552,7 @@
-     nDone += 128;
- }
--int ssl_print_connection_info(bio,ssl)
--BIO *bio;
--SSL *ssl;
-+static int ssl_print_connection_info(BIO *bio, SSL *ssl)
- {
-         SSL_CIPHER *c;
-         int alg_bits,bits;
-@@ -554,9 +567,7 @@
-         return(1);
- }
--int ssl_print_cert_info(bio,x509cert)
--BIO *bio;
--X509 *x509cert;
-+static int ssl_print_cert_info(BIO *bio, X509 *x509cert)
- {
-         X509_NAME *dn;
-         char buf[64];
-@@ -588,7 +599,7 @@
-         return(1);
- }
--void ssl_start_connect(struct connection * c)
-+static void ssl_start_connect(struct connection * c)
- {
-     BIO *bio;
-     X509 *x509cert;
-@@ -668,7 +679,7 @@
-             case SSL_ERROR_WANT_CONNECT:
-                 BIO_printf(bio_err, "Waiting .. sleep(1)\n");
-                 apr_sleep(apr_time_from_sec(1));
--                c->state = STATE_CONNECTING;
-+                c->state = STATE_CONNECTED;
-                 c->rwrite = 0;
-                 break;
-             case SSL_ERROR_ZERO_RETURN:
-@@ -724,7 +735,7 @@
-     do {
-       apr_time_t tnow = apr_time_now();
-       apr_size_t l = c->rwrite;
--      apr_status_t e;
-+      apr_status_t e = APR_SUCCESS; /* prevent gcc warning */
-       /*
-        * First time round ?
-@@ -760,7 +771,7 @@
-         }
-         else
- #endif
--      e = apr_send(c->aprsock, request + c->rwrote, &l);
-+      e = apr_socket_send(c->aprsock, request + c->rwrote, &l);
-       /*
-        * Bail early on the most common case
-@@ -770,6 +781,7 @@
- #ifdef USE_SSL
-         if (ssl != 1)
-+#endif
-       if (e != APR_SUCCESS) {
-           /*
-            * Let's hope this traps EWOULDBLOCK too !
-@@ -781,7 +793,6 @@
-           }
-           return;
-       }
--#endif
-       c->rwrote += l;
-       c->rwrite -= l;
-     } while (1);
-@@ -1250,13 +1261,13 @@
-         apr_err("socket nonblock", rv);
-     }
-     c->start = apr_time_now();
--    if ((rv = apr_connect(c->aprsock, destsa)) != APR_SUCCESS) {
-+    if ((rv = apr_socket_connect(c->aprsock, destsa)) != APR_SUCCESS) {
-       if (APR_STATUS_IS_EINPROGRESS(rv)) {
-             apr_pollfd_t new_pollfd;
-           c->state = STATE_CONNECTING;
-           c->rwrite = 0;
-             new_pollfd.desc_type = APR_POLL_SOCKET;
--            new_pollfd.reqevents = APR_POLLOUT | APR_POLLIN;
-+            new_pollfd.reqevents = APR_POLLOUT;
-             new_pollfd.desc.s = c->aprsock;
-             new_pollfd.client_data = c;
-           apr_pollset_add(readbits, &new_pollfd);
-@@ -1272,7 +1283,7 @@
-           if (bad++ > 10) {
-               fprintf(stderr,
-                       "\nTest aborted after 10 failures\n\n");
--              apr_err("apr_connect()", rv);
-+              apr_err("apr_socket_connect()", rv);
-           }
-           c->state = STATE_UNCONNECTED;
-           start_connect(c);
-@@ -1281,6 +1292,7 @@
-     }
-     /* connected first time */
-+    c->state = STATE_CONNECTED;
-     started++;
-     write_request(c);
- }
-@@ -1371,7 +1383,7 @@
-     }
-     else {
- #endif
--    status = apr_recv(c->aprsock, buffer, &r);
-+    status = apr_socket_recv(c->aprsock, buffer, &r);
-     if (APR_STATUS_IS_EAGAIN(status))
-       return;
-     else if (r == 0 && APR_STATUS_IS_EOF(status)) {
-@@ -1379,12 +1391,12 @@
-       close_connection(c);
-       return;
-     }
--    /* catch legitimate fatal apr_recv errors */
-+    /* catch legitimate fatal apr_socket_recv errors */
-     else if (status != APR_SUCCESS) {
-         err_except++; /* XXX: is this the right error counter? */
-         /* XXX: Should errors here be fatal, or should we allow a
-          * certain number of them before completely failing? -aaron */
--        apr_err("apr_recv", status);
-+        apr_err("apr_socket_recv", status);
-     }
- #ifdef USE_SSL
-     }
-@@ -1633,7 +1645,11 @@
-      * Combine headers and (optional) post file into one contineous buffer
-      */
-     if (posting == 1) {
--      char *buff = (char *) malloc(postlen + reqlen + 1);
-+      char *buff = malloc(postlen + reqlen + 1);
-+        if (!buff) {
-+            fprintf(stderr, "error creating request buffer: out of memory\n");
-+            return;
-+        }
-       strcpy(buff, request);
-       strcpy(buff + reqlen, postdata);
-       request = buff;
-@@ -1700,7 +1716,14 @@
-       for (i = 0; i < n; i++) {
-             const apr_pollfd_t *next_fd = &(pollresults[i]);
--            struct connection *c = next_fd->client_data;
-+            struct connection *c;
-+            
-+#ifdef USE_SSL
-+            if (ssl) 
-+                c = &con[i];
-+            else
-+#endif
-+                c = next_fd->client_data;
-           /*
-            * If the connection isn't connected how can we check it?
-@@ -1735,8 +1758,34 @@
-               start_connect(c);
-               continue;
-           }
--          if (rv & APR_POLLOUT)
--              write_request(c);
-+          if (rv & APR_POLLOUT) {
-+                if (c->state == STATE_CONNECTING) {
-+                    apr_pollfd_t remove_pollfd;
-+                    rv = apr_socket_connect(c->aprsock, destsa);
-+                    remove_pollfd.desc_type = APR_POLL_SOCKET;
-+                    remove_pollfd.desc.s = c->aprsock;
-+                    apr_pollset_remove(readbits, &remove_pollfd);
-+                    if (rv != APR_SUCCESS) {
-+                        apr_socket_close(c->aprsock);
-+                        err_conn++;
-+                        if (bad++ > 10) {
-+                            fprintf(stderr,
-+                                    "\nTest aborted after 10 failures\n\n");
-+                            apr_err("apr_socket_connect()", rv);
-+                        }
-+                        c->state = STATE_UNCONNECTED;
-+                        start_connect(c);
-+                        continue;
-+                    }
-+                    else {
-+                        c->state = STATE_CONNECTED;
-+                        write_request(c);
-+                    }
-+                }
-+                else {
-+                    write_request(c);
-+                }
-+            }
-           /*
-            * When using a select based poll every time we check the bits
-@@ -1748,8 +1797,7 @@
- #ifdef USE_SSL
-             if (ssl != 1)
- #endif
--          if (c->state == STATE_READ ||
--                c->state == STATE_CONNECTING) {
-+                if (c->state == STATE_READ) {
-                     apr_pollfd_t new_pollfd;
-                     new_pollfd.desc_type = APR_POLL_SOCKET;
-                     new_pollfd.reqevents = APR_POLLIN;
-@@ -1777,14 +1825,14 @@
- static void copyright(void)
- {
-     if (!use_html) {
--      printf("This is ApacheBench, Version %s\n", AP_AB_BASEREVISION " <$Revision$> apache-2.0");
-+      printf("This is ApacheBench, Version %s\n", AP_AB_BASEREVISION " <$Revision$> apache-2.0");
-       printf("Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/\n");
-       printf("Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/\n");
-       printf("\n");
-     }
-     else {
-       printf("<p>\n");
--      printf(" This is ApacheBench, Version %s <i>&lt;%s&gt;</i> apache-2.0<br>\n", AP_AB_BASEREVISION, "$Revision$");
-+      printf(" This is ApacheBench, Version %s <i>&lt;%s&gt;</i> apache-2.0<br>\n", AP_AB_BASEREVISION, "$Revision$");
-       printf(" Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/<br>\n");
-       printf(" Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/<br>\n");
-       printf("</p>\n<p>\n");
diff --git a/httpd-2.0.48-autoindex.patch b/httpd-2.0.48-autoindex.patch
deleted file mode 100644 (file)
index e50faf2..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
---- httpd-2.0.48/modules/generators/mod_autoindex.c.autoindex
-+++ httpd-2.0.48/modules/generators/mod_autoindex.c
-@@ -1329,14 +1329,6 @@
-         return (NULL);
-     }
--    if (rr->finfo.filetype == APR_DIR) {
--        /* ap_sub_req_lookup_dirent() adds '/' to end of any directory,
--         * but that messes up our attempt to find relevant
--         * AddDescription directives.
--         */
--        rr->filename[strlen(rr->filename) - 1] = '\0';
--    }
--
-     p = (struct ent *) apr_pcalloc(r->pool, sizeof(struct ent));
-     if (dirent->filetype == APR_DIR) {
-         p->name = apr_pstrcat(r->pool, dirent->name, "/", NULL);
-@@ -1362,6 +1354,10 @@
-                 p->isdir = 1;
-             }
-             rr->filename = ap_make_dirstr_parent (rr->pool, rr->filename);
-+
-+            /* omit the trailing slash (1.3 compat) */
-+            rr->filename[strlen(rr->filename) - 1] = '\0';
-+
-             if (!(p->icon = find_icon(d, rr, 1))) {
-                 p->icon = find_default_icon(d, "^^DIRECTORY^^");
-             }
-@@ -1650,8 +1646,9 @@
-         }
-         if (autoindex_opts & TABLE_INDEXING) {
-+            ap_rputs("<tr>", r);
-             if (!(autoindex_opts & SUPPRESS_ICON)) {
--                ap_rputs("<tr><td valign=\"top\">", r);
-+                ap_rputs("<td valign=\"top\">", r);
-                 if (autoindex_opts & ICONS_ARE_LINKS) {
-                     ap_rvputs(r, "<a href=\"", anchor, "\">", NULL);
-                 }
diff --git a/httpd-2.0.48-include.patch b/httpd-2.0.48-include.patch
deleted file mode 100644 (file)
index 44894e7..0000000
+++ /dev/null
@@ -1,2256 +0,0 @@
-*) Backport major overhaul of mod_include's filter parser from 2.1.
-    The new parser code is expected to be more robust and should
-    catch all of the edge cases that were not handled by the previous one.
-    The 2.1 external API changes were hidden by a wrapper which is
-    expected to keep the API backwards compatible.  [André Malo]
-
---- httpd-2.0.48/modules/filters/mod_include.h.include
-+++ httpd-2.0.48/modules/filters/mod_include.h
-@@ -131,7 +131,17 @@
-  * ssi_tag_brigade: The temporary brigade used by this filter to set aside
-  *                  the buckets containing parts of the ssi tag and headers.
-  */
--typedef enum {PRE_HEAD, PARSE_HEAD, PARSE_DIRECTIVE, PARSE_TAG, PARSE_TAIL, PARSED} states;
-+
-+/* I keep this stuff here, because of binary compat. It probably doesn't care,
-+ * but who knows ...?
-+ */
-+#ifdef MOD_INCLUDE_REDESIGN
-+typedef enum {PRE_HEAD, BLOW_PARSE_HEAD, BLOW_PARSE_DIRECTIVE, PARSE_TAG,
-+              BLOW_PARSE_TAIL, PARSED} states;
-+#else
-+typedef enum {PRE_HEAD, PARSE_HEAD, PARSE_DIRECTIVE, PARSE_TAG, PARSE_TAIL,
-+              PARSED} states;
-+#endif
- /** forward referenced as it needs to be held on the context */
- typedef struct bndm_t bndm_t;
---- httpd-2.0.48/modules/filters/mod_include.c.include
-+++ httpd-2.0.48/modules/filters/mod_include.c
-@@ -1,7 +1,7 @@
- /* ====================================================================
-  * The Apache Software License, Version 1.1
-  *
-- * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights
-+ * Copyright (c) 2000-2004 The Apache Software Foundation.  All rights
-  * reserved.
-  *
-  * Redistribution and use in source and binary forms, with or without
-@@ -73,6 +73,7 @@
- #include "apr_optional.h"
- #define APR_WANT_STRFUNC
-+#define APR_WANT_MEMFUNC
- #include "apr_want.h"
- #define CORE_PRIVATE
-@@ -89,6 +90,8 @@
- #include "http_main.h"
- #include "util_script.h"
- #include "http_core.h"
-+
-+#define MOD_INCLUDE_REDESIGN
- #include "mod_include.h"
- #include "util_ebcdic.h"
-@@ -126,6 +129,58 @@
-     int  undefinedEchoLen;
- } include_server_config;
-+/* main parser states */
-+typedef enum {
-+    PARSE_PRE_HEAD,
-+    PARSE_HEAD,
-+    PARSE_DIRECTIVE,
-+    PARSE_DIRECTIVE_POSTNAME,
-+    PARSE_DIRECTIVE_TAIL,
-+    PARSE_DIRECTIVE_POSTTAIL,
-+    PARSE_PRE_ARG,
-+    PARSE_ARG,
-+    PARSE_ARG_NAME,
-+    PARSE_ARG_POSTNAME,
-+    PARSE_ARG_EQ,
-+    PARSE_ARG_PREVAL,
-+    PARSE_ARG_VAL,
-+    PARSE_ARG_VAL_ESC,
-+    PARSE_ARG_POSTVAL,
-+    PARSE_TAIL,
-+    PARSE_TAIL_SEQ,
-+    PARSE_EXECUTE
-+} parse_state_t;
-+
-+typedef struct ssi_arg_item {
-+    struct ssi_arg_item *next;
-+    char                *name;
-+    apr_size_t           name_len;
-+    char                *value;
-+    apr_size_t           value_len;
-+} ssi_arg_item_t;
-+
-+typedef struct {
-+    parse_state_t state;
-+    int           seen_eos;
-+    int           error;
-+    char          quote;         /* quote character value (or \0) */
-+
-+    apr_bucket_brigade *tmp_bb;
-+
-+    apr_size_t    end_seq_len;
-+    char         *directive;     /* name of the current directive */
-+
-+    unsigned        argc;        /* argument counter (of the current
-+                                  * directive)
-+                                  */
-+    ssi_arg_item_t *argv;        /* all arguments */
-+    ssi_arg_item_t *current_arg; /* currently parsed argument */
-+    request_rec    *r;
-+    include_ctx_t  *ctx;         /* public part of the context structure */
-+
-+    apr_pool_t     *dpool;
-+} ssi_ctx_t;
-+
- #ifdef XBITHACK
- #define DEFAULT_XBITHACK xbithack_full
- #else
-@@ -134,6 +189,11 @@
- #define BYTE_COUNT_THRESHOLD AP_MIN_BYTES_TO_WRITE
-+#define SSI_CREATE_ERROR_BUCKET(ctx, f, bb) APR_BRIGADE_INSERT_TAIL((bb),   \
-+    apr_bucket_pool_create(apr_pstrdup((ctx)->pool, (ctx)->error_str),  \
-+                           strlen((ctx)->error_str), (ctx)->pool,       \
-+                           (f)->c->bucket_alloc))
-+
- /* ------------------------ Environment function -------------------------- */
- /* Sentinel value to store in subprocess_env for items that
-@@ -316,463 +376,6 @@
-     return hl;
- }
--/* 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);
--}
--
- /*
-  * decodes a string containing html entities or numeric character references.
-  * 's' is overwritten with the decoded string.
-@@ -890,106 +493,34 @@
- 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) {
-+    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++;
-+    *tag = ctx->curr_tag_pos;
-+    if (!**tag) {
-+        *tag = NULL;
-+        /* finitio */
-+        ctx->curr_tag_pos = ctx->combined_tag + ctx->tag_length;
-+        return;
-     }
--    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. */
--        }
-+    *tag_val = ap_strchr(*tag, '=');
-+    if (!*tag_val) {
-+        ctx->curr_tag_pos = ctx->combined_tag + ctx->tag_length;
-+        return;
-     }
--    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++;
--        }
-+    /* if it starts with '=' there was no tag name, just a value */
-+    if (*tag_val == *tag) {
-+        *tag = NULL;
-     }
--    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;
-+    *(*tag_val)++ = '\0';
-+    ctx->curr_tag_pos = *tag_val + strlen(*tag_val) + 1; /* skip \0 byte */
-+
-     if (dodecode) {
-         decodehtml(*tag_val);
-     }
-@@ -1354,6 +885,7 @@
-                             "unknown parameter \"%s\" to tag include in %s",
-                             tag, r->filename);
-                 CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
-+                return 1;
-             }
-         }
-     }
-@@ -1432,6 +964,7 @@
-                            "tag echo in %s", tag_val, r->filename);
-                     CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, 
-                                         *inserted_head);
-+                    return 1;
-                 }
-             }
-             else {
-@@ -1439,6 +972,7 @@
-                             "unknown parameter \"%s\" in tag echo of %s",
-                             tag, r->filename);
-                 CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
-+                return 1;
-             }
-         }
-@@ -1514,6 +1048,7 @@
-                               "unknown parameter \"%s\" to tag config in %s",
-                               tag, r->filename);
-                 CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
-+                return 1;
-             }
-         }
-     }
-@@ -1663,6 +1198,7 @@
-                 else {
-                     CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, 
-                                         *inserted_head);
-+                    return 1;
-                 }
-             }
-         }
-@@ -1712,6 +1248,7 @@
-                 else {
-                     CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, 
-                                         *inserted_head);
-+                    return 1;
-                 }
-             }
-         }
-@@ -2642,6 +2179,7 @@
-                             "unknown parameter \"%s\" to tag if in %s", tag, 
-                             r->filename);
-                 CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
-+                return 1;
-             }
-         }
-@@ -2678,7 +2216,7 @@
-                                   r->filename);
-                     CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, 
-                                         *inserted_head);
--                    return (1);
-+                    return 1;
-                 }
-                 expr_ret = parse_expr(r, ctx, expr, &was_error, 
-                                       &was_unmatched, debug_buf);
-@@ -2725,6 +2263,7 @@
-                                "unknown parameter \"%s\" to tag if in %s", tag, 
-                                r->filename);
-                 CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
-+                return 1;
-             }
-         }
-     }
-@@ -2914,362 +2453,1032 @@
- /* -------------------------- The main function --------------------------- */
--static apr_status_t send_parsed_content(apr_bucket_brigade **bb, 
--                                        request_rec *r, ap_filter_t *f)
-+/*
-+ * returns the index position of the first byte of start_seq (or the len of
-+ * the buffer as non-match)
-+ */
-+static apr_size_t find_start_sequence(ssi_ctx_t *ctx, const char *data,
-+                                      apr_size_t len)
- {
--    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_size_t slen = ctx->ctx->start_seq_len;
-+    apr_size_t index;
-+    const char *p, *ep;
--        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));
-+    if (len < slen) {
-+        p = data; /* try partial match at the end of the buffer (below) */
-     }
-+    else {
-+        /* try fast bndm search over the buffer
-+         * (hopefully the whole start sequence can be found in this buffer)
-+         */
-+        index = bndm(ctx->ctx->start_seq, ctx->ctx->start_seq_len, data, len,
-+                     ctx->ctx->start_seq_pat);
--    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.
-+        /* wow, found it. ready. */
-+        if (index < len) {
-+            ctx->state = PARSE_DIRECTIVE;
-+            return index;
-+        }
-+        else {
-+            /* ok, the pattern can't be found as whole in the buffer,
-+             * check the end for a partial match
-              */
--            if ((do_cleanup) && (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade))) {
--                apr_bucket *tmp_bkt;
-+            p = data + len - slen + 1;
-+        }
-+    }
--                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);
--            }
-+    ep = data + len;
-+    do {
-+        while (p < ep && *p != *ctx->ctx->start_seq) {
-+            ++p;
-+        }
--            /* 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;
-+        index = p - data;
--                while ((dptr != APR_BRIGADE_SENTINEL(*bb)) && (dptr != stop)) {
--                    apr_bucket *free_bucket = dptr;
-+        /* found a possible start_seq start */
-+        if (p < ep) {
-+            apr_size_t pos = 1;
--                    dptr = APR_BUCKET_NEXT(dptr);
--                    if (!APR_BUCKET_IS_METADATA(free_bucket)) {
--                        apr_bucket_delete(free_bucket);
--                    }
--                }
-+            ++p;
-+            while (p < ep && *p == ctx->ctx->start_seq[pos]) {
-+                ++p;
-+                ++pos;
-             }
--            /* 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);
--                }
-+            /* partial match found. Store the info for the next round */
-+            if (p == ep) {
-+                ctx->state = PARSE_HEAD;
-+                ctx->ctx->parse_pos = pos;
-+                return index;
-             }
--            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);  
--            }
-+        /* we must try all combinations; consider (e.g.) SSIStartTag "--->"
-+         * and a string data of "--.-" and the end of the buffer
-+         */
-+        p = data + index + 1;
-+    } while (p < ep);
-+
-+    /* no match */
-+    return len;
-+}
-+
-+/*
-+ * returns the first byte *after* the partial (or final) match.
-+ *
-+ * If we had to trick with the start_seq start, 'release' returns the
-+ * number of chars of the start_seq which appeared not to be part of a
-+ * full tag and may have to be passed down the filter chain.
-+ */
-+static apr_size_t find_partial_start_sequence(ssi_ctx_t *ctx,
-+                                              const char *data,
-+                                              apr_size_t len,
-+                                              apr_size_t *release)
-+{
-+    apr_size_t pos, spos = 0;
-+    apr_size_t slen = ctx->ctx->start_seq_len;
-+    const char *p, *ep;
-+
-+    pos = ctx->ctx->parse_pos;
-+    ep = data + len;
-+    *release = 0;
-+
-+    do {
-+        p = data;
-+
-+        while (p < ep && pos < slen && *p == ctx->ctx->start_seq[pos]) {
-+            ++p;
-+            ++pos;
-         }
--        /* 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;
--            }
-+        /* full match */
-+        if (pos == slen) {
-+            ctx->state = PARSE_DIRECTIVE;
-+            return (p - data);
-+        }
--            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);  
--            }
-+        /* the whole buffer is a partial match */
-+        if (p == ep) {
-+            ctx->ctx->parse_pos = pos;
-+            return (p - data);
-         }
--        /* 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 **);
-+        /* No match so far, but again:
-+         * We must try all combinations, since the start_seq is a random
-+         * user supplied string
-+         *
-+         * So: look if the first char of start_seq appears somewhere within
-+         * the current partial match. If it does, try to start a match that
-+         * begins with this offset. (This can happen, if a strange
-+         * start_seq like "---->" spans buffers)
-+         */
-+        if (spos < ctx->ctx->parse_pos) {
-+            do {
-+                ++spos;
-+                ++*release;
-+                p = ctx->ctx->start_seq + spos;
-+                pos = ctx->ctx->parse_pos - spos;
-+
-+                while (pos && *p != *ctx->ctx->start_seq) {
-+                    ++p;
-+                    ++spos;
-+                    ++*release;
-+                    --pos;
-+                }
--            /* 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.
--             */
-+                /* if a matching beginning char was found, try to match the
-+                 * remainder of the old buffer.
-+                 */
-+                if (pos > 1) {
-+                    apr_size_t t = 1;
--            /* 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);
-+                    ++p;
-+                    while (t < pos && *p == ctx->ctx->start_seq[t]) {
-+                        ++p;
-+                        ++t;
-+                    }
--                /* 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)));
-+                    if (t == pos) {
-+                        /* yeah, another partial match found in the *old*
-+                         * buffer, now test the *current* buffer for
-+                         * continuing match
-+                         */
-+                        break;
-+                    }
-                 }
-+            } while (pos > 1);
--                return APR_SUCCESS;
-+            if (pos) {
-+                continue;
-             }
-+        }
--            /* 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!
--             */
-+        break;
-+    } while (1); /* work hard to find a match ;-) */
--            /* 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.
-+    /* no match at all, release all (wrongly) matched chars so far */
-+    *release = ctx->ctx->parse_pos;
-+    ctx->state = PARSE_PRE_HEAD;
-+    return 0;
-+}
-+
-+/*
-+ * returns the position after the directive
-+ */
-+static apr_size_t find_directive(ssi_ctx_t *ctx, const char *data,
-+                                 apr_size_t len, char ***store,
-+                                 apr_size_t **store_len)
-+{
-+    const char *p = data;
-+    const char *ep = data + len;
-+    apr_size_t pos;
-+
-+    switch (ctx->state) {
-+    case PARSE_DIRECTIVE:
-+        while (p < ep && !apr_isspace(*p)) {
-+            /* we have to consider the case of missing space between directive
-+             * and end_seq (be somewhat lenient), e.g. <!--#printenv-->
-              */
--            if (content_head == NULL) {
--                content_head = dptr;
-+            if (*p == *ctx->ctx->end_seq) {
-+                ctx->state = PARSE_DIRECTIVE_TAIL;
-+                ctx->ctx->parse_pos = 1;
-+                ++p;
-+                return (p - data);
-+            }
-+            ++p;
-+        }
-+
-+        if (p < ep) { /* found delimiter whitespace */
-+            ctx->state = PARSE_DIRECTIVE_POSTNAME;
-+            *store = &ctx->directive;
-+            *store_len = &ctx->ctx->directive_length;
-+        }
-+
-+        break;
-+
-+    case PARSE_DIRECTIVE_TAIL:
-+        pos = ctx->ctx->parse_pos;
-+
-+        while (p < ep && pos < ctx->end_seq_len &&
-+               *p == ctx->ctx->end_seq[pos]) {
-+            ++p;
-+            ++pos;
-+        }
-+
-+        /* full match, we're done */
-+        if (pos == ctx->end_seq_len) {
-+            ctx->state = PARSE_DIRECTIVE_POSTTAIL;
-+            *store = &ctx->directive;
-+            *store_len = &ctx->ctx->directive_length;
-+            break;
-+        }
-+
-+        /* partial match, the buffer is too small to match fully */
-+        if (p == ep) {
-+            ctx->ctx->parse_pos = pos;
-+            break;
-+        }
-+
-+        /* no match. continue normal parsing */
-+        ctx->state = PARSE_DIRECTIVE;
-+        return 0;
-+
-+    case PARSE_DIRECTIVE_POSTTAIL:
-+        ctx->state = PARSE_EXECUTE;
-+        ctx->ctx->directive_length -= ctx->end_seq_len;
-+        /* continue immediately with the next state */
-+
-+    case PARSE_DIRECTIVE_POSTNAME:
-+        if (PARSE_DIRECTIVE_POSTNAME == ctx->state) {
-+            ctx->state = PARSE_PRE_ARG;
-+        }
-+        ctx->argc = 0;
-+        ctx->argv = NULL;
-+
-+        if (!ctx->ctx->directive_length) {
-+            ctx->error = 1;
-+            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r, "missing directive "
-+                          "name in parsed document %s", ctx->r->filename);
-+        }
-+        else {
-+            char *sp = ctx->directive;
-+            char *sep = ctx->directive + ctx->ctx->directive_length;
-+
-+            /* normalize directive name */
-+            for (; sp < sep; ++sp) {
-+                *sp = apr_tolower(*sp);
-             }
--            tmp_dptr = ctx->head_start_bucket;
--            if (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade)) {
--                apr_brigade_cleanup(ctx->ssi_tag_brigade);
-+        }
-+
-+        return 0;
-+
-+    default:
-+        /* get a rid of a gcc warning about unhandled enumerations */
-+        break;
-+    }
-+
-+    return (p - data);
-+}
-+
-+/*
-+ * find out whether the next token is (a possible) end_seq or an argument
-+ */
-+static apr_size_t find_arg_or_tail(ssi_ctx_t *ctx, const char *data,
-+                                   apr_size_t len)
-+{
-+    const char *p = data;
-+    const char *ep = data + len;
-+
-+    /* skip leading WS */
-+    while (p < ep && apr_isspace(*p)) {
-+        ++p;
-+    }
-+
-+    /* buffer doesn't consist of whitespaces only */
-+    if (p < ep) {
-+        ctx->state = (*p == *ctx->ctx->end_seq) ? PARSE_TAIL : PARSE_ARG;
-+    }
-+
-+    return (p - data);
-+}
-+
-+/*
-+ * test the stream for end_seq. If it doesn't match at all, it must be an
-+ * argument
-+ */
-+static apr_size_t find_tail(ssi_ctx_t *ctx, const char *data,
-+                            apr_size_t len)
-+{
-+    const char *p = data;
-+    const char *ep = data + len;
-+    apr_size_t pos = ctx->ctx->parse_pos;
-+
-+    if (PARSE_TAIL == ctx->state) {
-+        ctx->state = PARSE_TAIL_SEQ;
-+        pos = ctx->ctx->parse_pos = 0;
-+    }
-+
-+    while (p < ep && pos < ctx->end_seq_len && *p == ctx->ctx->end_seq[pos]) {
-+        ++p;
-+        ++pos;
-+    }
-+
-+    /* bingo, full match */
-+    if (pos == ctx->end_seq_len) {
-+        ctx->state = PARSE_EXECUTE;
-+        return (p - data);
-+    }
-+
-+    /* partial match, the buffer is too small to match fully */
-+    if (p == ep) {
-+        ctx->ctx->parse_pos = pos;
-+        return (p - data);
-+    }
-+
-+    /* no match. It must be an argument string then */
-+    ctx->state = PARSE_ARG;
-+    return 0;
-+}
-+
-+/*
-+ * extract name=value from the buffer
-+ * A pcre-pattern could look (similar to):
-+ * name\s*(?:=\s*(["'`]?)value\1(?>\s*))?
-+ */
-+static apr_size_t find_argument(ssi_ctx_t *ctx, const char *data,
-+                                apr_size_t len, char ***store,
-+                                apr_size_t **store_len)
-+{
-+    const char *p = data;
-+    const char *ep = data + len;
-+
-+    switch (ctx->state) {
-+    case PARSE_ARG:
-+        /*
-+         * create argument structure and append it to the current list
-+         */
-+        ctx->current_arg = apr_palloc(ctx->dpool,
-+                                      sizeof(*ctx->current_arg));
-+        ctx->current_arg->next = NULL;
-+
-+        ++(ctx->argc);
-+        if (!ctx->argv) {
-+            ctx->argv = ctx->current_arg;
-+        }
-+        else {
-+            ssi_arg_item_t *newarg = ctx->argv;
-+
-+            while (newarg->next) {
-+                newarg = newarg->next;
-             }
--            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)));
-+            newarg->next = ctx->current_arg;
-+        }
-+
-+        /* check whether it's a valid one. If it begins with a quote, we
-+         * can safely assume, someone forgot the name of the argument
-+         */
-+        switch (*p) {
-+        case '"': case '\'': case '`':
-+            *store = NULL;
-+
-+            ctx->state = PARSE_ARG_VAL;
-+            ctx->quote = *p++;
-+            ctx->current_arg->name = NULL;
-+            ctx->current_arg->name_len = 0;
-+            ctx->error = 1;
-+
-+            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r, "missing argument "
-+                          "name for value to tag %s in %s",
-+                          apr_pstrmemdup(ctx->r->pool, ctx->directive,
-+                                         ctx->ctx->directive_length),
-+                                         ctx->r->filename);
-+
-+            return (p - data);
-+
-+        default:
-+            ctx->state = PARSE_ARG_NAME;
-+        }
-+        /* continue immediately with next state */
-+
-+    case PARSE_ARG_NAME:
-+        while (p < ep && !apr_isspace(*p) && *p != '=') {
-+            ++p;
-+        }
-+
-+        if (p < ep) {
-+            ctx->state = PARSE_ARG_POSTNAME;
-+            *store = &ctx->current_arg->name;
-+            *store_len = &ctx->current_arg->name_len;
-+            return (p - data);
-+        }
-+        break;
-+
-+    case PARSE_ARG_POSTNAME:
-+        ctx->current_arg->name = apr_pstrmemdup(ctx->dpool,
-+                                                ctx->current_arg->name,
-+                                                ctx->current_arg->name_len);
-+        if (!ctx->current_arg->name_len) {
-+            ctx->error = 1;
-+            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r, "missing argument "
-+                          "name for value to tag %s in %s",
-+                          apr_pstrmemdup(ctx->r->pool, ctx->directive,
-+                                         ctx->ctx->directive_length),
-+                                         ctx->r->filename);
-+        }
-+        else {
-+            char *sp = ctx->current_arg->name;
-+
-+            /* normalize the name */
-+            while (*sp) {
-+                *sp = apr_tolower(*sp);
-+                ++sp;
-+            }
-+        }
-+
-+        ctx->state = PARSE_ARG_EQ;
-+        /* continue with next state immediately */
-+
-+    case PARSE_ARG_EQ:
-+        *store = NULL;
-+
-+        while (p < ep && apr_isspace(*p)) {
-+            ++p;
-+        }
-+
-+        if (p < ep) {
-+            if (*p == '=') {
-+                ctx->state = PARSE_ARG_PREVAL;
-+                ++p;
-             }
--            if (ctx->combined_tag == tmp_buf) {
--                ctx->combined_tag = NULL;
-+            else { /* no value */
-+                ctx->current_arg->value = NULL;
-+                ctx->state = PARSE_PRE_ARG;
-             }
--            /* 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;
-+            return (p - data);
-+        }
-+        break;
-+
-+    case PARSE_ARG_PREVAL:
-+        *store = NULL;
--            if (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade)) {
--                apr_brigade_cleanup(ctx->ssi_tag_brigade);
-+        while (p < ep && apr_isspace(*p)) {
-+            ++p;
-+        }
-+
-+        /* buffer doesn't consist of whitespaces only */
-+        if (p < ep) {
-+            ctx->state = PARSE_ARG_VAL;
-+            switch (*p) {
-+            case '"': case '\'': case '`':
-+                ctx->quote = *p++;
-+                break;
-+            default:
-+                ctx->quote = '\0';
-+                break;
-             }
--            ctx->state     = PRE_HEAD;
-+            return (p - data);
-         }
--    }
-+        break;
-+
-+    case PARSE_ARG_VAL_ESC:
-+        if (*p == ctx->quote) {
-+            ++p;
-+        }
-+        ctx->state = PARSE_ARG_VAL;
-+        /* continue with next state immediately */
-+
-+    case PARSE_ARG_VAL:
-+        for (; p < ep; ++p) {
-+            if (ctx->quote && *p == '\\') {
-+                ++p;
-+                if (p == ep) {
-+                    ctx->state = PARSE_ARG_VAL_ESC;
-+                    break;
-+                }
--    /* 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);
-+                if (*p != ctx->quote) {
-+                    --p;
-+                }
-+            }
-+            else if (ctx->quote && *p == ctx->quote) {
-+                ++p;
-+                *store = &ctx->current_arg->value;
-+                *store_len = &ctx->current_arg->value_len;
-+                ctx->state = PARSE_ARG_POSTVAL;
-+                break;
-+            }
-+            else if (!ctx->quote && apr_isspace(*p)) {
-+                ++p;
-+                *store = &ctx->current_arg->value;
-+                *store_len = &ctx->current_arg->value_len;
-+                ctx->state = PARSE_ARG_POSTVAL;
-+                break;
-+            }
-         }
--        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;
-+        return (p - data);
-+
-+    case PARSE_ARG_POSTVAL:
-+        /*
-+         * The value is still the raw input string. Finally clean it up.
-+         */
-+        --(ctx->current_arg->value_len);
-+
-+        /* strip quote escaping \ from the string */
-+        if (ctx->quote) {
-+            apr_size_t shift = 0;
-+            char *sp;
-+
-+            sp = ctx->current_arg->value;
-+            ep = ctx->current_arg->value + ctx->current_arg->value_len;
-+            while (sp < ep && *sp != '\\') {
-+                ++sp;
-             }
--            ctx->bytes_parsed = 0;
-+            for (; sp < ep; ++sp) {
-+                if (*sp == '\\' && sp[1] == ctx->quote) {
-+                    ++sp;
-+                    ++shift;
-+                }
-+                if (shift) {
-+                    *(sp-shift) = *sp;
-+                }
-+            }
-+
-+            ctx->current_arg->value_len -= shift;
-         }
-+
-+        ctx->current_arg->value[ctx->current_arg->value_len] = '\0';
-+        ctx->state = PARSE_PRE_ARG;
-+
-+        return 0;
-+
-+    default:
-+        /* get a rid of a gcc warning about unhandled enumerations */
-+        break;
-     }
--    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);
-+
-+    return len; /* partial match of something */
-+}
-+
-+/*
-+ * This is the main loop over the current bucket brigade.
-+ */
-+static apr_status_t send_parsed_content(ap_filter_t *f, apr_bucket_brigade *bb)
-+{
-+    ssi_ctx_t *ctx = f->ctx;
-+    request_rec *r = f->r;
-+    apr_bucket *b = APR_BRIGADE_FIRST(bb);
-+    apr_bucket_brigade *pass_bb;
-+    apr_status_t rv = APR_SUCCESS;
-+    char *magic; /* magic pointer for sentinel use */
-+
-+    /* fast exit */
-+    if (APR_BRIGADE_EMPTY(bb)) {
-+        return APR_SUCCESS;
-     }
--    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) {
-+
-+    /* we may crash, since already cleaned up; hand over the responsibility
-+     * to the next filter;-)
-+     */
-+    if (ctx->seen_eos) {
-+        return ap_pass_brigade(f->next, bb);
-+    }
-+
-+    /* All stuff passed along has to be put into that brigade */
-+    pass_bb = apr_brigade_create(ctx->ctx->pool, f->c->bucket_alloc);
-+    ctx->ctx->bytes_parsed = 0;
-+    ctx->ctx->output_now = 0;
-+    ctx->error = 0;
-+
-+    /* loop over the current bucket brigade */
-+    while (b != APR_BRIGADE_SENTINEL(bb)) {
-+        const char *data = NULL;
-+        apr_size_t len, index, release;
-+        apr_bucket *newb = NULL;
-+        char **store = &magic;
-+        apr_size_t *store_len;
-+
-+        /* handle meta buckets before reading any data */
-+        if (APR_BUCKET_IS_METADATA(b)) {
-+            newb = APR_BUCKET_NEXT(b);
-+
-+            APR_BUCKET_REMOVE(b);
-+
-+            if (APR_BUCKET_IS_EOS(b)) {
-+                ctx->seen_eos = 1;
-+
-+                /* Hit end of stream, time for cleanup ... But wait!
-+                 * Perhaps we're not ready yet. We may have to loop one or
-+                 * two times again to finish our work. In that case, we
-+                 * just re-insert the EOS bucket to allow for an extra loop.
-+                 *
-+                 * PARSE_EXECUTE means, we've hit a directive just before the
-+                 *    EOS, which is now waiting for execution.
-+                 *
-+                 * PARSE_DIRECTIVE_POSTTAIL means, we've hit a directive with
-+                 *    no argument and no space between directive and end_seq
-+                 *    just before the EOS. (consider <!--#printenv--> as last
-+                 *    or only string within the stream). This state, however,
-+                 *    just cleans up and turns itself to PARSE_EXECUTE, which
-+                 *    will be passed through within the next (and actually
-+                 *    last) round.
-+                 */
-+                if (PARSE_EXECUTE            == ctx->state ||
-+                    PARSE_DIRECTIVE_POSTTAIL == ctx->state) {
-+                    APR_BUCKET_INSERT_BEFORE(newb, b);
-+                }
-+                else {
-+                    break; /* END OF STREAM */
-+                }
-+            }
-+            else {
-+                APR_BRIGADE_INSERT_TAIL(pass_bb, b);
-+
-+                if (APR_BUCKET_IS_FLUSH(b)) {
-+                    ctx->ctx->output_now = 1;
-+                }
-+
-+                b = newb;
-+                continue;
-+            }
-+        }
-+
-+        /* enough is enough ... */
-+        if (ctx->ctx->output_now ||
-+            ctx->ctx->bytes_parsed > AP_MIN_BYTES_TO_WRITE) {
-+
-+            if (!APR_BRIGADE_EMPTY(pass_bb)) {
-+                rv = ap_pass_brigade(f->next, pass_bb);
-+                if (!APR_STATUS_IS_SUCCESS(rv)) {
-+                    apr_brigade_destroy(pass_bb);
-+                    return rv;
-+                }
-+            }
-+
-+            ctx->ctx->output_now = 0;
-+            ctx->ctx->bytes_parsed = 0;
-+        }
-+
-+        /* read the current bucket data */
-+        len = 0;
-+        if (!ctx->seen_eos) {
-+            if (ctx->ctx->bytes_parsed > 0) {
-+                rv = apr_bucket_read(b, &data, &len, APR_NONBLOCK_READ);
-+                if (APR_STATUS_IS_EAGAIN(rv)) {
-+                    ctx->ctx->output_now = 1;
-+                    continue;
-+                }
-+            }
-+
-+            if (!len || !APR_STATUS_IS_SUCCESS(rv)) {
-+                rv = apr_bucket_read(b, &data, &len, APR_BLOCK_READ);
-+            }
-+
-+            if (!APR_STATUS_IS_SUCCESS(rv)) {
-+                apr_brigade_destroy(pass_bb);
-                 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)) {
-+
-+            ctx->ctx->bytes_parsed += len;
-+        }
-+
-+        /* zero length bucket, fetch next one */
-+        if (!len && !ctx->seen_eos) {
-+            b = APR_BUCKET_NEXT(b);
-+            continue;
-+        }
-+
-+        /*
-+         * it's actually a data containing bucket, start/continue parsing
-+         */
-+
-+        switch (ctx->state) {
-+        /* no current tag; search for start sequence */
-+        case PARSE_PRE_HEAD:
-+            index = find_start_sequence(ctx, data, len);
-+
-+            if (index < len) {
-+                apr_bucket_split(b, index);
-+            }
-+
-+            newb = APR_BUCKET_NEXT(b);
-+            if (ctx->ctx->flags & FLAG_PRINTING) {
-+                APR_BUCKET_REMOVE(b);
-+                APR_BRIGADE_INSERT_TAIL(pass_bb, b);
-+            }
-+            else {
-+                apr_bucket_delete(b);
-+            }
-+
-+            if (index < len) {
-+                /* now delete the start_seq stuff from the remaining bucket */
-+                if (PARSE_DIRECTIVE == ctx->state) { /* full match */
-+                    apr_bucket_split(newb, ctx->ctx->start_seq_len);
-+                    ctx->ctx->output_now = 1; /* pass pre-tag stuff */
-+                }
-+
-+                b = APR_BUCKET_NEXT(newb);
-+                apr_bucket_delete(newb);
-+            }
-+            else {
-+                b = newb;
-+            }
-+
-+            break;
-+
-+        /* we're currently looking for the end of the start sequence */
-+        case PARSE_HEAD:
-+            index = find_partial_start_sequence(ctx, data, len, &release);
-+
-+            /* check if we mismatched earlier and have to release some chars */
-+            if (release && (ctx->ctx->flags & FLAG_PRINTING)) {
-+                char *to_release = apr_palloc(ctx->ctx->pool, release);
-+
-+                memcpy(to_release, ctx->ctx->start_seq, release);
-+                newb = apr_bucket_pool_create(to_release, release,
-+                                              ctx->ctx->pool,
-+                                              f->c->bucket_alloc);
-+                APR_BRIGADE_INSERT_TAIL(pass_bb, newb);
-+            }
-+
-+            if (index) { /* any match */
-+                /* now delete the start_seq stuff from the remaining bucket */
-+                if (PARSE_DIRECTIVE == ctx->state) { /* final match */
-+                    apr_bucket_split(b, index);
-+                    ctx->ctx->output_now = 1; /* pass pre-tag stuff */
-+                }
-+                newb = APR_BUCKET_NEXT(b);
-+                apr_bucket_delete(b);
-+                b = newb;
-+            }
-+
-+            break;
-+
-+        /* we're currently grabbing the directive name */
-+        case PARSE_DIRECTIVE:
-+        case PARSE_DIRECTIVE_POSTNAME:
-+        case PARSE_DIRECTIVE_TAIL:
-+        case PARSE_DIRECTIVE_POSTTAIL:
-+            index = find_directive(ctx, data, len, &store, &store_len);
-+
-+            if (index) {
-+                apr_bucket_split(b, index);
-+                newb = APR_BUCKET_NEXT(b);
-+            }
-+
-+            if (store) {
-+                if (index) {
-                     APR_BUCKET_REMOVE(b);
--                    apr_bucket_destroy(b);
-+                    APR_BRIGADE_INSERT_TAIL(ctx->tmp_bb, b);
-+                    b = newb;
-+                }
-+
-+                /* time for cleanup? */
-+                if (store != &magic) {
-+                    apr_brigade_pflatten(ctx->tmp_bb, store, store_len,
-+                                         ctx->dpool);
-+                    apr_brigade_cleanup(ctx->tmp_bb);
-+                }
-+            }
-+            else if (index) {
-+                apr_bucket_delete(b);
-+                b = newb;
-+            }
-+
-+            break;
-+
-+        /* skip WS and find out what comes next (arg or end_seq) */
-+        case PARSE_PRE_ARG:
-+            index = find_arg_or_tail(ctx, data, len);
-+
-+            if (index) { /* skipped whitespaces */
-+                if (index < len) {
-+                    apr_bucket_split(b, index);
-+                }
-+                newb = APR_BUCKET_NEXT(b);
-+                apr_bucket_delete(b);
-+                b = newb;
-+            }
-+
-+            break;
-+
-+        /* currently parsing name[=val] */
-+        case PARSE_ARG:
-+        case PARSE_ARG_NAME:
-+        case PARSE_ARG_POSTNAME:
-+        case PARSE_ARG_EQ:
-+        case PARSE_ARG_PREVAL:
-+        case PARSE_ARG_VAL:
-+        case PARSE_ARG_VAL_ESC:
-+        case PARSE_ARG_POSTVAL:
-+            index = find_argument(ctx, data, len, &store, &store_len);
-+
-+            if (index) {
-+                apr_bucket_split(b, index);
-+                newb = APR_BUCKET_NEXT(b);
-+            }
-+
-+            if (store) {
-+                if (index) {
-+                    APR_BUCKET_REMOVE(b);
-+                    APR_BRIGADE_INSERT_TAIL(ctx->tmp_bb, b);
-+                    b = newb;
-+                }
-+
-+                /* time for cleanup? */
-+                if (store != &magic) {
-+                    apr_brigade_pflatten(ctx->tmp_bb, store, store_len,
-+                                         ctx->dpool);
-+                    apr_brigade_cleanup(ctx->tmp_bb);
-+                }
-+            }
-+            else if (index) {
-+                apr_bucket_delete(b);
-+                b = newb;
-+            }
-+
-+            break;
-+
-+        /* try to match end_seq at current pos. */
-+        case PARSE_TAIL:
-+        case PARSE_TAIL_SEQ:
-+            index = find_tail(ctx, data, len);
-+
-+            switch (ctx->state) {
-+            case PARSE_EXECUTE:  /* full match */
-+                apr_bucket_split(b, index);
-+                newb = APR_BUCKET_NEXT(b);
-+                apr_bucket_delete(b);
-+                b = newb;
-+                break;
-+
-+            case PARSE_ARG:      /* no match */
-+                /* PARSE_ARG must reparse at the beginning */
-+                APR_BRIGADE_PREPEND(bb, ctx->tmp_bb);
-+                b = APR_BRIGADE_FIRST(bb);
-+                break;
-+
-+            default:             /* partial match */
-+                newb = APR_BUCKET_NEXT(b);
-+                APR_BUCKET_REMOVE(b);
-+                APR_BRIGADE_INSERT_TAIL(ctx->tmp_bb, b);
-+                b = newb;
-+                break;
-+            }
-+
-+            break;
-+
-+        /* now execute the parsed directive, cleanup the space and
-+         * start again with PARSE_PRE_HEAD
-+         */
-+        case PARSE_EXECUTE:
-+            /* if there was an error, it was already logged; just stop here */
-+            if (ctx->error) {
-+                if (ctx->ctx->flags & FLAG_PRINTING) {
-+                    SSI_CREATE_ERROR_BUCKET(ctx->ctx, f, pass_bb);
-+                    ctx->error = 0;
-                 }
--                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);
-+                include_handler_fn_t *handle_func;
-+
-+                handle_func =
-+                    (include_handler_fn_t *) apr_hash_get(include_hash,
-+                                                    ctx->directive,
-+                                                    ctx->ctx->directive_length);
-+                if (handle_func) {
-+                    apr_bucket *dummy;
-+                    char *tag;
-+                    apr_size_t tag_len = 0;
-+                    ssi_arg_item_t *carg = ctx->argv;
-+
-+                    /* legacy wrapper code */
-+                    while (carg) {
-+                        /* +1 \0 byte (either after tag or value)
-+                         * +1 =  byte (before value)
-+                         */
-+                        tag_len += (carg->name  ? carg->name_len      : 0) +
-+                                   (carg->value ? carg->value_len + 1 : 0) + 1;
-+                        carg = carg->next;
-+                    }
-+
-+                    tag = ctx->ctx->combined_tag = ctx->ctx->curr_tag_pos =
-+                        apr_palloc(ctx->dpool, tag_len);
-+
-+                    carg = ctx->argv;
-+                    while (carg) {
-+                        if (carg->name) {
-+                            memcpy(tag, carg->name, carg->name_len);
-+                            tag += carg->name_len;
-+                        }
-+                        if (carg->value) {
-+                            *tag++ = '=';
-+                            memcpy(tag, carg->value, carg->value_len);
-+                            tag += carg->value_len;
-+                        }
-+                        *tag++ = '\0';
-+                        carg = carg->next;
-+                    }
-+                    ctx->ctx->tag_length = tag_len;
-+
-+                    /* create dummy buckets for backards compat */
-+                    ctx->ctx->head_start_bucket =
-+                        apr_bucket_pool_create(apr_pmemdup(ctx->ctx->pool,
-+                                                           ctx->ctx->start_seq,
-+                                                       ctx->ctx->start_seq_len),
-+                                               ctx->ctx->start_seq_len,
-+                                               ctx->ctx->pool,
-+                                               f->c->bucket_alloc);
-+                    APR_BRIGADE_INSERT_TAIL(ctx->ctx->ssi_tag_brigade,
-+                                            ctx->ctx->head_start_bucket);
-+                    ctx->ctx->tag_start_bucket =
-+                        apr_bucket_pool_create(apr_pmemdup(ctx->ctx->pool,
-+                                                         ctx->ctx->combined_tag,
-+                                                         ctx->ctx->tag_length),
-+                                               ctx->ctx->tag_length,
-+                                               ctx->ctx->pool,
-+                                               f->c->bucket_alloc);
-+                    APR_BRIGADE_INSERT_TAIL(ctx->ctx->ssi_tag_brigade,
-+                                            ctx->ctx->tag_start_bucket);
-+                    ctx->ctx->tail_start_bucket =
-+                        apr_bucket_pool_create(apr_pmemdup(ctx->ctx->pool,
-+                                                           ctx->ctx->end_seq,
-+                                                           ctx->end_seq_len),
-+                                               ctx->end_seq_len,
-+                                               ctx->ctx->pool,
-+                                               f->c->bucket_alloc);
-+                    APR_BRIGADE_INSERT_TAIL(ctx->ctx->ssi_tag_brigade,
-+                                            ctx->ctx->tail_start_bucket);
-+
-+                    rv = handle_func(ctx->ctx, &bb, r, f, b, &dummy);
-+
-+                    apr_brigade_cleanup(ctx->ctx->ssi_tag_brigade);
-+
-+                    if (rv != 0 && rv != 1 && rv != -1) {
-+                        apr_brigade_destroy(pass_bb);
-+                        return rv;
-+                    }
-+
-+                    if (dummy) {
-+                        apr_bucket_brigade *remain;
-+
-+                        remain = apr_brigade_split(bb, b);
-+                        APR_BRIGADE_CONCAT(pass_bb, bb);
-+                        bb = remain;
-+                    }
-+                }
-+                else {
-+                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-+                                  "unknown directive \"%s\" in parsed doc %s",
-+                                  apr_pstrmemdup(r->pool, ctx->directive,
-+                                                 ctx->ctx->directive_length),
-+                                                 r->filename);
-+                    if (ctx->ctx->flags & FLAG_PRINTING) {
-+                        SSI_CREATE_ERROR_BUCKET(ctx->ctx, f, pass_bb);
-+                    }
-+                }
-             }
--            if (rv != APR_SUCCESS) {
--                return rv;
-+
-+            /* cleanup */
-+            apr_pool_clear(ctx->dpool);
-+            apr_brigade_cleanup(ctx->tmp_bb);
-+
-+            /* Oooof. Done here, start next round */
-+            ctx->state = PARSE_PRE_HEAD;
-+            break;
-+        }
-+
-+    } /* while (brigade) */
-+
-+    /* End of stream. Final cleanup */
-+    if (ctx->seen_eos) {
-+        if (PARSE_HEAD == ctx->state) {
-+            if (ctx->ctx->flags & FLAG_PRINTING) {
-+                char *to_release = apr_palloc(ctx->ctx->pool,
-+                                              ctx->ctx->parse_pos);
-+
-+                memcpy(to_release, ctx->ctx->start_seq, ctx->ctx->parse_pos);
-+                APR_BRIGADE_INSERT_TAIL(pass_bb,
-+                                        apr_bucket_pool_create(to_release,
-+                                        ctx->ctx->parse_pos, ctx->ctx->pool,
-+                                        f->c->bucket_alloc));
-             }
--            ctx->bytes_parsed = 0;
-         }
-+        else if (PARSE_PRE_HEAD != ctx->state) {
-+            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-+                          "SSI directive was not properly finished at the end "
-+                          "of parsed document %s", r->filename);
-+            if (ctx->ctx->flags & FLAG_PRINTING) {
-+                SSI_CREATE_ERROR_BUCKET(ctx->ctx, f, pass_bb);
-+            }
-+        }
-+
-+        if (!(ctx->ctx->flags & FLAG_PRINTING)) {
-+            ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
-+                          "missing closing endif directive in parsed document"
-+                          " %s", r->filename);
-+        }
-+
-+        /* cleanup our temporary memory */
-+        apr_brigade_destroy(ctx->tmp_bb);
-+        apr_pool_destroy(ctx->dpool);
-+
-+        /* don't forget to finally insert the EOS bucket */
-+        APR_BRIGADE_INSERT_TAIL(pass_bb, b);
-     }
--    return APR_SUCCESS;
-+
-+    /* if something's left over, pass it along */
-+    if (!APR_BRIGADE_EMPTY(pass_bb)) {
-+        rv = ap_pass_brigade(f->next, pass_bb);
-+    }
-+    else {
-+        rv = APR_SUCCESS;
-+    }
-+
-+    apr_brigade_destroy(pass_bb);
-+    return rv;
- }
- static void *create_includes_dir_config(apr_pool_t *p, char *dummy)
-@@ -3335,14 +3544,20 @@
-         || !(f->r->finfo.protection & APR_GEXECUTE)) {
-         f->r->no_local_copy = 1;
-     }
--    
-+
-+    /* Don't allow ETag headers to be generated - see RFC2616 - 13.3.4.
-+     * We don't know if we are going to be including a file or executing
-+     * a program - in either case a strong ETag header will likely be invalid.
-+     */
-+    apr_table_setn(f->r->notes, "no-etag", "");
-+
-     return OK;
- }
- static apr_status_t includes_filter(ap_filter_t *f, apr_bucket_brigade *b)
- {
-     request_rec *r = f->r;
--    include_ctx_t *ctx = f->ctx;
-+    ssi_ctx_t *ctx = f->ctx;
-     request_rec *parent;
-     include_dir_config *conf = 
-                    (include_dir_config *)ap_get_module_config(r->per_dir_config,
-@@ -3352,30 +3567,55 @@
-                                                               &include_module);
-     if (!(ap_allow_options(r) & OPT_INCLUDES)) {
-+        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
-+                      "mod_include: Options +Includes (or IncludesNoExec) "
-+                      "wasn't set, INCLUDES filter removed");
-+        ap_remove_output_filter(f);
-         return ap_pass_brigade(f->next, b);
-     }
-     if (!f->ctx) {
--        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;
-+        /* 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));
-+        ctx->ctx->pool = f->r->pool;
-+        apr_pool_create(&ctx->dpool, ctx->ctx->pool);
-+
-+        /* configuration data */
-+        ctx->end_seq_len = strlen(sconf->default_end_tag);
-+        ctx->r = f->r;
-+
-+        /* runtime data */
-+        ctx->tmp_bb = apr_brigade_create(ctx->ctx->pool, f->c->bucket_alloc);
-+        ctx->seen_eos = 0;
-+        ctx->state = PARSE_PRE_HEAD;
-+        ctx->ctx->flags = (FLAG_PRINTING | FLAG_COND_TRUE);
-+        if (ap_allow_options(f->r) & OPT_INCNOEXEC) {
-+            ctx->ctx->flags |= FLAG_NO_EXEC;
-+        }
-+        ctx->ctx->if_nesting_level = 0;
-+        ctx->ctx->re_string = NULL;
-+        ctx->ctx->error_str_override = NULL;
-+        ctx->ctx->time_str_override = NULL;
-+
-+        ctx->ctx->error_str = conf->default_error_msg;
-+        ctx->ctx->time_str = conf->default_time_fmt;
-+        ctx->ctx->start_seq_pat = &sconf->start_seq_pat;
-+        ctx->ctx->start_seq  = sconf->default_start_tag;
-+        ctx->ctx->start_seq_len = sconf->start_tag_len;
-+        ctx->ctx->end_seq = sconf->default_end_tag;
-+
-+        /* legacy compat stuff */
-+        ctx->ctx->state = PARSED; /* dummy */
-+        ctx->ctx->ssi_tag_brigade = apr_brigade_create(f->c->pool,
-+                                                       f->c->bucket_alloc);
-+        ctx->ctx->status = APR_SUCCESS;
-+        ctx->ctx->head_start_index = 0;
-+        ctx->ctx->tag_start_index = 0;
-+        ctx->ctx->tail_start_index = 0;
-     }
-     else {
--        ctx->bytes_parsed = 0;
-+        ctx->ctx->bytes_parsed = 0;
-     }
-     if ((parent = ap_get_module_config(r->request_config, &include_module))) {
-@@ -3405,14 +3645,13 @@
-      */
-     apr_table_unset(f->r->headers_out, "Content-Length");
--    /* Always unset the ETag/Last-Modified fields - see RFC2616 - 13.3.4.
-+    /* Always unset the Last-Modified field - see RFC2616 - 13.3.4.
-      * We don't know if we are going to be including a file or executing
-      * a program which may change the Last-Modified header or make the 
-      * content completely dynamic.  Therefore, we can't support these
-      * headers.
-      * Exception: XBitHack full means we *should* set the Last-Modified field.
-      */
--    apr_table_unset(f->r->headers_out, "ETag");
-     /* Assure the platform supports Group protections */
-     if ((*conf->xbithack == xbithack_full)
-@@ -3425,7 +3664,17 @@
-         apr_table_unset(f->r->headers_out, "Last-Modified");
-     }
--    return send_parsed_content(&b, r, f);
-+    /* add QUERY stuff to env cause it ain't yet */
-+    if (r->args) {
-+        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));
-+    }
-+
-+    return send_parsed_content(f, b);
- }
- static void ap_register_include_handler(char *tag, include_handler_fn_t *func)
diff --git a/httpd-2.0.48-proxy11.patch b/httpd-2.0.48-proxy11.patch
deleted file mode 100644 (file)
index af15501..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-
-HTTP/1.1 compliance fixes for mod_proxy, from HEAD.
-
---- httpd-2.0.48/modules/proxy/proxy_http.c.proxy11
-+++ httpd-2.0.48/modules/proxy/proxy_http.c
-@@ -700,11 +700,8 @@
-     request_rec *rp;
-     apr_bucket *e;
-     int len, backasswards;
--    int received_continue = 1; /* flag to indicate if we should
--                                * loop over response parsing logic
--                                * in the case that the origin told us
--                                * to HTTP_CONTINUE
--                                */
-+    int interim_response; /* non-zero whilst interim 1xx responses
-+                           * are being read. */
-     /* Get response from the remote server, and pass it up the
-      * filter chain
-@@ -716,7 +713,7 @@
-      */
-     rp->proxyreq = PROXYREQ_RESPONSE;
--    while (received_continue) {
-+    do {
-         apr_brigade_cleanup(bb);
-         len = ap_getline(buffer, sizeof(buffer), rp, 0);
-@@ -839,11 +836,11 @@
-             p_conn->close += 1;
-         }
--        if ( r->status != HTTP_CONTINUE ) {
--            received_continue = 0;
--        } else {
-+        interim_response = ap_is_HTTP_INFO(r->status);
-+        if (interim_response) {
-             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,
--                         "proxy: HTTP: received 100 CONTINUE");
-+                         "proxy: HTTP: received interim %d response",
-+                         r->status);
-         }
-         /* we must accept 3 kinds of date, but generate only 1 kind of date */
-@@ -903,7 +900,7 @@
-         /* send body - but only if a body is expected */
-         if ((!r->header_only) &&                   /* not HEAD request */
--            (r->status > 199) &&                   /* not any 1xx response */
-+            !interim_response &&                   /* not any 1xx response */
-             (r->status != HTTP_NO_CONTENT) &&      /* not 204 */
-             (r->status != HTTP_RESET_CONTENT) &&   /* not 205 */
-             (r->status != HTTP_NOT_MODIFIED)) {    /* not 304 */
-@@ -982,7 +979,7 @@
-             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
-                          "proxy: header only");
-         }
--    }
-+    } while (interim_response);
-     if ( conf->error_override ) {
-         /* the code above this checks for 'OK' which is what the hook expects */
-@@ -995,7 +992,11 @@
-              */
-             int status = r->status;
-             r->status = HTTP_OK;
--            ap_discard_request_body(rp);
-+            if (status != HTTP_NO_CONTENT && /* not 204 */
-+                status != HTTP_RESET_CONTENT && /* not 205 */
-+                status != HTTP_NOT_MODIFIED) { /* not 304 */
-+                ap_discard_request_body(rp);
-+            }
-             return status;
-         }
-     } else 
---- httpd-2.0.48/server/protocol.c.proxy11
-+++ httpd-2.0.48/server/protocol.c
-@@ -463,6 +463,7 @@
-                 }
-                     bytes_handled += next_len;
-+                    last_char += next_len;
-             }
-             }
-             else { /* next character is not tab or space */
diff --git a/httpd-2.0.48-sslvars.patch b/httpd-2.0.48-sslvars.patch
deleted file mode 100644 (file)
index a6cb080..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-
-Fixes for SSL variable handling from 2.0.49/HEAD.
-
---- httpd-2.0.48/modules/ssl/ssl_engine_vars.c.sslvars
-+++ httpd-2.0.48/modules/ssl/ssl_engine_vars.c
-@@ -87,9 +87,9 @@
-     return;
- }
-+/* This function must remain safe to use for a non-SSL connection. */
- char *ssl_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, char *var)
- {
--    SSLConnRec *sslconn;
-     SSLModConfigRec *mc = myModConfig(s);
-     char *result;
-     BOOL resdup;
-@@ -169,17 +169,18 @@
-      * Connection stuff
-      */
-     if (result == NULL && c != NULL) {
--        sslconn = myConnConfig(c);
-+        SSLConnRec *sslconn = myConnConfig(c);
-         if (strcEQ(var, "REMOTE_ADDR"))
-             result = c->remote_ip;
-         else if (strcEQ(var, "REMOTE_USER"))
-             result = r->user;
-         else if (strcEQ(var, "AUTH_TYPE"))
-             result = r->ap_auth_type;
--        else if (strlen(var) > 4 && strcEQn(var, "SSL_", 4))
-+        else if (strlen(var) > 4 && strcEQn(var, "SSL_", 4) 
-+                 && sslconn && sslconn->ssl)
-             result = ssl_var_lookup_ssl(p, c, var+4);
-         else if (strcEQ(var, "HTTPS")) {
--            if (sslconn->ssl != NULL)
-+            if (sslconn && sslconn->ssl)
-                 result = "on";
-             else
-                 result = "off";
-@@ -280,10 +281,12 @@
-     else if (ssl != NULL && strcEQ(var, "SESSION_ID")) {
-         char buf[SSL_SESSION_ID_STRING_LEN];
-         SSL_SESSION *pSession = SSL_get_session(ssl);
--        result = apr_pstrdup(p, SSL_SESSION_id2sz(
--                                SSL_SESSION_get_session_id(pSession),
--                                SSL_SESSION_get_session_id_length(pSession),
--                                buf, sizeof(buf)));
-+        if (pSession) {
-+            result = apr_pstrdup(p, SSL_SESSION_id2sz(
-+                                     SSL_SESSION_get_session_id(pSession),
-+                                     SSL_SESSION_get_session_id_length(pSession),
-+                                     buf, sizeof(buf)));
-+        }
-     }
-     else if (ssl != NULL && strlen(var) >= 6 && strcEQn(var, "CIPHER", 6)) {
-         result = ssl_var_lookup_ssl_cipher(p, c, var+6);
-@@ -608,7 +611,7 @@
-         result = apr_psprintf(p, "mod_ssl/%s", MOD_SSL_VERSION);
-     }
-     else if (strEQ(var, "LIBRARY")) {
--        result = apr_pstrdup(p, SSL_LIBRARY_TEXT);
-+        result = apr_pstrdup(p, SSLeay_version(SSLEAY_VERSION));
-         if ((cp = strchr(result, ' ')) != NULL) {
-             *cp = '/';
-             if ((cp2 = strchr(cp, ' ')) != NULL)
-@@ -655,7 +658,7 @@
-     SSLConnRec *sslconn = myConnConfig(r->connection);
-     char *result;
--    if (sslconn->ssl == NULL)
-+    if (sslconn == NULL || sslconn->ssl == NULL)
-         return NULL;
-     result = NULL;
-     if (strEQ(a, "version"))
-@@ -681,12 +684,9 @@
-  */
- static const char *ssl_var_log_handler_x(request_rec *r, char *a)
- {
--    SSLConnRec *sslconn = myConnConfig(r->connection);
-     char *result;
--    result = NULL;
--    if (sslconn && sslconn->ssl)
--        result = ssl_var_lookup(r->pool, r->server, r->connection, r, a);
-+    result = ssl_var_lookup(r->pool, r->server, r->connection, r, a);
-     if (result != NULL && result[0] == NUL)
-         result = NULL;
-     return result;
diff --git a/httpd-2.0.48-status.patch b/httpd-2.0.48-status.patch
deleted file mode 100644 (file)
index b3771a7..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-
-Add mod_status extension hook. (UPSTREAM, 2.0.49)
-
---- httpd-2.0.48/modules/generators/mod_status.c.status
-+++ httpd-2.0.48/modules/generators/mod_status.c
-@@ -107,6 +107,7 @@
- #include <time.h>
- #include "scoreboard.h"
- #include "http_log.h"
-+#include "mod_status.h"
- #if APR_HAVE_UNISTD_H
- #include <unistd.h>
- #endif
-@@ -141,6 +142,12 @@
- int server_limit, thread_limit;
-+/* Implement 'ap_run_status_hook'. */
-+AP_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(int,status_hook,
-+                                   (request_rec *r, int flags),
-+                                   (r, flags),
-+                                   OK, DECLINED)
-+
- /*
-  * command-related code. This is here to prevent use of ExtendedStatus
-  * without status_module included.
-@@ -786,6 +793,16 @@
-         }
-     }
-+    {
-+        /* Run extension hooks to insert extra content. */
-+        int flags = 
-+            (short_report ? AP_STATUS_SHORT : 0) | 
-+            (no_table_report ? AP_STATUS_NOTABLE : 0) |
-+            (ap_extended_status ? AP_STATUS_EXTENDED : 0);
-+        
-+        ap_run_status_hook(r, flags);
-+    }
-+
-     if (!short_report) {
-         ap_rputs(ap_psignature("<hr />\n",r), r);
-         ap_rputs("</body></html>\n", r);
---- httpd-2.0.48/modules/generators/mod_status.h.status
-+++ httpd-2.0.48/modules/generators/mod_status.h
-@@ -0,0 +1,92 @@
-+/* ====================================================================
-+ * The Apache Software License, Version 1.1
-+ *
-+ * Copyright (c) 2003-2004 The Apache Software Foundation.  All rights
-+ * reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ * 1. Redistributions of source code must retain the above copyright
-+ *    notice, this list of conditions and the following disclaimer.
-+ *
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ *    notice, this list of conditions and the following disclaimer in
-+ *    the documentation and/or other materials provided with the
-+ *    distribution.
-+ *
-+ * 3. The end-user documentation included with the redistribution,
-+ *    if any, must include the following acknowledgment:
-+ *       "This product includes software developed by the
-+ *        Apache Software Foundation (http://www.apache.org/)."
-+ *    Alternately, this acknowledgment may appear in the software itself,
-+ *    if and wherever such third-party acknowledgments normally appear.
-+ *
-+ * 4. The names "Apache" and "Apache Software Foundation" must
-+ *    not be used to endorse or promote products derived from this
-+ *    software without prior written permission. For written
-+ *    permission, please contact apache@apache.org.
-+ *
-+ * 5. Products derived from this software may not be called "Apache",
-+ *    nor may "Apache" appear in their name, without prior written
-+ *    permission of the Apache Software Foundation.
-+ *
-+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
-+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
-+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
-+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-+ * SUCH DAMAGE.
-+ * ====================================================================
-+ *
-+ * This software consists of voluntary contributions made by many
-+ * individuals on behalf of the Apache Software Foundation.  For more
-+ * information on the Apache Software Foundation, please see
-+ * <http://www.apache.org/>.
-+ */
-+
-+#ifndef MOD_STATUS_H
-+#define MOD_STATUS_H
-+
-+#include "ap_config.h"
-+#include "httpd.h"
-+
-+#define AP_STATUS_SHORT    (0x1)  /* short, non-HTML report requested */
-+#define AP_STATUS_NOTABLE  (0x2)  /* HTML report without tables */
-+#define AP_STATUS_EXTENDED (0x4)  /* detailed report */
-+
-+#if !defined(WIN32)
-+#define STATUS_DECLARE(type)            type
-+#define STATUS_DECLARE_NONSTD(type)     type
-+#define STATUS_DECLARE_DATA
-+#elif defined(STATUS_DECLARE_STATIC)
-+#define STATUS_DECLARE(type)            type __stdcall
-+#define STATUS_DECLARE_NONSTD(type)     type
-+#define STATUS_DECLARE_DATA
-+#elif defined(STATUS_DECLARE_EXPORT)
-+#define STATUS_DECLARE(type)            __declspec(dllexport) type __stdcall
-+#define STATUS_DECLARE_NONSTD(type)     __declspec(dllexport) type
-+#define STATUS_DECLARE_DATA             __declspec(dllexport)
-+#else
-+#define STATUS_DECLARE(type)            __declspec(dllimport) type __stdcall
-+#define STATUS_DECLARE_NONSTD(type)     __declspec(dllimport) type
-+#define STATUS_DECLARE_DATA             __declspec(dllimport)
-+#endif
-+
-+/* Optional hooks which can insert extra content into the mod_status
-+ * output.  FLAGS will be set to the bitwise OR of any of the
-+ * AP_STATUS_* flags.
-+ *
-+ * Implementations of this hook should generate content using
-+ * functions in the ap_rputs/ap_rprintf family; each hook should
-+ * return OK or DECLINED. */
-+APR_DECLARE_EXTERNAL_HOOK(ap, STATUS, int, status_hook,
-+                          (request_rec *r, int flags))
-+#endif
---- httpd-2.0.48/Makefile.in.status
-+++ httpd-2.0.48/Makefile.in
-@@ -174,6 +174,7 @@
-       @cp -p $(srcdir)/modules/dav/main/mod_dav.h $(DESTDIR)$(includedir)
-       @cp -p $(srcdir)/modules/filters/mod_include.h $(DESTDIR)$(includedir)
-       @cp -p $(srcdir)/modules/generators/mod_cgi.h $(DESTDIR)$(includedir)
-+      @cp -p $(srcdir)/modules/generators/mod_status.h $(DESTDIR)$(includedir)
-       @cp -p $(srcdir)/modules/loggers/mod_log_config.h $(DESTDIR)$(includedir)
-       @cp -p $(srcdir)/modules/http/mod_core.h $(DESTDIR)$(includedir)
-       @cp -p $(srcdir)/modules/proxy/mod_proxy.h $(DESTDIR)$(includedir)
---- httpd-2.0.48/configure.in.status
-+++ httpd-2.0.48/configure.in
-@@ -124,7 +124,7 @@
-   APR_ADDTO(INCLUDES, [-I\$(top_builddir)/include])
- fi
--APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/os/\$(OS_DIR) -I\$(top_srcdir)/server/mpm/\$(MPM_SUBDIR_NAME) -I\$(top_srcdir)/modules/http -I\$(top_srcdir)/modules/filters -I\$(top_srcdir)/modules/proxy -I\$(top_srcdir)/include])
-+APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/os/\$(OS_DIR) -I\$(top_srcdir)/server/mpm/\$(MPM_SUBDIR_NAME) -I\$(top_srcdir)/modules/http -I\$(top_srcdir)/modules/filters -I\$(top_srcdir)/modules/proxy -I\$(top_srcdir)/include -I\$(top_srcdir)/modules/generators])
- echo $ac_n "${nl}Applying OS-specific hints for httpd ...${nl}"
diff --git a/httpd-2.0.48-usertrack.patch b/httpd-2.0.48-usertrack.patch
deleted file mode 100644 (file)
index b224636..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-
-mod_usertrack fix from Manni Wood <manniwood planet-save.com>
-
-http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=113269
-
---- httpd-2.0.48/modules/metadata/mod_usertrack.c.usertrack
-+++ httpd-2.0.48/modules/metadata/mod_usertrack.c
-@@ -199,6 +199,20 @@
-  * which has three subexpressions, $0..$2 */
- #define NUM_SUBS 3
-+static void set_and_comp_regexp(cookie_dir_rec *dcfg, 
-+                                apr_pool_t *p,
-+                                const char *cookie_name) 
-+{
-+    /* The goal is to end up with this regexp, 
-+     * ^cookie_name=([^;]+)|;[\t]+cookie_name=([^;]+) 
-+     * with cookie_name obviously substituted either
-+     * with the real cookie name set by the user in httpd.conf, or with the
-+     * default COOKIE_NAME. */
-+    dcfg->regexp_string = apr_pstrcat(p, "^", cookie_name, "=([^;]+)|;[ \t]+", cookie_name, "=([^;]+)", NULL);
-+
-+    dcfg->regexp = ap_pregcomp(p, dcfg->regexp_string, REG_EXTENDED);
-+}
-+
- static int spot_cookie(request_rec *r)
- {
-     cookie_dir_rec *dcfg = ap_get_module_config(r->per_dir_config,
-@@ -260,6 +274,11 @@
-     dcfg->cookie_domain = NULL;
-     dcfg->style = CT_UNSET;
-     dcfg->enabled = 0;
-+
-+    /* In case the user does not use the CookieName directive,
-+     * we need to compile the regexp for the default cookie name. */
-+    set_and_comp_regexp(dcfg, p, COOKIE_NAME);
-+
-     return dcfg;
- }
-@@ -345,18 +364,10 @@
- {
-     cookie_dir_rec *dcfg = (cookie_dir_rec *) mconfig;
--    /* The goal is to end up with this regexp,
--     * ^cookie_name=([^;]+)|;[ \t]+cookie_name=([^;]+)
--     * with cookie_name
--     * obviously substituted with the real cookie name set by the
--     * user in httpd.conf. */
--    dcfg->regexp_string = apr_pstrcat(cmd->pool, "^", name,
--                                      "=([^;]+)|;[ \t]+", name,
--                                      "=([^;]+)", NULL);
--
-     dcfg->cookie_name = apr_pstrdup(cmd->pool, name);
--    dcfg->regexp = ap_pregcomp(cmd->pool, dcfg->regexp_string, REG_EXTENDED);
-+    set_and_comp_regexp(dcfg, cmd->pool, name);
-+
-     if (dcfg->regexp == NULL) {
-         return "Regular expression could not be compiled.";
-     }
diff --git a/httpd-2.0.48-worker.patch b/httpd-2.0.48-worker.patch
deleted file mode 100644 (file)
index f255412..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-
-- pod cleanup
-- fix for potential parent segfault (Jeff Trawick)
-
---- httpd-2.0.48/server/mpm/worker/pod.c.worker
-+++ httpd-2.0.48/server/mpm/worker/pod.c
-@@ -105,31 +105,13 @@
-     return AP_NORESTART;
- }
--AP_DECLARE(apr_status_t) ap_mpm_pod_close(ap_pod_t *pod)
--{
--    apr_status_t rv;
--
--    rv = apr_file_close(pod->pod_out);
--    if (rv != APR_SUCCESS) {
--        return rv;
--    }
--
--    rv = apr_file_close(pod->pod_in);
--    if (rv != APR_SUCCESS) {
--        return rv;
--    }
--    return rv;
--}
--
- static apr_status_t pod_signal_internal(ap_pod_t *pod, int graceful)
- {
-     apr_status_t rv;
-     char char_of_death = graceful ? GRACEFUL_CHAR : RESTART_CHAR;
-     apr_size_t one = 1;
--    do {
--        rv = apr_file_write(pod->pod_out, &char_of_death, &one);
--    } while (APR_STATUS_IS_EINTR(rv));
-+    rv = apr_file_write(pod->pod_out, &char_of_death, &one);
-     if (rv != APR_SUCCESS) {
-         ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf,
-                      "write pipe_of_death");
---- httpd-2.0.48/server/mpm/worker/worker.c.worker
-+++ httpd-2.0.48/server/mpm/worker/worker.c
-@@ -1483,6 +1483,7 @@
-             }
-         }
-         if (any_dead_threads && totally_free_length < idle_spawn_rate 
-+            && free_length < MAX_SPAWN_RATE
-                 && (!ps->pid               /* no process in the slot */
-                     || ps->quiescing)) {   /* or at least one is going away */
-             if (all_dead_threads) {
This page took 0.279677 seconds and 4 git commands to generate.