You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by David Young <dy...@nettonettech.com> on 2002/03/21 18:51:41 UTC

[PATCH] implement ForceLanguagePriority in 1.3

Implements the ForceLanguagePriority directive from 2.0.32 in 1.3.23
ftp://ftp.nettonettech.com/download/mod_negotiation.patch

---------------------------------------------------------------------

--- mod_negotiation-old.c    Thu Mar 21 12:30:16 2002
+++ mod_negotiation.c    Thu Mar 21 12:32:39 2002
@@ -76,16 +76,28 @@
  */
 
 typedef struct {
+    int forcelangpriority;
     array_header *language_priority;
 } neg_dir_config;
 
+/* forcelangpriority flags
+ */
+#define FLP_UNDEF    0    /* Same as FLP_DEFAULT, but base overrides */
+#define FLP_NONE     1    /* Return 406, HTTP_NOT_ACCEPTABLE */
+#define FLP_PREFER   2    /* Use language_priority rather than MC */
+#define FLP_FALLBACK 4    /* Use language_priority rather than NA */
+
+#define FLP_DEFAULT  FLP_PREFER
+
 module MODULE_VAR_EXPORT negotiation_module;
 
 static void *create_neg_dir_config(pool *p, char *dummy)
 {
     neg_dir_config *new = (neg_dir_config *) ap_palloc(p,
sizeof(neg_dir_config));
-
-    new->language_priority = ap_make_array(p, 4, sizeof(char *));
+    
+    new->forcelangpriority = FLP_UNDEF;
+    new->language_priority = NULL;
+    
     return new;
 }
 
@@ -96,17 +108,54 @@
     neg_dir_config *new = (neg_dir_config *) ap_palloc(p,
sizeof(neg_dir_config));
 
     /* give priority to the config in the subdirectory */
-    new->language_priority = ap_append_arrays(p, add->language_priority,
-                                           base->language_priority);
+    new->forcelangpriority = (add->forcelangpriority != FLP_UNDEF)
+                ? add->forcelangpriority
+                : base->forcelangpriority;
+    new->language_priority = add->language_priority
+                ? add->language_priority
+                                : base->language_priority;
     return new;
 }
 
-static const char *set_language_priority(cmd_parms *cmd, void *n, char
*lang)
+static const char *set_language_priority(cmd_parms *cmd, void *n_, const
char *lang)
 {
-    array_header *arr = ((neg_dir_config *) n)->language_priority;
-    char **langp = (char **) ap_push_array(arr);
+    neg_dir_config *n = n_;
+    const char **langp;
+
+    if (!n->language_priority)
+        n->language_priority = ap_make_array(cmd->pool, 4, sizeof(char *));
+
+    langp = (const char **) ap_push_array(n->language_priority);
+    *langp = lang;
+    return NULL;
+}
+
+static const char *set_force_priority(cmd_parms *cmd, void *n_, const char
*w)
+{
+    neg_dir_config *n = n_;
+  
+    if (!strcasecmp(w, "None")) {
+        if (n->forcelangpriority & ~FLP_NONE) {
+        return "Cannot combine ForceLanguagePriority options with None";
+        }
+    n->forcelangpriority = FLP_NONE;
+    }
+    else if (!strcasecmp(w, "Prefer")) {
+        if (n->forcelangpriority & FLP_NONE) {
+        return "Cannot combine ForceLanguagePriority options None and
Prefer";
+        }
+        n->forcelangpriority |= FLP_PREFER;
+    }
+    else if (!strcasecmp(w, "Fallback")) {
+        if (n->forcelangpriority & FLP_NONE) {
+        return "Cannot combine ForceLanguagePriority options None and
Fallback";
+        }
+        n->forcelangpriority |= FLP_FALLBACK;
+    }
+    else {
+        return ap_pstrcat(cmd->pool, "Invalid ForceLanguagePriority option
", w, NULL);
+    }
 
-    *langp = lang;
     return NULL;
 }
 
@@ -130,6 +179,8 @@
      "no arguments (either present or absent)"},
     {"LanguagePriority", set_language_priority, NULL, OR_FILEINFO, ITERATE,
      "space-delimited list of MIME language abbreviations"},
+    {"ForceLanguagePriority", set_force_priority, NULL, OR_FILEINFO,
ITERATE,
+     "Force LanguagePriority elections, either None, or Fallback and/or
Prefer"},
     {NULL}
 };
 
