29#define APR_WANT_STRFUNC
42#define MAP_FILE_MAGIC_TYPE "application/x-type-map"
60#define FLP_DEFAULT FLP_PREFER
64#define DISCARD_ALL_ENCODINGS 1
65#define DISCARD_ALL_BUT_HTML 2
67module AP_MODULE_DECLARE_DATA negotiation_module;
75 new->language_priority =
NULL;
89 :
base->forcelangpriority;
92 :
base->language_priority;
102 if (!
n->language_priority)
116 return "Cannot combine ForceLanguagePriority options with None";
122 return "Cannot combine ForceLanguagePriority options None and "
129 return "Cannot combine ForceLanguagePriority options None and "
135 return apr_pstrcat(
cmd->pool,
"Invalid ForceLanguagePriority option ",
153 &negotiation_module) !=
NULL);
159 "Either 'on' or 'off' (default)"),
162 "space-delimited list of MIME language abbreviations"),
165 "Force LanguagePriority elections, either None, or "
166 "Fallback and/or Prefer"),
316 var->is_pseudo_html = (!
strcmp(
var->mime_type,
"text/html")
363static float atoq(
const char *
string)
365 if (!
string || !*
string) {
376 if (*
string !=
'.' && *
string++ !=
'0') {
380 if (*
string ==
'.') {
386 if (*++
string >=
'0' && *
string <=
'9') {
387 i += (*
string -
'0') * 100;
389 if (*++
string >=
'0' && *
string <=
'9') {
390 i += (*
string -
'0') * 10;
392 if (*++
string >
'0' && *
string <=
'9') {
393 i += (*
string -
'0');
398 return (
float)
i / 1000.0f;
486 && (
parm[1] ==
'\0' || (
parm[1] ==
's' &&
parm[2] ==
'\0'))) {
576 &negotiation_module);
586 for (
i = 0;
i <
new->accepts->nelts; ++
i) {
587 if (elts[
i].quality < 1.0) {
593 new->accept_encodings =
597 new->accept_charsets =
624 neg->ua_supports_trans = 0;
625 neg->send_alternates = 0;
628 neg->dont_fiddle_headers = 0;
651 if (
strcmp(tok,
"trans") == 0 ||
652 strcmp(tok,
"vlist") == 0 ||
653 strcmp(tok,
"guess-small") == 0 ||
658 neg->ua_supports_trans = 1;
664 neg->send_alternates = 1;
666 if (
strcmp(tok,
"1.0") == 0) {
670 neg->dont_fiddle_headers = 1;
672 else if (tok[0] ==
'*') {
682 neg->dont_fiddle_headers = 1;
689 "dont_fiddle_headers=%d use_rvsa=%d ua_supports_trans=%d "
690 "send_alternates=%d, may_choose=%d",
691 neg->dont_fiddle_headers,
neg->use_rvsa,
692 neg->ua_supports_trans,
neg->send_alternates,
neg->may_choose);
756 }
while (
buffer[0] ==
'#');
888 else if (*
hdr ==
'(') {
889 while (*
hdr && *
hdr !=
')') {
909 for ( ; *cp && *cp !=
':' ; ++cp) {
915 "Syntax error in type map, no ':' in %s for header %s",
926 "Syntax error in type map --- no header body: %s for %s",
949 neg->count_multiviews_variants = 0;
954 "cannot access type map file: %s",
rr->
filename);
996 "Parse error in type map, Content-Length: "
997 "'%s' in %s is invalid.",
1017 for (cp = desc; *cp; ++cp) {
1018 if (*cp==
'\n') *cp=
' ';
1020 if (cp>desc) *(cp-1)=0;
1031 "Syntax error in type map, no end tag '%s' "
1032 "found in %s for Body: content.",
1069 if (
a->source_quality <
b->source_quality)
1071 if (
a->source_quality >
b->source_quality)
1075 return strcmp(
a->file_name,
b->file_name);
1115 "cannot read directory for multi: %s",
neg->dir_name);
1124#ifdef CASE_BLIND_FILESYSTEM
1184 "ap-mime-exceptions-list");
1208#ifdef CASE_BLIND_FILESYSTEM
1250 neg->avail_vars->nelts = 0;
1274 neg->count_multiviews_variants++;
1287 "Negotiation: discovered file(s) matching request: %s"
1288 " (None could be negotiated).",
1303 qsort((
void *)
neg->avail_vars->elts,
neg->avail_vars->nelts,
1394 if (
var1->is_pseudo_html && !
var2->is_pseudo_html) {
1408 if (
var1->level_matched >
var2->level_matched) {
1411 if (
var1->level_matched <
var2->level_matched) {
1453 if (!lang || !accept_langs) {
1457 alang = (
const char **) accept_langs->
elts;
1459 for (
i = 0;
i < accept_langs->
nelts; ++
i) {
1489 if (!
neg->dont_fiddle_headers) {
1490 for (j = 0; j <
neg->avail_vars->nelts; ++j) {
1492 if (
variant->content_languages &&
1493 variant->content_languages->nelts) {
1494 neg->default_lang_quality = 0.0001f;
1500 neg->default_lang_quality = 1.0f;
1541 if (!
variant->content_languages || !
variant->content_languages->nelts) {
1548 if (!
neg->dont_fiddle_headers) {
1563 if (!
neg->accept_langs) {
1577 for (j = 0; j <
variant->content_languages->nelts; ++j) {
1585 lang = ((
char **) (
variant->content_languages->elts))[j];
1594 for (
i = 0;
i <
neg->accept_langs->nelts; ++
i) {
1618 if ((strlen(lang) >=
alen) &&
1620 ((lang[
alen] == 0) || (lang[
alen] ==
'-')) ) {
1698 for (j = 0; j <
variant->content_languages->nelts; ++j)
1703 char *lang = ((
char **) (
variant->content_languages->elts))[j];
1724 variant->lang_quality = .0001f;
1778 if (!
neg->accepts) {
1797 for (
i = 0;
i <
neg->accepts->nelts; ++
i) {
1822 if (!
neg->dont_fiddle_headers && !
neg->accept_q &&
1826 else if (!
neg->dont_fiddle_headers && !
neg->accept_q &&
1836 variant->mime_type_quality = q;
1855 if (!
neg->accept_charsets) {
1877 if (
neg->dont_fiddle_headers)
1888 for (
i = 0;
i <
neg->accept_charsets->nelts; ++
i) {
1908 variant->charset_quality = 1.0f;
1911 variant->charset_quality = 0.0f;
1922 return (!enc || !enc[0] || !
strcmp(enc,
"7bit") || !
strcmp(enc,
"8bit")
1923 || !
strcmp(enc,
"binary"));
1941 const char *enc =
variant->content_encoding;
1946 if (!
neg->accept_encodings) {
1952 variant->encoding_quality = 1.0f;
1954 variant->encoding_quality = 0.5f;
1969 if (enc[0] ==
'x' && enc[1] ==
'-') {
1972 for (
i = 0;
i <
neg->accept_encodings->nelts; ++
i) {
1976 if (
name[0] ==
'x' &&
name[1] ==
'-') {
2041 if (
variant->encoding_quality == 0.0f)
2044 q =
variant->mime_type_quality *
2060 "Variant: file=%s type=%s lang=%s sourceq=%1.3f "
2061 "mimeq=%1.3f langq=%1.3f charq=%1.3f encq=%1.3f "
2062 "q=%1.5f definite=%d",
2088 if (
variant->encoding_quality >
best->encoding_quality) {
2131 "Variant: file=%s type=%s lang=%s sourceq=%1.3f "
2132 "mimeq=%1.3f langq=%1.3f langidx=%d charq=%1.3f encq=%1.3f ",
2146 if (
variant->encoding_quality == 0.0f ||
2147 variant->lang_quality == 0.0f ||
2148 variant->source_quality == 0.0f ||
2149 variant->charset_quality == 0.0f ||
2150 variant->mime_type_quality == 0.0f) {
2155 if (q == 0.0 || q <
bestq) {
2173 if (
best->lang_index != -1 &&
2177 if (
variant->lang_index != -1 &&
2196 if (
variant->charset_quality <
best->charset_quality) {
2203 if (
variant->charset_quality >
best->charset_quality ||
2205 *
variant->content_charset !=
'\0' &&
2208 *
best->content_charset ==
'\0' ||
2209 strcmp(
best->content_charset,
"iso-8859-1") == 0))) {
2216 if (
variant->encoding_quality <
best->encoding_quality) {
2219 if (
variant->encoding_quality >
best->encoding_quality) {
2243 || !
variant->content_languages) {
2297 "gzip-only-text/html");
2317 for (j = 0; j <
neg->avail_vars->nelts; ++j) {
2359 if (
neg->may_choose) {
2368 if (
neg->use_rvsa) {
2383 if (
neg->use_rvsa) {
2460 if (
neg->send_alternates &&
neg->avail_vars->nelts)
2470 for (j = 0; j <
neg->avail_vars->nelts; ++j) {
2473 if (
variant->content_languages &&
variant->content_languages->nelts) {
2497 variant->content_charset :
"")) {
2502 lang ? lang :
"")) {
2508 variant->content_encoding :
"")) {
2514 if (!
neg->send_alternates)
2527 if (
qstr[4] ==
'0') {
2529 if (
qstr[3] ==
'0') {
2531 if (
qstr[2] ==
'0') {
2589 if (
neg->send_alternates &&
neg->avail_vars->nelts) {
2599 neg->is_transparent ?
", negotiate" :
"",
2606 if (
neg->is_transparent) {
2632 for (
i = 0;
i <
neg->avail_vars->nelts; ++
i) {
2636 const char *description =
variant->description
2665 if (
variant->content_encoding) {
2738 if (
neg->is_transparent &&
2824 neg->is_transparent = 1;
2830 neg->is_transparent = 0;
2832 for (j = 0; j <
neg->avail_vars->nelts; ++j) {
2841 neg->is_transparent = 0;
2847 neg->is_transparent = 0;
2852 if (
neg->is_transparent) {
2856 neg->may_choose = 1;
2871 neg->send_alternates = 1;
2875 if (
neg->is_transparent &&
neg->ua_supports_trans) {
2894 "no acceptable variant: %s",
r->
filename);
2902 if (
neg->is_transparent) {
2947 &&
neg->count_multiviews_variants != 1) {
3004 if (
best->mime_type && *
best->mime_type) {
3005 if (
best->content_charset && *
best->content_charset) {
3009 best->content_charset,
3018 if (
best->content_languages &&
best->content_languages->nelts) {
3020 best->content_languages);
3024 if (
best->content_encoding && *
best->content_encoding) {
3026 best->content_encoding);
3092 for (j = 0; j <
neg->avail_vars->nelts; ++j) {
3100 if (
neg->avail_vars->nelts == 0) {
3110 if (!(sub_req =
best->sub_req)) {
3139 for (j = 0; j <
neg->avail_vars->nelts; ++j) {
3171 if (!enc || !*enc) {
3175 if (enc[0] ==
'x' && enc[1] ==
'-') {
3186 for (
i = 0;
i < accept_encodings->
nelts; ++
i) {
Symbol export macros and hook functions.
const char apr_size_t len
APR general purpose library routines.
APR Standard Headers Support.
#define ap_get_module_config(v, m)
#define AP_DECLARE_MODULE(foo)
#define AP_INIT_FLAG(directive, func, mconfig, where, help)
#define AP_INIT_ITERATE(directive, func, mconfig, where, help)
void ap_hook_handler(ap_HOOK_handler_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
#define ap_set_module_config(v, m, val)
#define HTTP_VERSION(major, minor)
apr_status_t ap_pass_brigade_fchk(request_rec *r, apr_bucket_brigade *bucket, const char *fmt,...) __attribute__((format(printf
int ap_allow_options(request_rec *r)
void ap_set_accept_ranges(request_rec *r)
int ap_meets_conditions(request_rec *r)
void ap_set_content_length(request_rec *r, apr_off_t length)
void ap_set_content_type_ex(request_rec *r, const char *ct, int trusted)
int ap_discard_request_body(request_rec *r)
char * ap_make_etag(request_rec *r, int force_weak)
void ap_internal_fast_redirect(request_rec *sub_req, request_rec *r)
request_rec * ap_sub_req_lookup_dirent(const apr_finfo_t *finfo, const request_rec *r, int subtype, ap_filter_t *next_filter)
#define AP_SUBREQ_MERGE_ARGS
request_rec * ap_sub_req_lookup_file(const char *new_file, const request_rec *r, ap_filter_t *next_filter)
void ap_hook_fixups(ap_HOOK_fixups_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
void ap_allow_standard_methods(request_rec *r, int reset,...)
void ap_hook_type_checker(ap_HOOK_type_checker_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
void ap_destroy_sub_req(request_rec *r)
void ap_internal_redirect(const char *new_uri, request_rec *r)
void ap_update_mtime(request_rec *r, apr_time_t dependency_mtime)
int ap_find_path_info(const char *uri, const char *path_info)
#define APR_STATUS_IS_ENOTDIR(s)
#define APR_STATUS_IS_ENOENT(s)
#define APR_BRIGADE_INSERT_TAIL(b, e)
apr_bucket apr_bucket_brigade * a
apr_pool_t apr_dbd_t apr_dbd_results_t ** res
#define HTTP_MULTIPLE_CHOICES
#define HTTP_INTERNAL_SERVER_ERROR
#define HTTP_METHOD_NOT_ALLOWED
#define HTTP_NOT_ACCEPTABLE
#define HTTP_VARIANT_ALSO_VARIES
#define STANDARD20_MODULE_STUFF
char * ap_make_full_path(apr_pool_t *a, const char *dir, const char *f)
#define ap_escape_uri(ppool, path)
char * ap_escape_path_segment(apr_pool_t *p, const char *s)
#define ap_strchr_c(s, c)
char * ap_get_token(apr_pool_t *p, const char **accept_line, int accept_white)
char * ap_get_list_item(apr_pool_t *p, const char **field)
char * ap_make_dirstr_parent(apr_pool_t *p, const char *s)
int ap_cstr_casecmpn(const char *s1, const char *s2, apr_size_t n)
#define ap_escape_html(p, s)
void ap_str_tolower(char *s)
int ap_parse_strict_length(apr_off_t *len, const char *str)
int ap_array_str_contains(const apr_array_header_t *array, const char *s)
int ap_os_is_path_absolute(apr_pool_t *p, const char *dir)
apr_array_header_t ** result
int strcasecmp(const char *a, const char *b)
int strncasecmp(const char *a, const char *b, size_t n)
apr_vformatter_buff_t * c
#define apr_pcalloc(p, size)
apr_size_t const char * filename
const apr_array_header_t * arr
#define INCLUDES_MAGIC_TYPE3
#define INCLUDES_MAGIC_TYPE
static void strip_paren_comments(char *hdr)
static char * make_variant_list(request_rec *r, negotiation_state *neg)
static int setup_choice_response(request_rec *r, negotiation_state *neg, var_rec *variant)
#define DISCARD_ALL_ENCODINGS
static int best_match(negotiation_state *neg, var_rec **pbest)
static const char * set_language_priority(cmd_parms *cmd, void *n_, const char *lang)
static int mime_match(accept_rec *accept_r, var_rec *avail)
static int is_variant_better(negotiation_state *neg, var_rec *variant, var_rec *best, float *p_bestq)
static void clean_var_rec(var_rec *mime_info)
static int read_types_multi(negotiation_state *neg)
static void * create_neg_dir_config(apr_pool_t *p, char *dummy)
static const command_rec negotiation_cmds[]
static int read_type_map(apr_file_t **map, negotiation_state *neg, request_rec *rr)
static void set_charset_quality(negotiation_state *neg, var_rec *variant)
static void maybe_add_default_accepts(negotiation_state *neg, int prefer_scripts)
static int is_identity_encoding(const char *enc)
#define MAP_FILE_MAGIC_TYPE
#define DISCARD_ALL_BUT_HTML
static void store_variant_list(request_rec *r, negotiation_state *neg)
static void set_accept_quality(negotiation_state *neg, var_rec *variant)
static float atoq(const char *string)
static int variantsortf(var_rec *a, var_rec *b)
static int handle_multi(request_rec *r)
static void * merge_neg_dir_configs(apr_pool_t *p, void *basev, void *addv)
static char * lcase_header_name_return_body(char *header, request_rec *r)
static apr_array_header_t * do_header_line(apr_pool_t *p, const char *accept_line)
static int find_lang_index(apr_array_header_t *accept_langs, char *lang)
static const char * get_entry(apr_pool_t *p, accept_rec *result, const char *accept_line)
static void set_language_quality(negotiation_state *neg, var_rec *variant)
static void set_encoding_quality(negotiation_state *neg, var_rec *variant)
static void register_hooks(apr_pool_t *p)
static int fix_encoding(request_rec *r)
static int do_cache_negotiated_docs(server_rec *s)
static negotiation_state * parse_accept_headers(request_rec *r)
static enum header_state get_header_line(char *buffer, int len, apr_file_t *map)
static int handle_map_file(request_rec *r)
static apr_array_header_t * do_languages_line(apr_pool_t *p, const char **lang_line)
static void parse_negotiate_header(request_rec *r, negotiation_state *neg)
static void set_mime_fields(var_rec *var, accept_rec *mime_info)
static int level_cmp(var_rec *var1, var_rec *var2)
static void set_neg_headers(request_rec *r, negotiation_state *neg, int alg_result)
static void set_default_lang_quality(negotiation_state *neg)
static apr_off_t get_body(char *buffer, apr_size_t *len, const char *tag, apr_file_t *map)
static const char * cache_negotiated_docs(cmd_parms *cmd, void *dummy, int arg)
static int is_variant_better_rvsa(negotiation_state *neg, var_rec *variant, var_rec *best, float *p_bestq)
static int discard_variant_by_env(var_rec *variant, int discard)
static const char * set_force_priority(cmd_parms *cmd, void *n_, const char *w)
static int variant_has_language(var_rec *variant, const char *lang)
static apr_off_t find_content_length(negotiation_state *neg, var_rec *variant)
static void set_vlist_validator(request_rec *r, request_rec *vlistr)
static int do_negotiation(request_rec *r, negotiation_state *neg, var_rec **bestp, int prefer_scripts)
Structure to store things which are per connection.
apr_array_header_t * language_priority
apr_array_header_t * accept_charsets
float default_lang_quality
apr_array_header_t * accepts
apr_array_header_t * avail_vars
apr_array_header_t * accept_encodings
apr_array_header_t * accept_langs
int count_multiviews_variants
A structure that represents the current request.
apr_array_header_t * content_languages
const char * content_type
struct ap_filter_t * output_filters
apr_table_t * err_headers_out
struct ap_conf_vector_t * per_dir_config
const char * content_encoding
A structure to store information for each virtual server.
const char * content_encoding
const char * content_charset
apr_array_header_t * content_languages
apr_status_t apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted, apr_dir_t *thedir)
apr_status_t apr_dir_close(apr_dir_t *thedir)
apr_status_t apr_dir_open(apr_dir_t **new, const char *dirname, apr_pool_t *pool)
typedef int(WSAAPI *apr_winapi_fpt_WSAPoll)(IN OUT LPWSAPOLLFD fdArray