httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From David Young <dyo...@nettonettech.com>
Subject [PATCH] implement ForceLanguagePriority in 1.3
Date Thu, 21 Mar 2002 17:51:41 GMT
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;
 }
 


Mime
View raw message