@@ -211,6 +262,7 @@
 typedef struct {
     pool *pool;
     request_rec *r;
+    neg_dir_config *conf;
     char *dir_name;
     int accept_q;               /* 1 if an Accept item has a q= param */
     float default_lang_quality; /* fiddle lang q for variants with no lang
*/
@@ -475,6 +527,10 @@
 
     new->pool = r->pool;
     new->r = r;
+
+    new->conf = (neg_dir_config *)ap_get_module_config(r->per_dir_config,
+                  
&negotiation_module);
+
     new->dir_name = ap_make_dirstr_parent(r->pool, r->filename);
 
     new->accepts = do_header_line(r->pool, ap_table_get(hdrs, "Accept"));
@@ -1219,48 +1275,21 @@
 
 static int find_lang_index(array_header *accept_langs, char *lang)
 {
-    accept_rec *accs;
+    const char **alang;
     int i;
 
     if (!lang || !accept_langs) {
         return -1;
     }
 
-    accs = (accept_rec *) accept_langs->elts;
+    alang = (const char **) accept_langs->elts;
 
     for (i = 0; i < accept_langs->nelts; ++i) {
-        if (!strncmp(lang, accs[i].name, strlen(accs[i].name))) {
-            return i;
-        }
-    }
-
-    return -1;
-}
-
-/* This function returns the priority of a given language
- * according to LanguagePriority.  It is used in case of a tie
- * between several languages.
- */
 
-static int find_default_index(neg_dir_config *conf, char *lang)
-{
-    array_header *arr;
-    int nelts;
-    char **elts;
-    int i;
-
-    if (!lang) {
-        return -1;
-    }
-
-    arr = conf->language_priority;
-    nelts = arr->nelts;
-    elts = (char **) arr->elts;
-
-    for (i = 0; i < nelts; ++i) {
-        if (!strcasecmp(elts[i], lang)) {
+        if (!strncmp(lang, *alang, strlen(*alang))) {
             return i;
         }
+        alang += (accept_langs->elt_size / sizeof(char*));
     }
 
     return -1;
@@ -1301,7 +1330,7 @@
 }
 
 /* Set the language_quality value in the variant record. Also
- * assigns lang_index for back-compat.
+ * assigns lang_index for ForceLanguagePriority.
  *
  * To find the language_quality value, we look for the 'q' value
  * of the 'best' matching language on the Accept-Language
@@ -1333,8 +1362,11 @@
 
 static void set_language_quality(negotiation_state *neg, var_rec *variant)
 {
-    char *firstlang;
-    int idx;
+
+    int forcepriority = neg->conf->forcelangpriority;
+    if (forcepriority == FLP_UNDEF) {
+        forcepriority = FLP_DEFAULT;
+    }
 
     if (!variant->content_languages || !variant->content_languages->nelts)
{
         /* This variant has no content-language, so use the default
@@ -1349,9 +1381,9 @@
         if (!neg->accept_langs) {
             return;             /* no accept-language header */
         }
-
+        return;
     }
-    else {
+    else { 
         /* Variant has one (or more) languages.  Look for the best
          * match. We do this by going through each language on the
          * variant description looking for a match on the
@@ -1363,7 +1395,7 @@
 
         if (!neg->accept_langs) {
             /* no accept-language header makes the variant indefinite */
-            variant->definite = 0;
+            variant->definite = 0;
         }
         else {    /* There is an accept-language with 0 or more items */
             accept_rec *accs = (accept_rec *) neg->accept_langs->elts;
@@ -1484,27 +1516,53 @@
         }
     }
 
-    /* Now set the old lang_index field. Since this is old
-     * stuff anyway, don't bother with handling multiple languages
-     * per variant, just use the first one assigned to it
+    /* Handle the ForceDefaultLanguage overrides, based on the best match
+     * to LanguagePriority order.  The best match is the lowest index of
+     * any LanguagePriority match.
      */
