⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_negotiation.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License.  You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * mod_negotiation.c: keeps track of MIME types the client is willing to * accept, and contains code to handle type arbitration. * * rst */#include "apr.h"#include "apr_strings.h"#include "apr_file_io.h"#include "apr_lib.h"#define APR_WANT_STRFUNC#include "apr_want.h"#include "ap_config.h"#include "httpd.h"#include "http_config.h"#include "http_request.h"#include "http_protocol.h"#include "http_core.h"#include "http_log.h"#include "util_script.h"#define MAP_FILE_MAGIC_TYPE "application/x-type-map"/* Commands --- configuring document caching on a per (virtual?) * server basis... */typedef struct {    int forcelangpriority;    apr_array_header_t *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/* env evaluation */#define DISCARD_ALL_ENCODINGS 1  /* no-gzip */#define DISCARD_ALL_BUT_HTML  2  /* gzip-only-text/html */module AP_MODULE_DECLARE_DATA negotiation_module;static void *create_neg_dir_config(apr_pool_t *p, char *dummy){    neg_dir_config *new = (neg_dir_config *) apr_palloc(p,                                                        sizeof(neg_dir_config));    new->forcelangpriority = FLP_UNDEF;    new->language_priority = NULL;    return new;}static void *merge_neg_dir_configs(apr_pool_t *p, void *basev, void *addv){    neg_dir_config *base = (neg_dir_config *) basev;    neg_dir_config *add = (neg_dir_config *) addv;    neg_dir_config *new = (neg_dir_config *) apr_palloc(p,                                                        sizeof(neg_dir_config));    /* give priority to the config in the subdirectory */    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_,                                         const char *lang){    neg_dir_config *n = n_;    const char **langp;    if (!n->language_priority)        n->language_priority = apr_array_make(cmd->pool, 4, sizeof(char *));    langp = (const char **) apr_array_push(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 apr_pstrcat(cmd->pool, "Invalid ForceLanguagePriority option ",                           w, NULL);    }    return NULL;}static const char *cache_negotiated_docs(cmd_parms *cmd, void *dummy,                                         int arg){    ap_set_module_config(cmd->server->module_config, &negotiation_module,                         (arg ? "Cache" : NULL));    return NULL;}static int do_cache_negotiated_docs(server_rec *s){    return (ap_get_module_config(s->module_config,                                 &negotiation_module) != NULL);}static const command_rec negotiation_cmds[] ={    AP_INIT_FLAG("CacheNegotiatedDocs", cache_negotiated_docs, NULL, RSRC_CONF,                 "Either 'on' or 'off' (default)"),    AP_INIT_ITERATE("LanguagePriority", set_language_priority, NULL,                    OR_FILEINFO,                    "space-delimited list of MIME language abbreviations"),    AP_INIT_ITERATE("ForceLanguagePriority", set_force_priority, NULL,                    OR_FILEINFO,                    "Force LanguagePriority elections, either None, or "                    "Fallback and/or Prefer"),    {NULL}};/* * Record of available info on a media type specified by the client * (we also use 'em for encodings and languages) */typedef struct accept_rec {    char *name;                 /* MUST be lowercase */    float quality;    float level;    char *charset;              /* for content-type only */} accept_rec;/* * Record of available info on a particular variant * * Note that a few of these fields are updated by the actual negotiation * code.  These are: * * level_matched --- initialized to zero.  Set to the value of level *             if the client actually accepts this media type at that *             level (and *not* if it got in on a wildcard).  See level_cmp *             below. * mime_stars -- initialized to zero.  Set to the number of stars *               present in the best matching Accept header element. *               1 for star/star, 2 for type/star and 3 for *               type/subtype. * * definite -- initialized to 1.  Set to 0 if there is a match which *             makes the variant non-definite according to the rules *             in rfc2296. */typedef struct var_rec {    request_rec *sub_req;       /* May be NULL (is, for map files) */    const char *mime_type;      /* MUST be lowercase */    const char *file_name;      /* Set to 'this' (for map file body content) */    apr_off_t body;             /* Only for map file body content */    const char *content_encoding;    apr_array_header_t *content_languages; /* list of lang. for this variant */    const char *content_charset;    const char *description;    /* The next five items give the quality values for the dimensions     * of negotiation for this variant. They are obtained from the     * appropriate header lines, except for source_quality, which     * is obtained from the variant itself (the 'qs' parameter value     * from the variant's mime-type). Apart from source_quality,     * these values are set when we find the quality for each variant     * (see best_match()). source_quality is set from the 'qs' parameter     * of the variant description or mime type: see set_mime_fields().     */    float lang_quality;         /* quality of this variant's language */    float encoding_quality;     /* ditto encoding */    float charset_quality;      /* ditto charset */    float mime_type_quality;    /* ditto media type */    float source_quality;       /* source quality for this variant */    /* Now some special values */    float level;                /* Auxiliary to content-type... */    apr_off_t bytes;            /* content length, if known */    int lang_index;             /* Index into LanguagePriority list */    int is_pseudo_html;         /* text/html, *or* the INCLUDES_MAGIC_TYPEs */    /* Above are all written-once properties of the variant.  The     * three fields below are changed during negotiation:     */    float level_matched;    int mime_stars;    int definite;} var_rec;/* Something to carry around the state of negotiation (and to keep * all of this thread-safe)... */typedef struct {    apr_pool_t *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 */    /* the array pointers below are NULL if the corresponding accept     * headers are not present     */    apr_array_header_t *accepts;            /* accept_recs */    apr_array_header_t *accept_encodings;   /* accept_recs */    apr_array_header_t *accept_charsets;    /* accept_recs */    apr_array_header_t *accept_langs;       /* accept_recs */    apr_array_header_t *avail_vars;         /* available variants */    int count_multiviews_variants;    /* number of variants found on disk */    int is_transparent;       /* 1 if this resource is trans. negotiable */    int dont_fiddle_headers;  /* 1 if we may not fiddle with accept hdrs */    int ua_supports_trans;    /* 1 if ua supports trans negotiation */    int send_alternates;      /* 1 if we want to send an Alternates header */    int may_choose;           /* 1 if we may choose a variant for the client */    int use_rvsa;             /* 1 if we must use RVSA/1.0 negotiation algo */} negotiation_state;/* A few functions to manipulate var_recs. * Cleaning out the fields... */static void clean_var_rec(var_rec *mime_info){    mime_info->sub_req = NULL;    mime_info->mime_type = "";    mime_info->file_name = "";    mime_info->body = 0;    mime_info->content_encoding = NULL;    mime_info->content_languages = NULL;    mime_info->content_charset = "";    mime_info->description = "";    mime_info->is_pseudo_html = 0;    mime_info->level = 0.0f;    mime_info->level_matched = 0.0f;    mime_info->bytes = -1;    mime_info->lang_index = -1;    mime_info->mime_stars = 0;    mime_info->definite = 1;    mime_info->charset_quality = 1.0f;    mime_info->encoding_quality = 1.0f;    mime_info->lang_quality = 1.0f;    mime_info->mime_type_quality = 1.0f;    mime_info->source_quality = 0.0f;}/* Initializing the relevant fields of a variant record from the * accept_info read out of its content-type, one way or another. */static void set_mime_fields(var_rec *var, accept_rec *mime_info){    var->mime_type = mime_info->name;    var->source_quality = mime_info->quality;    var->level = mime_info->level;    var->content_charset = mime_info->charset;    var->is_pseudo_html = (!strcmp(var->mime_type, "text/html")                           || !strcmp(var->mime_type, INCLUDES_MAGIC_TYPE)                           || !strcmp(var->mime_type, INCLUDES_MAGIC_TYPE3));}/* Create a variant list validator in r using info from vlistr. */static void set_vlist_validator(request_rec *r, request_rec *vlistr){    /* Calculating the variant list validator is similar to     * calculating an etag for the source of the variant list     * information, so we use ap_make_etag().  Note that this     * validator can be 'weak' in extreme case.     */    ap_update_mtime(vlistr, vlistr->finfo.mtime);    r->vlist_validator = ap_make_etag(vlistr, 0);    /* ap_set_etag will later take r->vlist_validator into account     * when creating the etag header     */}/***************************************************************** * * Parsing (lists of) media types and their parameters, as seen in * HTTPD header lines and elsewhere. *//* * parse quality value. atof(3) is not well-usable here, because it * depends on the locale (argh). * * However, RFC 2616 states: * 3.9 Quality Values * * [...] HTTP/1.1 applications MUST NOT generate more than three digits * after the decimal point. User configuration of these values SHOULD also * be limited in this fashion. * *     qvalue         = ( "0" [ "." 0*3DIGIT ] ) *                    | ( "1" [ "." 0*3("0") ] ) * * This is quite easy. If the supplied string doesn't match the above * definition (loosely), we simply return 1 (same as if there's no qvalue) */static float atoq(const char *string){    if (!string || !*string) {        return  1.0f;    }    while (*string && apr_isspace(*string)) {        ++string;    }    /* be tolerant and accept qvalues without leading zero     * (also for backwards compat, where atof() was in use)     */    if (*string != '.' && *string++ != '0') {        return 1.0f;    }    if (*string == '.') {        /* better only one division later, than dealing with fscking         * IEEE format 0.1 factors ...         */        int i = 0;        if (*++string >= '0' && *string <= '9') {            i += (*string - '0') * 100;            if (*++string >= '0' && *string <= '9') {                i += (*string - '0') * 10;                if (*++string > '0' && *string <= '9') {                    i += (*string - '0');

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -