You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by nd...@apache.org on 2003/01/28 03:31:28 UTC
cvs commit: httpd-2.0/modules/mappers mod_negotiation.c
nd 2003/01/27 18:31:27
Modified: . CHANGES
modules/mappers mod_negotiation.c
Log:
Introduce "prefer-language" environment variable,
which allows to influence the negotiation process on request basis
to prefer a certain language, e.g.:
SetEnvIf Request_URI ^/manual/foo/ prefer-language=foo
Revision Changes Path
1.1039 +4 -0 httpd-2.0/CHANGES
Index: CHANGES
===================================================================
RCS file: /home/cvs/httpd-2.0/CHANGES,v
retrieving revision 1.1038
retrieving revision 1.1039
diff -u -r1.1038 -r1.1039
--- CHANGES 27 Jan 2003 17:49:03 -0000 1.1038
+++ CHANGES 28 Jan 2003 02:31:24 -0000 1.1039
@@ -2,6 +2,10 @@
[Remove entries to the current 2.0 section below, when backported]
+ *) mod_negotiation: Introduce "prefer-language" environment variable,
+ which allows to influence the negotiation process on request basis
+ to prefer a certain language. [Andr� Malo]
+
*) Added AllowEncodedSlashes directive which permits request URIs
to encode '/' as '%2f' and pass it to scripts in path-info without
triggering the 'no encoded slashes anywhere' legacy rule.
1.110 +96 -45 httpd-2.0/modules/mappers/mod_negotiation.c
Index: mod_negotiation.c
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/mappers/mod_negotiation.c,v
retrieving revision 1.109
retrieving revision 1.110
diff -u -r1.109 -r1.110
--- mod_negotiation.c 25 Nov 2002 19:02:44 -0000 1.109
+++ mod_negotiation.c 28 Jan 2003 02:31:27 -0000 1.110
@@ -2185,74 +2185,125 @@
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 = NULL;
+ var_rec *best;
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.
*/
- for (j = 0; j < neg->avail_vars->nelts; ++j) {
- var_rec *variant = &avail_recs[j];
+ do {
+ best = NULL;
+
+ for (j = 0; j < neg->avail_vars->nelts; ++j) {
+ var_rec *variant = &avail_recs[j];
+
+ /* 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;
+ }
+
+ /* 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);
- /* 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);
-
- /* 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.
+ /* 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;
+ 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;
+ else {
+ 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;
- }
+ 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);
/* Returning a choice response with a non-neighboring variant is a
* protocol security error in TCN (see rfc2295). We do *not*