-    idx = 0;
-    if (variant->content_languages && variant->content_languages->nelts) {
-        firstlang = ((char **) variant->content_languages->elts)[0];
-    }
-    else {
-        firstlang = "";
-    }
-    if (!neg->accept_langs) {   /* Client doesn't care */
-        idx = find_default_index((neg_dir_config *) ap_get_module_config(
-                                  neg->r->per_dir_config,
&negotiation_module),
-                                 firstlang);
-    }
-    else {                      /* Client has Accept-Language */
-        idx = find_lang_index(neg->accept_langs, firstlang);
-    }
-    variant->lang_index = idx;
+    if (((forcepriority & FLP_PREFER)
+             && (variant->lang_index < 0))
+     || ((forcepriority & FLP_FALLBACK)
+             && !variant->lang_quality))
+    {
+        int bestidx = -1;
+        int j;
+
+        for (j = 0; j < variant->content_languages->nelts; ++j)
+        {
+            /* lang is the variant's language-tag, which is the one
+             * we are allowed to use the prefix of in HTTP/1.1
+             */
+            char *lang = ((char **) (variant->content_languages->elts))[j];
+            int idx = -1;
+      
+            /* If we wish to fallback or
+             * we use our own LanguagePriority index.
+             */   
+             
+            idx = find_lang_index(neg->conf->language_priority, lang);
+              
+            if ((idx >= 0) && ((bestidx == -1) || (idx < bestidx))) {
+                bestidx = idx;
+            }
+        }
 
+        if (bestidx >= 0) {
+            if (variant->lang_quality) {
+                if (forcepriority & FLP_PREFER) {
+                    variant->lang_index = bestidx;
+                }
+            }
+            else {
+                if (forcepriority & FLP_FALLBACK) {
+                    variant->lang_index = bestidx;
+                    variant->lang_quality = .0001f;
+                    variant->definite = 0;
+                }
+            }
+        }
+    }
+    
     return;
 }
 


Re: [PATCH] implement ForceLanguagePriority in 1.3

Posted by "William A. Rowe, Jr." <wr...@rowe-clan.net>.
At 07:58 AM 4/18/2002, William A. Rowe, Jr. wrote:
>At 08:08 PM 4/17/2002, David Young wrote:
>>
>>How about adding it to contrib then?
>
>+1
>
>Renamed for clarity to force_language_priority.patch.  Changed header
>to reflect a cvs diff.
>
>Copied to http://www.apache.org/dist/httpd/patches/apply_to_1.3.24/

Whoops.  Make that http://www.apache.org/dist/httpd/contrib/patches/1.3/

And thank you once again.



Re: [PATCH] implement ForceLanguagePriority in 1.3

Posted by "William A. Rowe, Jr." <wr...@rowe-clan.net>.
At 08:08 PM 4/17/2002, David Young wrote:
>From: "William A. Rowe, Jr." <wr...@rowe-clan.net>
> >> Any chance of getting this patch implemented in a future 1.3.x release?
> >
> > As the author of that patch for 2.0 ... I have to suggest no.
>
>How about adding it to contrib then?

+1

Renamed for clarity to force_language_priority.patch.  Changed header
to reflect a cvs diff.

Copied to http://www.apache.org/dist/httpd/patches/apply_to_1.3.24/

Thanks for the contribution!





Re: [PATCH] implement ForceLanguagePriority in 1.3

Posted by "William A. Rowe, Jr." <wr...@rowe-clan.net>.
At 01:01 PM 4/17/2002, you wrote:

>Any chance of getting this patch implemented in a future 1.3.x release?

As the author of that patch for 2.0 ... I have to suggest no.  Many other
interrelated changes have gone into 2.0's negotiation and other entangled
modules.  Changing that back in 1.3 is not trivial.  I have no time to invest,
and any effort would require the vetting that many invested in reviewing and
chasing out bugs in my code.

We are treating 1.3.25 as a VERY stable code point.  Destabilizing features
will almost certainly be vetoed by the developer community.  The cost to
the development of the Apache 2.0 code base every time we have to untangle
changes and bugs in the 1.3 tree is not appealing to the project contributors.

Sorry, but glad you enjoy the feature, and hope to see you adopt Apache 2.0
if that (and many of the other new features) are valuable to you.

Bill


[PATCH] implement ForceLanguagePriority in 1.3

Posted by David Young <dy...@nettonet.com>.
Any chance of getting this patch implemented in a future 1.3.x release?


----------
From: David Young <dy...@nettonettech.com>
Reply-To: dev@httpd.apache.org
Date: Thu, 21 Mar 2002 12:51:41 -0500
To: <de...@httpd.apache.org>
Subject: [PATCH] implement ForceLanguagePriority in 1.3

Implements the ForceLanguagePriority directive from 2.0.32 in 1.3.23

ftp://ftp.nettonettech.com/download/mod_negotiation.patch

---------------------------------------------------------------------

--- mod_negotiation-old.c    Thu Mar 21 12:30:16 2002
+++ mod_negotiation.c    Thu Mar 21 12:32:39 2002
@@ -76,16 +76,28 @@
  */
 
 typedef struct {
+    int forcelangpriority;
     array_header *language_priority;
 } neg_dir_config;
 
