mod_negotiation.c revision 8df0e180e83b3135acc7261de293c138731ca25f
212032b342cab2f8798b146813d800ce522f9a66nd/* ====================================================================
212032b342cab2f8798b146813d800ce522f9a66nd * The Apache Software License, Version 1.1
fd9abdda70912b99b24e3bf1a38f26fde908a74cnd * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
fd9abdda70912b99b24e3bf1a38f26fde908a74cnd * reserved.
212032b342cab2f8798b146813d800ce522f9a66nd * Redistribution and use in source and binary forms, with or without
212032b342cab2f8798b146813d800ce522f9a66nd * modification, are permitted provided that the following conditions
212032b342cab2f8798b146813d800ce522f9a66nd * are met:
212032b342cab2f8798b146813d800ce522f9a66nd * 1. Redistributions of source code must retain the above copyright
212032b342cab2f8798b146813d800ce522f9a66nd * notice, this list of conditions and the following disclaimer.
2e545ce2450a9953665f701bb05350f0d3f26275nd * 2. Redistributions in binary form must reproduce the above copyright
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * notice, this list of conditions and the following disclaimer in
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * the documentation and/or other materials provided with the
212032b342cab2f8798b146813d800ce522f9a66nd * distribution.
af33a4994ae2ff15bc67d19ff1a7feb906745bf8rbowen * 3. The end-user documentation included with the redistribution,
3f08db06526d6901aa08c110b5bc7dde6bc39905nd * if any, must include the following acknowledgment:
212032b342cab2f8798b146813d800ce522f9a66nd * "This product includes software developed by the
212032b342cab2f8798b146813d800ce522f9a66nd * Apache Software Foundation (http://www.apache.org/)."
212032b342cab2f8798b146813d800ce522f9a66nd * Alternately, this acknowledgment may appear in the software itself,
c9e2bff5ba899896dcd1f6e3e42662402c4fb58frbowen * if and wherever such third-party acknowledgments normally appear.
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd * 4. The names "Apache" and "Apache Software Foundation" must
980bee71ed017c72bfdd9861445f9495855508ccgryzor * not be used to endorse or promote products derived from this
7f5b59ccc63c0c0e3e678a168f09ee6a2f51f9d0nd * software without prior written permission. For written
91f378b5a10f2d83820902ed10ba7967a3920c18nilgun * permission, please contact apache@apache.org.
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd * 5. Products derived from this software may not be called "Apache",
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd * nor may "Apache" appear in their name, without prior written
a2a160100f0a51cb7fd738c1462a0b251215870erbowen * permission of the Apache Software Foundation.
a2a160100f0a51cb7fd738c1462a0b251215870erbowen * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
a2a160100f0a51cb7fd738c1462a0b251215870erbowen * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1844bb5f7939bd31f51dffaf8d8cf1c00657a681rbowen * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1844bb5f7939bd31f51dffaf8d8cf1c00657a681rbowen * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
1844bb5f7939bd31f51dffaf8d8cf1c00657a681rbowen * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212032b342cab2f8798b146813d800ce522f9a66nd * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
212032b342cab2f8798b146813d800ce522f9a66nd * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
212032b342cab2f8798b146813d800ce522f9a66nd * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
212032b342cab2f8798b146813d800ce522f9a66nd * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
212032b342cab2f8798b146813d800ce522f9a66nd * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
212032b342cab2f8798b146813d800ce522f9a66nd * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
212032b342cab2f8798b146813d800ce522f9a66nd * SUCH DAMAGE.
212032b342cab2f8798b146813d800ce522f9a66nd * ====================================================================
99ca75ffd7b9d0e6573ba8858c6e59d4a6d2fa15nd * This software consists of voluntary contributions made by many
99ca75ffd7b9d0e6573ba8858c6e59d4a6d2fa15nd * individuals on behalf of the Apache Software Foundation. For more
15b1ec87bc44ffcbe4630fc8a266439bcaedd4e8mrumph * information on the Apache Software Foundation, please see
212032b342cab2f8798b146813d800ce522f9a66nd * Portions of this software are based upon public domain software
212032b342cab2f8798b146813d800ce522f9a66nd * originally written at the National Center for Supercomputing Applications,
212032b342cab2f8798b146813d800ce522f9a66nd * University of Illinois, Urbana-Champaign.
e4ca72aa494fed7b6948012734b9c9c098fbba07nd * mod_negotiation.c: keeps track of MIME types the client is willing to
e4ca72aa494fed7b6948012734b9c9c098fbba07nd * accept, and contains code to handle type arbitration.
e4ca72aa494fed7b6948012734b9c9c098fbba07nd/* Commands --- configuring document caching on a per (virtual?)
1bf1953a52a1b56dbaa513ba91cf234b7165889enoodl * server basis...
99ca75ffd7b9d0e6573ba8858c6e59d4a6d2fa15ndtypedef struct {
e4ca72aa494fed7b6948012734b9c9c098fbba07nd/* forcelangpriority flags
91f378b5a10f2d83820902ed10ba7967a3920c18nilgun#define FLP_UNDEF 0 /* Same as FLP_NONE, but base overrides */
91f378b5a10f2d83820902ed10ba7967a3920c18nilgun#define FLP_NONE 1 /* Return 406, HTTP_NOT_ACCEPTABLE */
15b1ec87bc44ffcbe4630fc8a266439bcaedd4e8mrumph#define FLP_PREFER 2 /* Use language_priority rather than MC */
99ca75ffd7b9d0e6573ba8858c6e59d4a6d2fa15nd#define FLP_FALLBACK 4 /* Use language_priority rather than NA */
99ca75ffd7b9d0e6573ba8858c6e59d4a6d2fa15ndstatic void *create_neg_dir_config(apr_pool_t *p, char *dummy)
e4ca72aa494fed7b6948012734b9c9c098fbba07nd neg_dir_config *new = (neg_dir_config *) apr_palloc(p, sizeof(neg_dir_config));
212032b342cab2f8798b146813d800ce522f9a66ndstatic void *merge_neg_dir_configs(apr_pool_t *p, void *basev, void *addv)
a2a160100f0a51cb7fd738c1462a0b251215870erbowen neg_dir_config *new = (neg_dir_config *) apr_palloc(p, sizeof(neg_dir_config));
a2a160100f0a51cb7fd738c1462a0b251215870erbowen /* give priority to the config in the subdirectory */
a2a160100f0a51cb7fd738c1462a0b251215870erbowen new->forcelangpriority = add->forcelangpriority ? add->forcelangpriority
838d5ac1582d50020a146d747b64d64548fa8c92rbowen new->language_priority = add->language_priority ? add->language_priority
8e88ea9de3027912dc4c69ebb44f32257c4bb0c4rbowenstatic const char *set_language_priority(cmd_parms *cmd, void *n_,
212032b342cab2f8798b146813d800ce522f9a66nd const char *lang)
838d5ac1582d50020a146d747b64d64548fa8c92rbowen const char **langp;
212032b342cab2f8798b146813d800ce522f9a66nd n->language_priority = apr_array_make(cmd->pool, 4, sizeof(char *));
838d5ac1582d50020a146d747b64d64548fa8c92rbowen langp = (const char **) apr_array_push(n->language_priority);
212032b342cab2f8798b146813d800ce522f9a66ndstatic const char *set_force_priority(cmd_parms *cmd, void *n_, const char *w)
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh return "Cannot combine ForceLanguagePriority options with None";
a2a160100f0a51cb7fd738c1462a0b251215870erbowen return "Cannot combine ForceLanguagePriority options None and Prefer";
91f378b5a10f2d83820902ed10ba7967a3920c18nilgun return "Cannot combine ForceLanguagePriority options None and Fallback";
99ca75ffd7b9d0e6573ba8858c6e59d4a6d2fa15nd return apr_pstrcat(cmd->pool, "Invalid ForceLanguagePriority option ", w, NULL);
a2a160100f0a51cb7fd738c1462a0b251215870erbowenstatic const char *cache_negotiated_docs(cmd_parms *cmd, void *dummy,
8e88ea9de3027912dc4c69ebb44f32257c4bb0c4rbowen ap_set_module_config(cmd->server->module_config, &negotiation_module,
212032b342cab2f8798b146813d800ce522f9a66nd return (ap_get_module_config(s->module_config, &negotiation_module) != NULL);
8e88ea9de3027912dc4c69ebb44f32257c4bb0c4rbowen AP_INIT_FLAG("CacheNegotiatedDocs", cache_negotiated_docs, NULL, RSRC_CONF,
8e88ea9de3027912dc4c69ebb44f32257c4bb0c4rbowen "Either 'on' or 'off' (default)"),
91f378b5a10f2d83820902ed10ba7967a3920c18nilgun AP_INIT_ITERATE("LanguagePriority", set_language_priority, NULL, OR_FILEINFO,
8e88ea9de3027912dc4c69ebb44f32257c4bb0c4rbowen "space-delimited list of MIME language abbreviations"),
212032b342cab2f8798b146813d800ce522f9a66nd AP_INIT_ITERATE("ForceLanguagePriority", set_force_priority, NULL, OR_FILEINFO,
212032b342cab2f8798b146813d800ce522f9a66nd "Force LanguagePriority elections, either None, or Fallback and/or Prefer"),
a2a160100f0a51cb7fd738c1462a0b251215870erbowen * Record of available info on a media type specified by the client
212032b342cab2f8798b146813d800ce522f9a66nd * (we also use 'em for encodings and languages)
212032b342cab2f8798b146813d800ce522f9a66ndtypedef struct accept_rec {
8e88ea9de3027912dc4c69ebb44f32257c4bb0c4rbowen * Record of available info on a particular variant
838d5ac1582d50020a146d747b64d64548fa8c92rbowen * Note that a few of these fields are updated by the actual negotiation
838d5ac1582d50020a146d747b64d64548fa8c92rbowen * code. These are:
838d5ac1582d50020a146d747b64d64548fa8c92rbowen * level_matched --- initialized to zero. Set to the value of level
838d5ac1582d50020a146d747b64d64548fa8c92rbowen * if the client actually accepts this media type at that
8c3bb4bd8e33f6712e32fe1b938733292551e293slive * level (and *not* if it got in on a wildcard). See level_cmp
838d5ac1582d50020a146d747b64d64548fa8c92rbowen * mime_stars -- initialized to zero. Set to the number of stars
212032b342cab2f8798b146813d800ce522f9a66nd * present in the best matching Accept header element.
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh * definite -- initialized to 1. Set to 0 if there is a match which
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh * makes the variant non-definite according to the rules
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh * in rfc2296.
419d55842022e9e257941bfe226549661fb2c6c7humbedoohtypedef struct var_rec {
212032b342cab2f8798b146813d800ce522f9a66nd request_rec *sub_req; /* May be NULL (is, for map files) */
838d5ac1582d50020a146d747b64d64548fa8c92rbowen const char *file_name; /* Set to 'this' (for map file body content) */
212032b342cab2f8798b146813d800ce522f9a66nd apr_array_header_t *content_languages; /* list of languages for this variant */
6dea816e0f19e6dc7674282f4a8aaa486d11eed3sf /* The next five items give the quality values for the dimensions
6dea816e0f19e6dc7674282f4a8aaa486d11eed3sf * of negotiation for this variant. They are obtained from the
212032b342cab2f8798b146813d800ce522f9a66nd * appropriate header lines, except for source_quality, which
9335f6d807d76d60e54af4ededdebebddb3e3d13noodl * is obtained from the variant itself (the 'qs' parameter value
212032b342cab2f8798b146813d800ce522f9a66nd * from the variant's mime-type). Apart from source_quality,
212032b342cab2f8798b146813d800ce522f9a66nd * these values are set when we find the quality for each variant
212032b342cab2f8798b146813d800ce522f9a66nd * (see best_match()). source_quality is set from the 'qs' parameter
212032b342cab2f8798b146813d800ce522f9a66nd * of the variant description or mime type: see set_mime_fields().
212032b342cab2f8798b146813d800ce522f9a66nd float lang_quality; /* quality of this variant's language */
838d5ac1582d50020a146d747b64d64548fa8c92rbowen float source_quality; /* source quality for this variant */
838d5ac1582d50020a146d747b64d64548fa8c92rbowen /* Now some special values */
838d5ac1582d50020a146d747b64d64548fa8c92rbowen int lang_index; /* Index into LanguagePriority list */
8c3bb4bd8e33f6712e32fe1b938733292551e293slive int is_pseudo_html; /* text/html, *or* the INCLUDES_MAGIC_TYPEs */
8e88ea9de3027912dc4c69ebb44f32257c4bb0c4rbowen /* Above are all written-once properties of the variant. The
8e88ea9de3027912dc4c69ebb44f32257c4bb0c4rbowen * three fields below are changed during negotiation:
838d5ac1582d50020a146d747b64d64548fa8c92rbowen/* Something to carry around the state of negotiation (and to keep
838d5ac1582d50020a146d747b64d64548fa8c92rbowen * all of this thread-safe)...
8c3bb4bd8e33f6712e32fe1b938733292551e293slivetypedef struct {
8c3bb4bd8e33f6712e32fe1b938733292551e293slive int accept_q; /* 1 if an Accept item has a q= param */
8c3bb4bd8e33f6712e32fe1b938733292551e293slive float default_lang_quality; /* fiddle lang q for variants with no lang */
9335f6d807d76d60e54af4ededdebebddb3e3d13noodl /* the array pointers below are NULL if the corresponding accept
212032b342cab2f8798b146813d800ce522f9a66nd * headers are not present
838d5ac1582d50020a146d747b64d64548fa8c92rbowen apr_array_header_t *accept_charsets; /* accept_recs */
a2a160100f0a51cb7fd738c1462a0b251215870erbowen int count_multiviews_variants; /* number of variants found on disk */
a2a160100f0a51cb7fd738c1462a0b251215870erbowen int is_transparent; /* 1 if this resource is trans. negotiable */
a2a160100f0a51cb7fd738c1462a0b251215870erbowen int dont_fiddle_headers; /* 1 if we may not fiddle with accept hdrs */
212032b342cab2f8798b146813d800ce522f9a66nd int ua_supports_trans; /* 1 if ua supports trans negotiation */
212032b342cab2f8798b146813d800ce522f9a66nd int send_alternates; /* 1 if we want to send an Alternates header */
212032b342cab2f8798b146813d800ce522f9a66nd int may_choose; /* 1 if we may choose a variant for the client */
212032b342cab2f8798b146813d800ce522f9a66nd int use_rvsa; /* 1 if we must use RVSA/1.0 negotiation algo */
a2a160100f0a51cb7fd738c1462a0b251215870erbowen/* A few functions to manipulate var_recs.
a2a160100f0a51cb7fd738c1462a0b251215870erbowen * Cleaning out the fields...
a2a160100f0a51cb7fd738c1462a0b251215870erbowen/* Initializing the relevant fields of a variant record from the
a2a160100f0a51cb7fd738c1462a0b251215870erbowen * accept_info read out of its content-type, one way or another.
15292da5451dea4ad10c12d35d9addc88be302c5humbedoohstatic void set_mime_fields(var_rec *var, accept_rec *mime_info)
a2a160100f0a51cb7fd738c1462a0b251215870erbowen var->is_pseudo_html = (!strcmp(var->mime_type, "text/html")
212032b342cab2f8798b146813d800ce522f9a66nd/* Create a variant list validator in r using info from vlistr. */
212032b342cab2f8798b146813d800ce522f9a66ndstatic void set_vlist_validator(request_rec *r, request_rec *vlistr)
a2a160100f0a51cb7fd738c1462a0b251215870erbowen /* Calculating the variant list validator is similar to
a2a160100f0a51cb7fd738c1462a0b251215870erbowen * calculating an etag for the source of the variant list
a2a160100f0a51cb7fd738c1462a0b251215870erbowen * information, so we use ap_make_etag(). Note that this
a2a160100f0a51cb7fd738c1462a0b251215870erbowen * validator can be 'weak' in extreme case.
a2a160100f0a51cb7fd738c1462a0b251215870erbowen /* ap_set_etag will later take r->vlist_validator into account
a2a160100f0a51cb7fd738c1462a0b251215870erbowen * when creating the etag header
838d5ac1582d50020a146d747b64d64548fa8c92rbowen/*****************************************************************
212032b342cab2f8798b146813d800ce522f9a66nd * Parsing (lists of) media types and their parameters, as seen in
212032b342cab2f8798b146813d800ce522f9a66nd * HTTPD header lines and elsewhere.
b12f74e1aaac71d21e4b9a376b31d7307a8d87d8nd * Get a single mime type entry --- one media type and parameters;
b12f74e1aaac71d21e4b9a376b31d7307a8d87d8nd * enter the values we recognize into the argument accept_rec
101351670b0802f14c308dfe3f57d7f48faa0322noodlstatic const char *get_entry(apr_pool_t *p, accept_rec *result,
101351670b0802f14c308dfe3f57d7f48faa0322noodl const char *accept_line)
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh * Note that this handles what I gather is the "old format",
4aa603e6448b99f9371397d439795c91a93637eand * without any compatibility kludges --- if the token after the
419d55842022e9e257941bfe226549661fb2c6c7humbedooh * MIME type begins with a semicolon, we know we're looking at parms,
b12f74e1aaac71d21e4b9a376b31d7307a8d87d8nd * otherwise, we know we aren't. (So why all the pissing and moaning
b12f74e1aaac71d21e4b9a376b31d7307a8d87d8nd * in the CERN server code? I must be missing something).
99ca75ffd7b9d0e6573ba8858c6e59d4a6d2fa15nd ap_str_tolower(result->name); /* You want case insensitive,
99ca75ffd7b9d0e6573ba8858c6e59d4a6d2fa15nd * you'll *get* case insensitive.
91f378b5a10f2d83820902ed10ba7967a3920c18nilgun /* KLUDGE!!! Default HTML to level 2.0 unless the browser
91f378b5a10f2d83820902ed10ba7967a3920c18nilgun * *explicitly* says something else.
99ca75ffd7b9d0e6573ba8858c6e59d4a6d2fa15nd if (!strcmp(result->name, "text/html") && (result->level == 0.0)) {
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh else if (!strcmp(result->name, INCLUDES_MAGIC_TYPE)) {
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh else if (!strcmp(result->name, INCLUDES_MAGIC_TYPE3)) {
99ca75ffd7b9d0e6573ba8858c6e59d4a6d2fa15nd /* Parameters ... */
99ca75ffd7b9d0e6573ba8858c6e59d4a6d2fa15nd /* Look for 'var = value' --- and make sure the var is in lcase. */
b86121f212a2da547f4e5bd1c774eea9ea699e9echrisd for (cp = parm; (*cp && !apr_isspace(*cp) && *cp != '='); ++cp) {
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh continue; /* No '='; just ignore it. */
1e367a83311e5243e04d68857d007d04765a48f9chrisd (*end && *end != '\n' && *end != '\r' && *end != '\"');
15b1ec87bc44ffcbe4630fc8a266439bcaedd4e8mrumph && (parm[1] == '\0' || (parm[1] == 's' && parm[2] == '\0'))) {
fa299b341c4a4ad05338ac60c23b0a0e5a3474e1chrisd/*****************************************************************
fa299b341c4a4ad05338ac60c23b0a0e5a3474e1chrisd * Dealing with header lines ...
1e367a83311e5243e04d68857d007d04765a48f9chrisd * Accept, Accept-Charset, Accept-Language and Accept-Encoding
91f378b5a10f2d83820902ed10ba7967a3920c18nilgun * are handled by do_header_line() - they all have the same
1e367a83311e5243e04d68857d007d04765a48f9chrisd * basic structure of a list of items of the format
fa299b341c4a4ad05338ac60c23b0a0e5a3474e1chrisd * name; q=N; charset=TEXT
fa299b341c4a4ad05338ac60c23b0a0e5a3474e1chrisd * where charset is only valid in Accept.
fa299b341c4a4ad05338ac60c23b0a0e5a3474e1chrisdstatic apr_array_header_t *do_header_line(apr_pool_t *p, const char *accept_line)
fa299b341c4a4ad05338ac60c23b0a0e5a3474e1chrisd accept_recs = apr_array_make(p, 40, sizeof(accept_rec));
99ca75ffd7b9d0e6573ba8858c6e59d4a6d2fa15nd accept_rec *new = (accept_rec *) apr_array_push(accept_recs);
b244bbf442a0aea3dc397b4d0d751f4716c5891dnd/* Given the text of the Content-Languages: line from the var map file,
b244bbf442a0aea3dc397b4d0d751f4716c5891dnd * return an array containing the languages of this variant
b244bbf442a0aea3dc397b4d0d751f4716c5891dndstatic apr_array_header_t *do_languages_line(apr_pool_t *p, const char **lang_line)
91f378b5a10f2d83820902ed10ba7967a3920c18nilgun apr_array_header_t *lang_recs = apr_array_make(p, 2, sizeof(char *));
91f378b5a10f2d83820902ed10ba7967a3920c18nilgun/*****************************************************************
91f378b5a10f2d83820902ed10ba7967a3920c18nilgun * Handling header lines from clients...
99ca75ffd7b9d0e6573ba8858c6e59d4a6d2fa15ndstatic negotiation_state *parse_accept_headers(request_rec *r)
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh (negotiation_state *) apr_pcalloc(r->pool, sizeof(negotiation_state));
99ca75ffd7b9d0e6573ba8858c6e59d4a6d2fa15nd new->conf = (neg_dir_config *)ap_get_module_config(r->per_dir_config,
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh new->dir_name = ap_make_dirstr_parent(r->pool, r->filename);
4aa603e6448b99f9371397d439795c91a93637eand new->accepts = do_header_line(r->pool, apr_table_get(hdrs, "Accept"));
91f378b5a10f2d83820902ed10ba7967a3920c18nilgun /* calculate new->accept_q value */
48c9194853e9509d118bd036923be7c5a144fe02rjung do_header_line(r->pool, apr_table_get(hdrs, "Accept-Encoding"));
48c9194853e9509d118bd036923be7c5a144fe02rjung do_header_line(r->pool, apr_table_get(hdrs, "Accept-Language"));
91f378b5a10f2d83820902ed10ba7967a3920c18nilgun do_header_line(r->pool, apr_table_get(hdrs, "Accept-Charset"));
99ca75ffd7b9d0e6573ba8858c6e59d4a6d2fa15nd /* This is possibly overkill for some servers, heck, we have
99ca75ffd7b9d0e6573ba8858c6e59d4a6d2fa15nd * only 33 index.html variants in docs/docroot (today).
91f378b5a10f2d83820902ed10ba7967a3920c18nilgun * Make this configurable?
99ca75ffd7b9d0e6573ba8858c6e59d4a6d2fa15nd new->avail_vars = apr_array_make(r->pool, 40, sizeof(var_rec));
99ca75ffd7b9d0e6573ba8858c6e59d4a6d2fa15ndstatic void parse_negotiate_header(request_rec *r, negotiation_state *neg)
a29610af88e278144045bfa1bc63b4a1a4b5ff14trawick const char *negotiate = apr_table_get(r->headers_in, "Negotiate");
a29610af88e278144045bfa1bc63b4a1a4b5ff14trawick /* First, default to no TCN, no Alternates, and the original Apache
a29610af88e278144045bfa1bc63b4a1a4b5ff14trawick * negotiation algorithm with fiddles for broken browser configs.
15b1ec87bc44ffcbe4630fc8a266439bcaedd4e8mrumph * To save network bandwidth, we do not configure to send an
a29610af88e278144045bfa1bc63b4a1a4b5ff14trawick * Alternates header to the user agent by default. User
a29610af88e278144045bfa1bc63b4a1a4b5ff14trawick * agents that want an Alternates header for agent-driven
a29610af88e278144045bfa1bc63b4a1a4b5ff14trawick * negotiation will have to request it by sending an
b12f74e1aaac71d21e4b9a376b31d7307a8d87d8nd * appropriate Negotiate header.
91f378b5a10f2d83820902ed10ba7967a3920c18nilgun /* Lynx 2.7 and 2.8 send 'negotiate: trans' even though they
8e88ea9de3027912dc4c69ebb44f32257c4bb0c4rbowen * do not support transparent content negotiation, so for Lynx we
8e88ea9de3027912dc4c69ebb44f32257c4bb0c4rbowen * ignore the negotiate header when its contents are exactly "trans".
8e88ea9de3027912dc4c69ebb44f32257c4bb0c4rbowen * If future versions of Lynx ever need to say 'negotiate: trans',
212032b342cab2f8798b146813d800ce522f9a66nd * they can send the equivalent 'negotiate: trans, trans' instead
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd * to avoid triggering the workaround below.
980bee71ed017c72bfdd9861445f9495855508ccgryzor const char *ua = apr_table_get(r->headers_in, "User-Agent");
ed62c84ee0911cfebbd8da319ac00757b555707chumbedooh neg->may_choose = 0; /* An empty Negotiate would require 300 response */
0d0ba3a410038e179b695446bb149cce6264e0abnd while ((tok = ap_get_list_item(neg->pool, &negotiate)) != NULL) {
0d0ba3a410038e179b695446bb149cce6264e0abnd /* The user agent supports transparent negotiation */
0d0ba3a410038e179b695446bb149cce6264e0abnd /* Send-alternates could be configurable, but note
0d0ba3a410038e179b695446bb149cce6264e0abnd * that it must be 1 if we have 'vlist' in the
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh * negotiate header.
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd /* we may use the RVSA/1.0 algorithm, configure for it */
#ifdef NEG_DEBUG
int prefer_scripts)
enum header_state {
char *cp;
return header_eof;
return header_sep;
return header_seen;
else if (apr_isspace(c)) {
*cp++ = c;
return header_seen;
return header_seen;
char *endbody;
int bodylen;
if (!endbody) {
while (*endbody) {
++endbody;
++endbody;
while (*hdr) {
++hdr;
if (*hdr) {
++hdr;
if (!*cp) {
return NULL;
++cp;
if (!*cp) {
return NULL;
return cp;
int has_content;
if (!map)
return HTTP_FORBIDDEN;
has_content = 0;
const char *body;
return HTTP_INTERNAL_SERVER_ERROR;
&body);
char *cp;
has_content = 0;
if (map_)
return OK;
char *filp;
int prefix_len;
void *new_var;
int anymatch = 0;
return DECLINED;
++filp;
return HTTP_FORBIDDEN;
#ifdef CASE_BLIND_FILESYSTEM
* readme.txt and readme.foo, we will throw away .foo if
if (!exception_list) {
* A test of index.html.foo will match index.foo or index.html.foo,
* but it will never transpose the segments and allow index.foo.html
#ifdef CASE_BLIND_FILESYSTEM
--nexcept;
++cur_except;
if (!saveend)
if (nexcept) {
r->filename);
return HTTP_NOT_FOUND;
set_vlist_validator(r, r);
return OK;
return OK;
const char **alang;
char *lang, *p;
int any_match_on_star = 0;
p = NULL;
alen = 0;
if (!star) {
if (!best ||
if ( any_match_on_star &&
(!best)) ) {
if (bestidx >= 0) {
int prev_mime_stars;
if (star) {
if (star) {
enum algorithm_results {
#ifdef NEG_DEBUG
if (q > bestq) {
*p_bestq = q;
if (q == bestq) {
*p_bestq = q;
int levcmp;
#ifdef NEG_DEBUG
*p_bestq = q;
*p_bestq = q;
*p_bestq = q;
*p_bestq = q;
*p_bestq = q;
*p_bestq = q;
*p_bestq = q;
return algorithm_result;
* example if we have 3 variants x.html, x.ps.en and x.ps.nl, and if
int alg_result)
char *lang;
char *qstr;
char *lenstr;
int vary_by_type = 0;
int vary_by_language = 0;
int vary_by_charset = 0;
int vary_by_encoding = 0;
if (first_variant) {
if (!vary_by_type &&
if (!vary_by_charset &&
if (!vary_by_language &&
if (!vary_by_encoding &&
first_variant = 0;
if (lang) {
const char *sub_vary;
int status;
return status;
return HTTP_VARIANT_ALSO_VARIES;
return HTTP_VARIANT_ALSO_VARIES;
int res;
return HTTP_MULTIPLE_CHOICES;
if (!*bestp) {
return HTTP_NOT_ACCEPTABLE;
* Manual setting of cache-control/expires always overrides this
return OK;
int res;
char *udir;
return DECLINED;
return res;
apr_bucket *e;
return res;
return HTTP_METHOD_NOT_ALLOWED;
return res;
e = apr_bucket_eos_create();
* viewcvs.cgi.xx, all serving the same repository.)
return OK;
int res;
return DECLINED;
return res;
return DECLINED;
if (res != 0)
goto return_from_multi;
goto return_from_multi;
r->mtime = 0;
return OK;
return DECLINED;
return DECLINED;
return OK;
if (x_enc) {
return OK;
return DECLINED;