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

📄 mod_negotiation.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 5 页
字号:
            accept_rec *accs = (accept_rec *) neg->accept_langs->elts;            accept_rec *best = NULL, *star = NULL;            accept_rec *bestthistag;            char *lang, *p;            float fiddle_q = 0.0f;            int any_match_on_star = 0;            int i, j;            apr_size_t alen, longest_lang_range_len;            for (j = 0; j < variant->content_languages->nelts; ++j) {                p = NULL;                bestthistag = NULL;                longest_lang_range_len = 0;                alen = 0;                /* lang is the variant's language-tag, which is the one                 * we are allowed to use the prefix of in HTTP/1.1                 */                lang = ((char **) (variant->content_languages->elts))[j];                /* now find the best (i.e. longest) matching                 * Accept-Language header language. We put the best match                 * for this tag in bestthistag. We cannot update the                 * overall best (based on q value) because the best match                 * for this tag is the longest language item on the accept                 * header, not necessarily the highest q.                 */                for (i = 0; i < neg->accept_langs->nelts; ++i) {                    if (!strcmp(accs[i].name, "*")) {                        if (!star) {                            star = &accs[i];                        }                        continue;                    }                    /* Find language. We match if either the variant                     * language tag exactly matches the language range                     * from the accept header, or a prefix of the variant                     * language tag up to a '-' character matches the                     * whole of the language range in the Accept-Language                     * header.  Note that HTTP/1.x allows any number of                     * '-' characters in a tag or range, currently only                     * tags with zero or one '-' characters are defined                     * for general use (see rfc1766).                     *                     * We only use language range in the Accept-Language                     * header the best match for the variant language tag                     * if it is longer than the previous best match.                     */                    alen = strlen(accs[i].name);                    if ((strlen(lang) >= alen) &&                        !strncmp(lang, accs[i].name, alen) &&                        ((lang[alen] == 0) || (lang[alen] == '-')) ) {                        if (alen > longest_lang_range_len) {                            longest_lang_range_len = alen;                            bestthistag = &accs[i];                        }                    }                    if (!bestthistag && !neg->dont_fiddle_headers) {                        /* The next bit is a fiddle. Some browsers might                         * be configured to send more specific language                         * ranges than desirable. For example, an                         * Accept-Language of en-US should never match                         * variants with languages en or en-GB. But US                         * English speakers might pick en-US as their                         * language choice.  So this fiddle checks if the                         * language range has a prefix, and if so, it                         * matches variants which match that prefix with a                         * priority of 0.001. So a request for en-US would                         * match variants of types en and en-GB, but at                         * much lower priority than matches of en-US                         * directly, or of any other language listed on                         * the Accept-Language header. Note that this                         * fiddle does not handle multi-level prefixes.                         */                        if ((p = strchr(accs[i].name, '-'))) {                            int plen = p - accs[i].name;                            if (!strncmp(lang, accs[i].name, plen)) {                                fiddle_q = 0.001f;                            }                        }                    }                }                /* Finished looking at Accept-Language headers, the best                 * (longest) match is in bestthistag, or NULL if no match                 */                if (!best ||                    (bestthistag && bestthistag->quality > best->quality)) {                    best = bestthistag;                }                /* See if the tag matches on a * in the Accept-Language                 * header. If so, record this fact for later use                 */                if (!bestthistag && star) {                    any_match_on_star = 1;                }            }            /* If one of the language tags of the variant matched on *, we             * need to see if its q is better than that of any non-* match             * on any other tag of the variant.  If so the * match takes             * precedence and the overall match is not definite.             */            if ( any_match_on_star &&                ((best && star->quality > best->quality) ||                 (!best)) ) {                best = star;                variant->definite = 0;            }            variant->lang_quality = best ? best->quality : fiddle_q;        }    }    /* Handle the ForceDefaultLanguage overrides, based on the best match     * to LanguagePriority order.  The best match is the lowest index of     * any LanguagePriority match.     */    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;}/* Determining the content length --- if the map didn't tell us, * we have to do a stat() and remember for next time. */static apr_off_t find_content_length(negotiation_state *neg, var_rec *variant){    apr_finfo_t statb;    if (variant->bytes < 0) {        if (   variant->sub_req            && (variant->sub_req->finfo.valid & APR_FINFO_SIZE)) {            variant->bytes = variant->sub_req->finfo.size;        }        else {            char *fullname = ap_make_full_path(neg->pool, neg->dir_name,                                               variant->file_name);            if (apr_stat(&statb, fullname,                         APR_FINFO_SIZE, neg->pool) == APR_SUCCESS) {                variant->bytes = statb.size;            }        }    }    return variant->bytes;}/* For a given variant, find the best matching Accept: header * and assign the Accept: header's quality value to the * mime_type_quality field of the variant, for later use in * determining the best matching variant. */static void set_accept_quality(negotiation_state *neg, var_rec *variant){    int i;    accept_rec *accept_recs;    float q = 0.0f;    int q_definite = 1;    /* if no Accept: header, leave quality alone (will     * remain at the default value of 1)     *     * XXX: This if is currently never true because of the effect of     * maybe_add_default_accepts().     */    if (!neg->accepts) {        if (variant->mime_type && *variant->mime_type)            variant->definite = 0;        return;    }    accept_recs = (accept_rec *) neg->accepts->elts;    /*     * Go through each of the ranges on the Accept: header,     * looking for the 'best' match with this variant's     * content-type. We use the best match's quality     * value (from the Accept: header) for this variant's     * mime_type_quality field.     *     * The best match is determined like this:     *    type/type is better than type/ * is better than * / *     *    if match is type/type, use the level mime param if available     */    for (i = 0; i < neg->accepts->nelts; ++i) {        accept_rec *type = &accept_recs[i];        int prev_mime_stars;        prev_mime_stars = variant->mime_stars;        if (!mime_match(type, variant)) {            continue;           /* didn't match the content type at all */        }        else {            /* did match - see if there were less or more stars than             * in previous match             */            if (prev_mime_stars == variant->mime_stars) {                continue;       /* more stars => not as good a match */            }        }        /* If we are allowed to mess with the q-values         * and have no explicit q= parameters in the accept header,         * make wildcards very low, so we have a low chance         * of ending up with them if there's something better.         */        if (!neg->dont_fiddle_headers && !neg->accept_q &&            variant->mime_stars == 1) {            q = 0.01f;        }        else if (!neg->dont_fiddle_headers && !neg->accept_q &&                 variant->mime_stars == 2) {            q = 0.02f;        }        else {            q = type->quality;        }        q_definite = (variant->mime_stars == 3);    }    variant->mime_type_quality = q;    variant->definite = variant->definite && q_definite;}/* For a given variant, find the 'q' value of the charset given * on the Accept-Charset line. If no charsets are listed, * assume value of '1'. */static void set_charset_quality(negotiation_state *neg, var_rec *variant){    int i;    accept_rec *accept_recs;    const 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_quali

⌨️ 快捷键说明

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