+/* forcelangpriority flags
+ */
+#define FLP_UNDEF    0    /* Same as FLP_DEFAULT, but base overrides */
+#define FLP_NONE     1    /* Return 406, HTTP_NOT_ACCEPTABLE */
+#define FLP_PREFER   2    /* Use language_priority rather than MC */
+#define FLP_FALLBACK 4    /* Use language_priority rather than NA */
+
+#define FLP_DEFAULT  FLP_PREFER
+
 module MODULE_VAR_EXPORT negotiation_module;
 
 static void *create_neg_dir_config(pool *p, char *dummy)
 {
     neg_dir_config *new = (neg_dir_config *) ap_palloc(p,
sizeof(neg_dir_config));
-
-    new->language_priority = ap_make_array(p, 4, sizeof(char *));
+    
+    new->forcelangpriority = FLP_UNDEF;
+    new->language_priority = NULL;
+    
     return new;
 }
 
@@ -96,17 +108,54 @@
     neg_dir_config *new = (neg_dir_config *) ap_palloc(p,
sizeof(neg_dir_config));
 
     /* give priority to the config in the subdirectory */
-    new->language_priority = ap_append_arrays(p, add->language_priority,
-                                           base->language_priority);
+    new->forcelangpriority = (add->forcelangpriority != FLP_UNDEF)
+                ? add->forcelangpriority
+                : base->forcelangpriority;
+    new->language_priority = add->language_priority
+                ? add->language_priority
+                                : base->language_priority;
     return new;
 }
 
-static const char *set_language_priority(cmd_parms *cmd, void *n, char
*lang)
+static const char *set_language_priority(cmd_parms *cmd, void *n_, const
char *lang)
 {
-    array_header *arr = ((neg_dir_config *) n)->language_priority;
-    char **langp = (char **) ap_push_array(arr);
+    neg_dir_config *n = n_;
+    const char **langp;
+
+    if (!n->language_priority)
+        n->language_priority = ap_make_array(cmd->pool, 4, sizeof(char *));
+
+    langp = (const char **) ap_push_array(n->language_priority);
+    *langp = lang;
+    return NULL;
+}
+
+static const char *set_force_priority(cmd_parms *cmd, void *n_, const char
*w)
+{
+    neg_dir_config *n = n_;
+  
+    if (!strcasecmp(w, "None")) {
+        if (n->forcelangpriority & ~FLP_NONE) {
+        return "Cannot combine ForceLanguagePriority options with None";
+        }
+    n->forcelangpriority = FLP_NONE;
+    }
+    else if (!strcasecmp(w, "Prefer")) {
+        if (n->forcelangpriority & FLP_NONE) {
+        return "Cannot combine ForceLanguagePriority options None and
Prefer";
+        }
+        n->forcelangpriority |= FLP_PREFER;
+    }
+    else if (!strcasecmp(w, "Fallback")) {
+        if (n->forcelangpriority & FLP_NONE) {
+        return "Cannot combine ForceLanguagePriority options None and
Fallback";
+        }
+        n->forcelangpriority |= FLP_FALLBACK;
+    }
+    else {
+        return ap_pstrcat(cmd->pool, "Invalid ForceLanguagePriority option
", w, NULL);
+    }
 
-    *langp = lang;
     return NULL;
 }
 
@@ -130,6 +179,8 @@
      "no arguments (either present or absent)"},
     {"LanguagePriority", set_language_priority, NULL, OR_FILEINFO, ITERATE,
      "space-delimited list of MIME language abbreviations"},
+    {"ForceLanguagePriority", set_force_priority, NULL, OR_FILEINFO,
ITERATE,
+     "Force LanguagePriority elections, either None, or Fallback and/or
Prefer"},
     {NULL}
 };
 
