This commit was manufactured by cvs2svn to create tag
'APACHE_2_0_46'.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/tags/2.0.46@100062 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/CHANGES b/CHANGES
index 71628f7..f3cfb6c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,17 @@
 Changes with Apache 2.0.46
 
+  *) SECURITY [CAN-2003-0245]: Fixed a bug that could be triggered
+     remotely through mod_dav and possibly other mechanisms, causing
+     an Apache child process to crash.  The crash was first reported
+     by David Endler <DEndler@iDefense.com> and was researched and
+     fixed by Joe Orton <jorton@redhat.com>.  Details will be released
+     on 30 May 2003.
+
+  *) SECURITY [CAN-2003-0189]: Fixed a denial-of-service vulnerability
+     affecting basic authentication on Unix platforms related to
+     thread-safety in apr_password_validate().  The problem was reported
+     by John Hughes <john.hughes@entegrity.com>.
+
   *) Fix for mod_dav.  Call the 'can_be_activity' callback, if provided,
      when a MKACTIVITY request comes in.
      [Ben Collins-Sussman <sussman@collab.net>]
diff --git a/docs/manual/content-negotiation.html.en b/docs/manual/content-negotiation.html.en
index 937af96..9baa734 100644
--- a/docs/manual/content-negotiation.html.en
+++ b/docs/manual/content-negotiation.html.en
@@ -480,20 +480,6 @@
     specification and to work effectively with properly configured
     clients.</p>
 
-    <p>In order to support advanced techniques (such as Cookies or
-    special URL-paths) to determine the user's preferred language,
-    since Apache 2.0.46 <code class="module"><a href="./mod/mod_negotiation.html">mod_negotiation</a></code> recognizes
-    the <a href="env.html">environment variable</a>
-    <code>prefer-language</code>. If it exists and contains an
-    appropriate language tag, <code class="module"><a href="./mod/mod_negotiation.html">mod_negotiation</a></code> will
-    try to select a matching variant. If there's no such variant,
-    the normal negotiation process applies.</p>
-
-    <div class="example"><h3>Example</h3><p><code>
-      SetEnvIf Cookie "language=en" prefer-language=en
-      SetEnvIf Cookie "language=fr" prefer-language=fr
-   </code></p></div>
-
 </div><div class="top"><a href="#page-header"><img alt="top" src="./images/up.gif" /></a></div>
 <div class="section">
 <h2><a name="extensions" id="extensions">Extensions to Transparent Content
diff --git a/docs/manual/content-negotiation.xml b/docs/manual/content-negotiation.xml
index 0618696..ee7562b 100644
--- a/docs/manual/content-negotiation.xml
+++ b/docs/manual/content-negotiation.xml
@@ -465,20 +465,6 @@
     This is necessary to maintain compliance with the HTTP/1.1
     specification and to work effectively with properly configured
     clients.</p>
-
-    <p>In order to support advanced techniques (such as Cookies or
-    special URL-paths) to determine the user's preferred language,
-    since Apache 2.0.46 <module>mod_negotiation</module> recognizes
-    the <a href="env.html">environment variable</a>
-    <code>prefer-language</code>. If it exists and contains an
-    appropriate language tag, <module>mod_negotiation</module> will
-    try to select a matching variant. If there's no such variant,
-    the normal negotiation process applies.</p>
-
-    <example><title>Example</title>
-      SetEnvIf Cookie "language=en" prefer-language=en
-      SetEnvIf Cookie "language=fr" prefer-language=fr
-   </example>
 </section>
 </section>
 
diff --git a/docs/manual/env.html.en b/docs/manual/env.html.en
index 95ae3c8..6c37c2c 100644
--- a/docs/manual/env.html.en
+++ b/docs/manual/env.html.en
@@ -268,18 +268,6 @@
         <p>This disables <code class="directive"><a href="./mod/core.html#keepalive">KeepAlive</a></code> when set.</p>
     
     
-
-    <h3><a name="prefer-language" id="prefer-language">prefer-language</a></h3>
-    
-        <p>This influences <code class="module"><a href="./mod/mod_negotiation.html">mod_negotiation</a></code>'s behaviour. If
-        it contains a language tag (such as <code>en</code>, <code>ja</code>
-        or <code>x-klingon</code>), <code class="module"><a href="./mod/mod_negotiation.html">mod_negotiation</a></code> tries
-        to deliver a variant with that language. If there's no such variant,
-        the normal <a href="content-negotiation.html">negotiation</a> process
-        applies.</p>
-    
-    
-    
     <h3><a name="redirect-carefully" id="redirect-carefully">redirect-carefully</a></h3>
         
     
diff --git a/docs/manual/env.xml b/docs/manual/env.xml
index 58ae9cf..ded93dd 100644
--- a/docs/manual/env.xml
+++ b/docs/manual/env.xml
@@ -294,18 +294,6 @@
         <p>This disables <directive module="core">KeepAlive</directive> when set.</p>
     
     </section>
