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

📄 mod_negotiation.c

📁 apache 安装教程 apache 安装教程
💻 C
📖 第 1 页 / 共 5 页
字号:
    }    accs = (accept_rec *) accept_langs->elts;    for (i = 0; i < accept_langs->nelts; ++i) {        if (!strncmp(lang, accs[i].name, strlen(accs[i].name))) {            return i;        }    }    return -1;}/* This function returns the priority of a given language * according to LanguagePriority.  It is used in case of a tie * between several languages. */static int find_default_index(neg_dir_config *conf, char *lang){    array_header *arr;    int nelts;    char **elts;    int i;    if (!lang) {        return -1;    }    arr = conf->language_priority;    nelts = arr->nelts;    elts = (char **) arr->elts;    for (i = 0; i < nelts; ++i) {        if (!strcasecmp(elts[i], lang)) {            return i;        }    }    return -1;}/* set_default_lang_quality() sets the quality we apply to variants * which have no language assigned to them. If none of the variants * have a language, we are not negotiating on language, so all are * acceptable, and we set the default q value to 1.0. However if * some of the variants have languages, we set this default to 0.001. * The value of this default will be applied to all variants with * no explicit language -- which will have the effect of making them * acceptable, but only if no variants with an explicit language * are acceptable. The default q value set here is assigned to variants * with no language type in set_language_quality(). * * Note that if using the RVSA/1.0 algorithm, we don't use this * fiddle.   */static void set_default_lang_quality(negotiation_state *neg){    var_rec *avail_recs = (var_rec *) neg->avail_vars->elts;    int j;    if (!neg->dont_fiddle_headers) {        for (j = 0; j < neg->avail_vars->nelts; ++j) {            var_rec *variant = &avail_recs[j];            if (variant->content_languages &&                variant->content_languages->nelts) {                neg->default_lang_quality = 0.001f;                return;            }        }    }    neg->default_lang_quality = 1.0f;}/* Set the language_quality value in the variant record. Also * assigns lang_index for back-compat.  * * To find the language_quality value, we look for the 'q' value * of the 'best' matching language on the Accept-Language * header. The 'best' match is the language on Accept-Language * header which matches the language of this variant either fully, * or as far as the prefix marker (-). If two or more languages * match, use the longest string from the Accept-Language header * (see HTTP/1.1 [14.4]) * * When a variant has multiple languages, we find the 'best' * match for each variant language tag as above, then select the * one with the highest q value. Because both the accept-header * and variant can have multiple languages, we now have a hairy * loop-within-a-loop here. * * If the variant has no language and we have no Accept-Language * items, leave the quality at 1.0 and return. * * If the variant has no language, we use the default as set by * set_default_lang_quality() (1.0 if we are not negotiating on * language, 0.001 if we are). * * Following the setting of the language quality, we drop through to * set the old 'lang_index'. This is set based on either the order * of the languages on the Accept-Language header, or the * order on the LanguagePriority directive. This is only used * in the negotiation if the language qualities tie. */static void set_language_quality(negotiation_state *neg, var_rec *variant){    char *firstlang;    int idx;    if (!variant->content_languages || !variant->content_languages->nelts) {        /* This variant has no content-language, so use the default         * quality factor for variants with no content-language         * (previously set by set_default_lang_quality()).         * Leave the factor alone (it remains at 1.0) when we may not fiddle         * with the headers.         */        if (!neg->dont_fiddle_headers) {            variant->lang_quality = neg->default_lang_quality;        }        if (!neg->accept_langs) {            return;             /* no accept-language header */        }    }    else {        /* Variant has one (or more) languages.  Look for the best         * match. We do this by going through each language on the         * variant description looking for a match on the         * Accept-Language header. The best match is the longest         * matching language on the header. The final result is the         * best q value from all the languages on the variant         * description.         */        if (!neg->accept_langs) {            /* no accept-language header makes the variant indefinite */            variant->definite = 0;        }        else {    /* There is an accept-language with 0 or more items */            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, 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 (((int)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;        }    }    /* Now set the old lang_index field. Since this is old      * stuff anyway, don't bother with handling multiple languages     * per variant, just use the first one assigned to it      */    idx = 0;    if (variant->content_languages && variant->content_languages->nelts) {        firstlang = ((char **) variant->content_languages->elts)[0];    }    else {        firstlang = "";    }    if (!neg->accept_langs) {   /* Client doesn't care */        idx = find_default_index((neg_dir_config *) ap_get_module_config(                                  neg->r->per_dir_config, &negotiation_module),                                 firstlang);    }    else {                      /* Client has Accept-Language */        idx = find_lang_index(neg->accept_langs, firstlang);    }    variant->lang_index = idx;    return;}/* Determining the content length --- if the map didn't tell us, * we have to do a stat() and remember for next time. * * Grump.  For Apache, even the first stat here may well be * redundant (for multiviews) with a stat() done by the sub_req * machinery.  At some point, that ought to be fixed. */static float find_content_length(negotiation_state *neg, var_rec *variant){    struct stat statb;    if (variant->bytes == 0) {        char *fullname = ap_make_full_path(neg->pool, neg->dir_name,                                           variant->file_name);        if (stat(fullname, &statb) >= 0) {            /* Note, precision may be lost */            variant->bytes = (float) statb.st_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)

⌨️ 快捷键说明

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