@@ -211,6 +262,7 @@
 typedef struct {
     pool *pool;
     request_rec *r;
+    neg_dir_config *conf;
     char *dir_name;
     int accept_q;               /* 1 if an Accept item has a q= param */
     float default_lang_quality; /* fiddle lang q for variants with no lang
*/
@@ -475,6 +527,10 @@
 
     new->pool = r->pool;
     new->r = r;
+
+    new->conf = (neg_dir_config *)ap_get_module_config(r->per_dir_config,
+                  
&negotiation_module);
+
     new->dir_name = ap_make_dirstr_parent(r->pool, r->filename);
 
     new->accepts = do_header_line(r->pool, ap_table_get(hdrs, "Accept"));
@@ -1219,48 +1275,21 @@
 
 static int find_lang_index(array_header *accept_langs, char *lang)
 {
-    accept_rec *accs;
+    const char **alang;
     int i;
 
     if (!lang || !accept_langs) {
         return -1;
     }
 
-    accs = (accept_rec *) accept_langs->elts;
+    alang = (const char **) accept_langs->elts;
 
     for (i = 0; i < accept_langs->nelts; ++i) {
-        if (!strncmp(lang, accs[i].name, strlen(accs[i].name))) {
-            return i;
-        }
-    }
-
-    return -1;
-}
-
-/* This function returns the priority of a given language
- * according to LanguagePriority.  It is used in case of a tie
- * between several languages.
- */
 
-static int find_default_index(neg_dir_config *conf, char *lang)
-{
-    array_header *arr;
-    int nelts;
-    char **elts;
-    int i;
-
-    if (!lang) {
-        return -1;
-    }
-
-    arr = conf->language_priority;
-    nelts = arr->nelts;
-    elts = (char **) arr->elts;
-
-    for (i = 0; i < nelts; ++i) {
-        if (!strcasecmp(elts[i], lang)) {
+        if (!strncmp(lang, *alang, strlen(*alang))) {
             return i;
         }
+        alang += (accept_langs->elt_size / sizeof(char*));
     }
 
     return -1;
@@ -1301,7 +1330,7 @@
 }
 
 /* Set the language_quality value in the variant record. Also
- * assigns lang_index for back-compat.
+ * assigns lang_index for ForceLanguagePriority.
  *
  * To find the language_quality value, we look for the 'q' value
  * of the 'best' matching language on the Accept-Language
@@ -1333,8 +1362,11 @@
 
 static void set_language_quality(negotiation_state *neg, var_rec *variant)
 {
-    char *firstlang;
-    int idx;
+
+    int forcepriority = neg->conf->forcelangpriority;
+    if (forcepriority == FLP_UNDEF) {
+        forcepriority = FLP_DEFAULT;
+    }
 
     if (!variant->content_languages || !variant->content_languages->nelts)
{
         /* This variant has no content-language, so use the default
@@ -1349,9 +1381,9 @@
         if (!neg->accept_langs) {
             return;             /* no accept-language header */
         }
-
+        return;
     }
-    else {
+    else { 
         /* Variant has one (or more) languages.  Look for the best
          * match. We do this by going through each language on the
          * variant description looking for a match on the
@@ -1363,7 +1395,7 @@
 
         if (!neg->accept_langs) {
             /* no accept-language header makes the variant indefinite */
-            variant->definite = 0;
+            variant->definite = 0;
         }
         else {    /* There is an accept-language with 0 or more items */
             accept_rec *accs = (accept_rec *) neg->accept_langs->elts;
@@ -1484,27 +1516,53 @@
         }
     }
 
-    /* Now set the old lang_index field. Since this is old
-     * stuff anyway, don't bother with handling multiple languages
-     * per variant, just use the first one assigned to it
+    /* Handle the ForceDefaultLanguage overrides, based on the best match
+     * to LanguagePriority order.  The best match is the lowest index of
+     * any LanguagePriority match.
      */
-    idx = 0;
-    if (variant->content_languages && variant->content_languages->nelts) {
-        firstlang = ((char **) variant->content_languages->elts)[0];
-    }
-    else {
-        firstlang = "";
-    }
-    if (!neg->accept_langs) {   /* Client doesn't care */
-        idx = find_default_index((neg_dir_config *) ap_get_module_config(
-                                  neg->r->per_dir_config,
&negotiation_module),
-                                 firstlang);
-    }
-    else {                      /* Client has Accept-Language */
-        idx = find_lang_index(neg->accept_langs, firstlang);
-    }
-    variant->lang_index = idx;
+    if (((forcepriority & FLP_PREFER)
+             && (variant->lang_index < 0))
+     || ((forcepriority & FLP_FALLBACK)
+             && !variant->lang_quality))
+    {
+        int bestidx = -1;
+        int j;
+
+        for (j = 0; j < variant->content_languages->nelts; ++j)
+        {
+            /* lang is the variant's language-tag, which is the one
+             * we are allowed to use the prefix of in HTTP/1.1
+             */
+            char *lang = ((char **) (variant->content_languages->elts))[j];
+            int idx = -1;
+      
+            /* If we wish to fallback or
+             * we use our own LanguagePriority index.
+             */   
+             
+            idx = find_lang_index(neg->conf->language_priority, lang);
+              
+            if ((idx >= 0) && ((bestidx == -1) || (idx < bestidx))) {
+                bestidx = idx;
+            }
+        }
 
+        if (bestidx >= 0) {
+            if (variant->lang_quality) {
+                if (forcepriority & FLP_PREFER) {
+                    variant->lang_index = bestidx;
+                }
+            }
+            else {
+                if (forcepriority & FLP_FALLBACK) {
+                    variant->lang_index = bestidx;
+                    variant->lang_quality = .0001f;
+                    variant->definite = 0;
+                }
+            }
+        }
+    }
+    
     return;
 }