-
-    <section id="prefer-language"><title>prefer-language</title>
-    
-        <p>This influences <module>mod_negotiation</module>'s behaviour. If
-        it contains a language tag (such as <code>en</code>, <code>ja</code>
-        or <code>x-klingon</code>), <module>mod_negotiation</module> tries
-        to deliver a variant with that language. If there's no such variant,
-        the normal <a href="content-negotiation.html">negotiation</a> process
-        applies.</p>
-    
-    </section>
-    
     <section id="redirect-carefully">
         <title>redirect-carefully</title>
     
diff --git a/modules/mappers/mod_negotiation.c b/modules/mappers/mod_negotiation.c
index b486d6e..8f2670c 100644
--- a/modules/mappers/mod_negotiation.c
+++ b/modules/mappers/mod_negotiation.c
@@ -2202,134 +2202,74 @@
     return 1;
 }
 
-/* figure out, whether a variant is in a specific language
- * it returns also false, if the variant has no language.
- */
-static int variant_has_language(var_rec *variant, const char *lang)
-{
-    int j, max;
-
-    /* fast exit */
-    if (   !lang
-        || !variant->content_languages
-        || !(max = variant->content_languages->nelts)) {
-        return 0;
-    }
-
-    for (j = 0; j < max; ++j) {
-        if (!strcmp(lang,
-                    ((char **) (variant->content_languages->elts))[j])) {
-            return 1;
-        }
-    }
-
-    return 0;
-}
-
 static int best_match(negotiation_state *neg, var_rec **pbest)
 {
     int j;
-    var_rec *best;
+    var_rec *best = NULL;
     float bestq = 0.0f;
     enum algorithm_results algorithm_result;
 
     var_rec *avail_recs = (var_rec *) neg->avail_vars->elts;
 
-    const char *preferred_language = apr_table_get(neg->r->subprocess_env,
-                                                   "prefer-language");
-
     set_default_lang_quality(neg);
 
     /*
-     * Find the 'best' variant 
-     * We run the loop possibly twice: if "prefer-language"
-     * environment variable is set but we did not find an appropriate
-     * best variant. In that case forget the preferred language and
-     * negotiate over all variants.
+     * Find the 'best' variant
      */
 
-    do {
-        best = NULL;
+    for (j = 0; j < neg->avail_vars->nelts; ++j) {
+        var_rec *variant = &avail_recs[j];
 
-        for (j = 0; j < neg->avail_vars->nelts; ++j) {
-            var_rec *variant = &avail_recs[j];
+        /* Find all the relevant 'quality' values from the
+         * Accept... headers, and store in the variant.  This also
+         * prepares for sending an Alternates header etc so we need to
+         * do it even if we do not actually plan to find a best
+         * variant.
+         */
+        set_accept_quality(neg, variant);
+        set_language_quality(neg, variant);
+        set_encoding_quality(neg, variant);
+        set_charset_quality(neg, variant);
 
-            /* if a language is preferred, but the current variant
-             * is not in that language, then drop it for now
-             */
-            if (   preferred_language
-                && !variant_has_language(variant, preferred_language)) {
-                continue;
-            }
+        /* Only do variant selection if we may actually choose a
+         * variant for the client
+         */
+        if (neg->may_choose) {
 
-            /* Find all the relevant 'quality' values from the
-             * Accept... headers, and store in the variant.  This also
-             * prepares for sending an Alternates header etc so we need to
-             * do it even if we do not actually plan to find a best
-             * variant.  
+            /* Now find out if this variant is better than the current
+             * best, either using the RVSA/1.0 algorithm, or Apache's
+             * internal server-driven algorithm. Presumably other
+             * server-driven algorithms are possible, and could be
+             * implemented here.
              */
-            set_accept_quality(neg, variant);
-            /* accept the preferred language, even when it's not listed within
-             * the Accept-Language header
-             */
-            if (preferred_language) {
-                variant->lang_quality = 1.0f;
-                variant->definite = 1;
+
+            if (neg->use_rvsa) {
+                if (is_variant_better_rvsa(neg, variant, best, &bestq)) {
+                    best = variant;
+                }
             }
             else {
-                set_language_quality(neg, variant);
-            }
-            set_encoding_quality(neg, variant);
-            set_charset_quality(neg, variant);
-
-            /* Only do variant selection if we may actually choose a
-             * variant for the client 
-             */
-            if (neg->may_choose) {
-
-                /* Now find out if this variant is better than the current
-                 * best, either using the RVSA/1.0 algorithm, or Apache's
-                 * internal server-driven algorithm. Presumably other
-                 * server-driven algorithms are possible, and could be
-                 * implemented here.
-                 */
-     
-                if (neg->use_rvsa) {
-                    if (is_variant_better_rvsa(neg, variant, best, &bestq)) {
-                        best = variant;
-                    }
-                }
-                else {
-                    if (is_variant_better(neg, variant, best, &bestq)) {
-                        best = variant;
-                    }
+                if (is_variant_better(neg, variant, best, &bestq)) {
+                    best = variant;
                 }
             }
         }
+    }
 
-        /* We now either have a best variant, or no best variant */
+    /* We now either have a best variant, or no best variant */
 
-        if (neg->use_rvsa)    {
-            /* calculate result for RVSA/1.0 algorithm:
-             * only a choice response if the best variant has q>0
-             * and is definite
-             */
-            algorithm_result = (best && best->definite) && (bestq > 0) ?
-                                alg_choice : alg_list;
-        }
-        else {
-            /* calculate result for Apache negotiation algorithm */
-            algorithm_result = bestq > 0 ? alg_choice : alg_list;        
-        }
-
-        /* run the loop again, if the "prefer-language" got no clear result */
-        if (preferred_language && (!best || algorithm_result != alg_choice)) {
-            preferred_language = NULL;
-            continue;
-        }
-
-        break;
-    } while (1);
+    if (neg->use_rvsa)    {
+        /* calculate result for RVSA/1.0 algorithm:
+         * only a choice response if the best variant has q>0
+         * and is definite
+         */
+        algorithm_result = (best && best->definite) && (bestq > 0) ?
+                           alg_choice : alg_list;
+    }
+    else {
+        /* calculate result for Apache negotiation algorithm */
+        algorithm_result = bestq > 0 ? alg_choice : alg_list;
+    }
 
     /* Returning a choice response with a non-neighboring variant is a
      * protocol security error in TCN (see rfc2295).  We do *not*
diff --git a/modules/metadata/mod_expires.c b/modules/metadata/mod_expires.c
index 64fdb0c..e35e554 100644
--- a/modules/metadata/mod_expires.c
+++ b/modules/metadata/mod_expires.c
@@ -212,11 +212,6 @@
     apr_table_t *expiresbytype;
 } expires_dir_config;
 
-typedef struct {
-    int defaulted;
-    apr_table_t *expfields;
-} expires_interphase_t;
-
 /* from mod_dir, why is this alias used?
  */
 #define DIR_CMD_PERMS OR_INDEXES
@@ -421,23 +416,59 @@
     return new;
 }
 
-/*
- * Handle the setting of the expiration response header fields according
- * to our criteria.
- */
-
-static int set_expiration_fields(request_rec *r, const char *code,
-                                 apr_table_t *t)
+static int add_expires(request_rec *r)
 {
+    expires_dir_config *conf;
+    char *code;
     apr_time_t base;
     apr_time_t additional;
     apr_time_t expires;
     int additional_sec;
     char *timestr;
-    expires_interphase_t *notes;
 
-    notes = (expires_interphase_t *) ap_get_module_config(r->request_config,
-                                                          &expires_module);
+    if (ap_is_HTTP_ERROR(r->status))       /* Don't add Expires headers to errors */
+        return DECLINED;
+
+    if (r->main != NULL)        /* Say no to subrequests */
+        return DECLINED;
+
+    conf = (expires_dir_config *) ap_get_module_config(r->per_dir_config, &expires_module);
+    if (conf == NULL) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                    "internal error: %s", r->filename);
+        return HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    if (conf->active != ACTIVE_ON)
+        return DECLINED;
+
+    /* we perhaps could use the default_type(r) in its place but that
+     * may be 2nd guesing the desired configuration...  calling table_get
+     * with a NULL key will SEGV us
+     *
+     * I still don't know *why* r->content_type would ever be NULL, this
+     * is possibly a result of fixups being called in many different
+     * places.  Fixups is probably the wrong place to be doing all this
+     * work...  Bah.
+     *
+     * Changed as of 08.Jun.96 don't DECLINE, look for an ExpiresDefault.
+     */
+    if (r->content_type == NULL)
+        code = NULL;
+    else
+        code = (char *) apr_table_get(conf->expiresbytype, 
+		ap_field_noparam(r->pool, r->content_type));
+
+    if (code == NULL) {
+        /* no expires defined for that type, is there a default? */
+        code = conf->expiresdefault;
+
+        if (code[0] == '\0')
+            return OK;
+    }
+
+    /* we have our code */
+
     switch (code[0]) {
     case 'M':
 	if (r->finfo.filetype == 0) { 
@@ -468,143 +499,17 @@
     }
 
     expires = base + additional;
-    apr_table_mergen(t, "Cache-Control",
-                     apr_psprintf(r->pool, "max-age=%" APR_TIME_T_FMT,
-                                  apr_time_sec(expires - r->request_time)));
+    apr_table_mergen(r->headers_out, "Cache-Control",
+		    apr_psprintf(r->pool, "max-age=%" APR_TIME_T_FMT,
+                                 apr_time_sec(expires - r->request_time)));
     timestr = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
     apr_rfc822_date(timestr, expires);
-    apr_table_setn(t, "Expires", timestr);
+    apr_table_setn(r->headers_out, "Expires", timestr);
     return OK;
 }
 
-/*
- * Output filter to set the Expires response header field
- * according to the content-type of the response -- if it hasn't
- * already been set.
- */
-static apr_status_t expires_by_type_filter(ap_filter_t *f,
-                                           apr_bucket_brigade *b)
-{
-    request_rec *r;
-    expires_dir_config *conf;
-    expires_interphase_t *notes;
-    const char *bytype_expiry;
-    apr_table_t *t;
-
-    r = f->r;
-    conf = (expires_dir_config *) ap_get_module_config(r->per_dir_config,
-                                                       &expires_module);
-    notes = (expires_interphase_t *) ap_get_module_config(r->request_config,
-                                                          &expires_module);
-
-    /*
-     * If this filter is getting called, it *should* mean that
-     * the fixup-phase handler ran and set things up for us.
-     * Check to see which output header table we should use;
-     * mod_cgi loads script fields into r->err_headers_out,
-     * for instance.
-     */
-    bytype_expiry = apr_table_get(r->err_headers_out, "Expires");
-    if (bytype_expiry != NULL) {
-        t = r->err_headers_out;
-    }
-    else {
-        bytype_expiry = apr_table_get(r->headers_out, "Expires");
-        t = r->headers_out;
-    }
-    if (bytype_expiry == NULL) {
-        /*
-         * No expiration has been set, so we can apply any managed by
-         * this module.  Check for one for this content type.
-         */
-        bytype_expiry = apr_table_get(conf->expiresbytype,
-                                      ap_field_noparam(r->pool,
-                                                       r->content_type));
-        if (bytype_expiry != NULL) {
-            set_expiration_fields(r, bytype_expiry, t);
-        }
-        else if ((notes != NULL) && notes->defaulted) {
-            /*
-             * None for this type, but there was a default defined --
-             * so use it.
-             */
-            t = apr_table_overlay(r->pool, notes->expfields, t);
-        }
-    }
-    ap_remove_output_filter(f);
-    return ap_pass_brigade(f->next, b);
-}
-
-static int add_expires(request_rec *r)
-{
-    expires_dir_config *conf;
-    expires_interphase_t *notes;
-    apr_table_t *rfields;
-    char *code;
-
-    if (ap_is_HTTP_ERROR(r->status)) {/* Don't add Expires headers to errors */
-        return DECLINED;
-    }
-
-    if (r->main != NULL) {      /* Say no to subrequests */
-        return DECLINED;
-    }
-
-    conf = (expires_dir_config *) ap_get_module_config(r->per_dir_config,
-                                                       &expires_module);
-    if (conf == NULL) {
-        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                    "internal error: %s", r->filename);
-        return HTTP_INTERNAL_SERVER_ERROR;
-    }
-
-    if (conf->active != ACTIVE_ON) {
-        return DECLINED;
-    }
-
-    notes = apr_palloc(r->pool, sizeof(expires_interphase_t));
-    notes->defaulted = 0;
-    notes->expfields = apr_table_make(r->pool, 4);
-    ap_set_module_config(r->request_config, &expires_module, notes);
-
-    /*
-     * If there are any ExpiresByType directives for this scope,
-     * add the output filter and defer all setting to it.  We
-     * do make a note of any ExpiresDefault value for its use.
-     */
-    if (! apr_is_empty_table(conf->expiresbytype)) {
-        ap_add_output_filter("MOD_EXPIRES", NULL, r, r->connection);
-        rfields = notes->expfields;
-    }
-    else {
-        rfields = r->headers_out;
-    }
-    /*
-     * Apply the default expiration if there is one; the filter will
-     * narrow it down later if possible.
-     */
-    code = conf->expiresdefault;
-
-    if (code[0] == '\0') {
-        return OK;
-    }
-    else {
-        /*
-         * Note that we're setting it from the default, so that
-         * the output filter (if it runs) knows it can override the
-         * value.  This allows the by-type filter to be able to
-         * tell the difference between a value set by, say, a
-         * CGI script and the one we set by default.
-         */
-        notes->defaulted = 1;
-    }
-    return set_expiration_fields(r, code, rfields);
-}
-
 static void register_hooks(apr_pool_t *p)
 {
-    ap_register_output_filter("MOD_EXPIRES", expires_by_type_filter, NULL,
-                              AP_FTYPE_CONTENT_SET);
     ap_hook_fixups(add_expires,NULL,NULL,APR_HOOK_MIDDLE);
 }