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

📄 mod_negotiation.c

📁 apache 安装教程 apache 安装教程
💻 C
📖 第 1 页 / 共 5 页
字号:
{    int i;    accept_rec *accept_recs;    char *charset = variant->content_charset;    accept_rec *star = NULL;    /* if no Accept-Charset: header, leave quality alone (will     * remain at the default value of 1)     */    if (!neg->accept_charsets) {        if (charset && *charset)            variant->definite = 0;        return;    }    accept_recs = (accept_rec *) neg->accept_charsets->elts;    if (charset == NULL || !*charset) {        /* Charset of variant not known */        /* if not a text / * type, leave quality alone */        if (!(!strncmp(variant->mime_type, "text/", 5)              || !strcmp(variant->mime_type, INCLUDES_MAGIC_TYPE)              || !strcmp(variant->mime_type, INCLUDES_MAGIC_TYPE3)               ))            return;        /* Don't go guessing if we are in strict header mode,         * e.g. when running the rvsa, as any guess won't be reflected         * in the variant list or content-location headers.         */        if (neg->dont_fiddle_headers)            return;        charset = "iso-8859-1"; /* The default charset for HTTP text types */    }    /*     * Go through each of the items on the Accept-Charset header,     * looking for a match with this variant's charset. If none     * match, charset is unacceptable, so set quality to 0.     */    for (i = 0; i < neg->accept_charsets->nelts; ++i) {        accept_rec *type = &accept_recs[i];        if (!strcmp(type->name, charset)) {            variant->charset_quality = type->quality;            return;        }        else if (strcmp(type->name, "*") == 0) {            star = type;        }    }    /* No explicit match */    if (star) {        variant->charset_quality = star->quality;        variant->definite = 0;        return;    }    /* If this variant is in charset iso-8859-1, the default is 1.0 */    if (strcmp(charset, "iso-8859-1") == 0) {        variant->charset_quality = 1.0f;    }    else {        variant->charset_quality = 0.0f;    }}/* is_identity_encoding is included for back-compat, but does anyone * use 7bit, 8bin or binary in their var files?? */static int is_identity_encoding(const char *enc){    return (!enc || !enc[0] || !strcmp(enc, "7bit") || !strcmp(enc, "8bit")            || !strcmp(enc, "binary"));}/* * set_encoding_quality determines whether the encoding for a particular * variant is acceptable for the user-agent. * * The rules for encoding are that if the user-agent does not supply * any Accept-Encoding header, then all encodings are allowed but a * variant with no encoding should be preferred. * If there is an empty Accept-Encoding header, then no encodings are  * acceptable. If there is a non-empty Accept-Encoding header, then * any of the listed encodings are acceptable, as well as no encoding * unless the "identity" encoding is specifically excluded. */static void set_encoding_quality(negotiation_state *neg, var_rec *variant){    accept_rec *accept_recs;    const char *enc = variant->content_encoding;    accept_rec *star = NULL;    float value_if_not_found = 0.0f;    int i;    if (!neg->accept_encodings) {        /* We had no Accept-Encoding header, assume that all         * encodings are acceptable with a low quality,         * but we prefer no encoding if available.         */        if (!enc || is_identity_encoding(enc))            variant->encoding_quality = 1.0f;        else            variant->encoding_quality = 0.5f;        return;    }    if (!enc || is_identity_encoding(enc)) {        enc = "identity";        value_if_not_found = 0.0001f;    }    accept_recs = (accept_rec *) neg->accept_encodings->elts;    /* Go through each of the encodings on the Accept-Encoding: header,     * looking for a match with our encoding. x- prefixes are ignored.     */    if (enc[0] == 'x' && enc[1] == '-') {        enc += 2;    }    for (i = 0; i < neg->accept_encodings->nelts; ++i) {        char *name = accept_recs[i].name;        if (name[0] == 'x' && name[1] == '-') {            name += 2;        }        if (!strcmp(name, enc)) {            variant->encoding_quality = accept_recs[i].quality;            return;        }        if (strcmp(name, "*") == 0) {            star = &accept_recs[i];        }    }    /* No explicit match */    if (star) {        variant->encoding_quality = star->quality;        return;    }    /* Encoding not found on Accept-Encoding: header, so it is     * _not_ acceptable unless it is the identity (no encoding)     */    variant->encoding_quality = value_if_not_found;}/*************************************************************  * Possible results of the variant selection algorithm  */enum algorithm_results {    alg_choice = 1,              /* choose variant */    alg_list                     /* list variants */};/* Below is the 'best_match' function. It returns an int, which has * one of the two values alg_choice or alg_list, which give the result * of the variant selection algorithm.  alg_list means that no best * variant was found by the algorithm, alg_choice means that a best * variant was found and should be returned.  The list/choice * terminology comes from TCN (rfc2295), but is used in a more generic * way here.  The best variant is returned in *pbest. best_match has * two possible algorithms for determining the best variant: the * RVSA/1.0 algorithm (from RFC2296), and the standard Apache * algorithm. These are split out into separate functions * (is_variant_better_rvsa() and is_variant_better()).  Selection of * one is through the neg->use_rvsa flag. * * The call to best_match also creates full information, including * language, charset, etc quality for _every_ variant. This is needed * for generating a correct Vary header, and can be used for the * Alternates header, the human-readable list responses and 406 errors. *//* Firstly, the RVSA/1.0 (HTTP Remote Variant Selection Algorithm * v1.0) from rfc2296.  This is the algorithm that goes together with * transparent content negotiation (TCN). */static int is_variant_better_rvsa(negotiation_state *neg, var_rec *variant,                                  var_rec *best, float *p_bestq){    float bestq = *p_bestq, q;    /* TCN does not cover negotiation on content-encoding.  For now,     * we ignore the encoding unless it was explicitly excluded.     */    if (variant->encoding_quality == 0.0f)        return 0;        q = variant->mime_type_quality *        variant->source_quality *        variant->charset_quality *        variant->lang_quality;   /* RFC 2296 calls for the result to be rounded to 5 decimal places,    * but we don't do that because it serves no useful purpose other    * than to ensure that a remote algorithm operates on the same    * precision as ours.  That is silly, since what we obviously want    * is for the algorithm to operate on the best available precision    * regardless of who runs it.  Since the above calculation may    * result in significant variance at 1e-12, rounding would be bogus.    */#ifdef NEG_DEBUG    fprintf(stderr, "Variant: file=%s type=%s lang=%s sourceq=%1.3f "           "mimeq=%1.3f langq=%1.3f charq=%1.3f encq=%1.3f "           "q=%1.5f definite=%d\n",                        (variant->file_name ? variant->file_name : ""),            (variant->mime_type ? variant->mime_type : ""),            (variant->content_languages             ? ap_array_pstrcat(neg->pool, variant->content_languages, ',')             : ""),            variant->source_quality,            variant->mime_type_quality,            variant->lang_quality,            variant->charset_quality,            variant->encoding_quality,            q,            variant->definite);#endif    if (q <= 0.0f) {        return 0;    }    if (q > bestq) {        *p_bestq = q;        return 1;    }    if (q == bestq) {        /* If the best variant's encoding is of lesser quality than         * this variant, then we prefer this variant         */        if (variant->encoding_quality > best->encoding_quality) {            *p_bestq = q;            return 1;        }    }    return 0;}/* Negotiation algorithm as used by previous versions of Apache * (just about).  */static int is_variant_better(negotiation_state *neg, var_rec *variant,                             var_rec *best, float *p_bestq){    float bestq = *p_bestq, q;    int levcmp;    /* For non-transparent negotiation, server can choose how     * to handle the negotiation. We'll use the following in     * order: content-type, language, content-type level, charset,     * content encoding, content length.     *     * For each check, we have three possible outcomes:     *   This variant is worse than current best: return 0     *   This variant is better than the current best:     *          assign this variant's q to *p_bestq, and return 1     *   This variant is just as desirable as the current best:     *          drop through to the next test.     *     * This code is written in this long-winded way to allow future     * customisation, either by the addition of additional     * checks, or to allow the order of the checks to be determined     * by configuration options (e.g. we might prefer to check     * language quality _before_ content type).     */    /* First though, eliminate this variant if it is not     * acceptable by type, charset, encoding or language.     */#ifdef NEG_DEBUG    fprintf(stderr, "Variant: file=%s type=%s lang=%s sourceq=%1.3f "           "mimeq=%1.3f langq=%1.3f langidx=%d charq=%1.3f encq=%1.3f \n",            (variant->file_name ? variant->file_name : ""),            (variant->mime_type ? variant->mime_type : ""),            (variant->content_languages             ? ap_array_pstrcat(neg->pool, variant->content_languages, ',')             : ""),            variant->source_quality,            variant->mime_type_quality,            variant->lang_quality,            variant->lang_index,            variant->charset_quality,            variant->encoding_quality);#endif    if (variant->encoding_quality == 0.0f ||        variant->lang_quality == 0.0f ||        variant->source_quality == 0.0f ||        variant->charset_quality == 0.0f ||        variant->mime_type_quality == 0.0f) {        return 0;               /* don't consider unacceptables */    }    q = variant->mime_type_quality * variant->source_quality;    if (q == 0.0 || q < bestq) {        return 0;    }    if (q > bestq || !best) {        *p_bestq = q;        return 1;    }    /* language */    if (variant->lang_quality < best->lang_quality) {        return 0;    }    if (variant->lang_quality > best->lang_quality) {        *p_bestq = q;        return 1;    }    /* if language qualities were equal, try the LanguagePriority stuff */    if (best->lang_index != -1 &&        (variant->lang_index == -1 || variant->lang_index > best->lang_index)) {        return 0;    }    if (variant->lang_index != -1 &&        (best->lang_index == -1 || variant->lang_index < best->lang_index)) {        *p_bestq = q;        return 1;    }    /* content-type level (sometimes used with text/html, though we     * support it on other types too)     */    levcmp = level_cmp(variant, best);    if (levcmp == -1) {        return 0;    }    if (levcmp == 1) {        *p_bestq = q;        return 1;    }    /* charset */    if (variant->charset_quality < best->charset_quality) {        return 0;    }    /* If the best variant's charset is ISO-8859-1 and this variant has     * the same charset quality, then we prefer this variant     */    if (variant->charset_quality > best->charset_quality ||        ((variant->content_charset != NULL &&          *variant->content_charset != '\0' &&          strcmp(variant->content_charset, "iso-8859-1") != 0) &&         (best->content_charset == NULL ||          *best->content_charset == '\0' ||          strcmp(best->content_charset, "iso-8859-1") == 0))) {        *p_bestq = q;        return 1;    }    /* Prefer the highest value for encoding_quality.     */    if (variant->encoding_quality < best->encoding_quality) {       return 0;    }    if (variant->encoding_quality > best->encoding_quality) {       *p_bestq = q;       return 1;    }    /* content length if all else equal */    if (find_content_length(neg, variant) >= find_content_length(neg, best)) {        return 0;    }    /* ok, to get here means every thing turned out equal, except     * we have a shorter content length, so use this variant     */    *p_bestq = q;    return 1;}static int best_match(negotiation_state *neg, var_rec **pbest){    int j;    var_rec *best = NULL;    float bestq = 0.0f;    enum algorithm_results algorithm_r

⌨️ 快捷键说明

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