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

📄 mod_negotiation.c

📁 apache 安装教程 apache 安装教程
💻 C
📖 第 1 页 / 共 5 页
字号:
                for (cp = desc; *cp; ++cp) {                    if (*cp=='\n') *cp=' ';                }                if (cp>desc) *(cp-1)=0;                mime_info.description = desc;            }        }        else {            if (*mime_info.file_name && has_content) {                void *new_var = ap_push_array(neg->avail_vars);                memcpy(new_var, (void *) &mime_info, sizeof(var_rec));            }            clean_var_rec(&mime_info);            has_content = 0;        }    } while (hstate != header_eof);    ap_pfclose(neg->pool, map);    set_vlist_validator(r, rr);    return OK;}/* Sort function used by read_types_multi. */static int variantsortf(var_rec *a, var_rec *b) {    /* First key is the source quality, sort in descending order. */    /* XXX: note that we currently implement no method of setting the     * source quality for multiviews variants, so we are always comparing     * 1.0 to 1.0 for now     */    if (a->source_quality < b->source_quality)        return 1;    if (a->source_quality > b->source_quality)        return -1;    /* Second key is the variant name */    return strcmp(a->file_name, b->file_name);}/***************************************************************** * * Same as read_type_map, except we use a filtered directory listing * as the map...   */static int read_types_multi(negotiation_state *neg){    request_rec *r = neg->r;    char *filp;    int prefix_len;    DIR *dirp;    struct DIR_TYPE *dir_entry;    struct var_rec mime_info;    struct accept_rec accept_info;    void *new_var;    struct { int any, all; } forbidden;    clean_var_rec(&mime_info);    if (!(filp = strrchr(r->filename, '/'))) {        return DECLINED;        /* Weird... */    }    if (strncmp(r->filename, "proxy:", 6) == 0) {        return DECLINED;    }    ++filp;    prefix_len = strlen(filp);    dirp = ap_popendir(neg->pool, neg->dir_name);    if (dirp == NULL) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, r,                    "cannot read directory for multi: %s", neg->dir_name);        return HTTP_FORBIDDEN;    }    forbidden.any = 0;    forbidden.all = 1;    while ((dir_entry = readdir(dirp))) {        array_header *exception_list;        request_rec *sub_req;        /* Do we have a match? */#ifdef CASE_BLIND_FILESYSTEM        if (strncasecmp(dir_entry->d_name, filp, prefix_len)) {#else        if (strncmp(dir_entry->d_name, filp, prefix_len)) {#endif            continue;        }        if (dir_entry->d_name[prefix_len] != '.') {            continue;        }        /* Yep.  See if it's something which we have access to, and          * which has a known type and encoding (as opposed to something         * which we'll be slapping default_type on later).         */        sub_req = ap_sub_req_lookup_file(dir_entry->d_name, r);        /* If it has a handler, we'll pretend it's a CGI script,         * since that's a good indication of the sort of thing it         * might be doing.         */        if (sub_req->handler && !sub_req->content_type) {            sub_req->content_type = CGI_MAGIC_TYPE;        }        /* HTTP_FORBIDDEN is returned, e.g., if the path length limit was exceeded */        /* HTTP_OK does NOT necessarily mean that the file is really readable! */        if (sub_req->status == HTTP_OK)            forbidden.all = 0;        else if (sub_req->status == HTTP_FORBIDDEN)            forbidden.any = 1;        /*          * mod_mime will _always_ provide us the base name in the         * ap-mime-exception-list, if it processed anything.  If         * this list is empty, give up immediately, there was         * nothing interesting.  For example, looking at the files         * readme.txt and readme.foo, we will throw away .foo if         * it's an insignificant file (e.g. did not identify a          * language, charset, encoding, content type or handler,)         */        exception_list =             (array_header *) ap_table_get(sub_req->notes,                                          "ap-mime-exceptions-list");        if (!exception_list) {            ap_destroy_sub_req(sub_req);            continue;        }        /* Each unregonized bit better match our base name, in sequence.         * A test of index.html.foo will match index.foo or index.html.foo,         * but it will never transpose the segments and allow index.foo.html         * because that would introduce too much CPU consumption.  Better that         * we don't attempt a many-to-many match here.         */        {            int nexcept = exception_list->nelts;            char **cur_except = (char**)exception_list->elts;            char *segstart = filp, *segend, saveend;            while (*segstart && nexcept) {                if (!(segend = strchr(segstart, '.')))                    segend = strchr(segstart, '\0');                saveend = *segend;                *segend = '\0';#ifdef CASE_BLIND_FILESYSTEM                if (strcasecmp(segstart, *cur_except) == 0) {#else                if (strcmp(segstart, *cur_except) == 0) {#endif                    --nexcept;                    ++cur_except;                }                if (!saveend)                    break;                *segend = saveend;                segstart = segend + 1;            }            if (nexcept) {                /* Something you don't know is, something you don't know...                 */                ap_destroy_sub_req(sub_req);                continue;            }        }        /*          * ###: be warned, the _default_ content type is already         * picked up here!  If we failed the subrequest, or don't          * know what we are serving, then continue.         */        if (sub_req->status != HTTP_OK || (!sub_req->content_type)) {            ap_destroy_sub_req(sub_req);            continue;        }        /* If it's a map file, we use that instead of the map         * we're building...         */        if (((sub_req->content_type) &&             !strcmp(sub_req->content_type, MAP_FILE_MAGIC_TYPE)) ||            ((sub_req->handler) &&             !strcmp(sub_req->handler, "type-map"))) {            ap_pclosedir(neg->pool, dirp);            neg->avail_vars->nelts = 0;            if (sub_req->status != HTTP_OK) {                return sub_req->status;            }            return read_type_map(neg, sub_req);        }        /* Have reasonable variant --- gather notes. */        mime_info.sub_req = sub_req;        mime_info.file_name = ap_pstrdup(neg->pool, dir_entry->d_name);        if (sub_req->content_encoding) {            mime_info.content_encoding = sub_req->content_encoding;        }        if (sub_req->content_languages) {            mime_info.content_languages = sub_req->content_languages;        }        get_entry(neg->pool, &accept_info, sub_req->content_type);        set_mime_fields(&mime_info, &accept_info);        new_var = ap_push_array(neg->avail_vars);        memcpy(new_var, (void *) &mime_info, sizeof(var_rec));        neg->count_multiviews_variants++;        clean_var_rec(&mime_info);    }    ap_pclosedir(neg->pool, dirp);    /* If all variants we considered turn out to be forbidden, then return FORBIDDEN */    if (forbidden.any && forbidden.all)        return HTTP_FORBIDDEN;    set_vlist_validator(r, r);    /* Sort the variants into a canonical order.  The negotiation     * result sometimes depends on the order of the variants.  By     * sorting the variants into a canonical order, rather than using     * the order in which readdir() happens to return them, we ensure     * that the negotiation result will be consistent over filesystem     * backup/restores and over all mirror sites.     */           qsort((void *) neg->avail_vars->elts, neg->avail_vars->nelts,          sizeof(var_rec), (int (*)(const void *, const void *)) variantsortf);    return OK;}/***************************************************************** * And now for the code you've been waiting for... actually * finding a match to the client's requirements.   *//* Matching MIME types ... the star/star and foo/star commenting conventions * are implemented here.  (You know what I mean by star/star, but just * try mentioning those three characters in a C comment).  Using strcmp() * is legit, because everything has already been smashed to lowercase. * * Note also that if we get an exact match on the media type, we update * level_matched for use in level_cmp below... *  * We also give a value for mime_stars, which is used later. It should * be 1 for star/star, 2 for type/star and 3 for type/subtype. */static int mime_match(accept_rec *accept_r, var_rec *avail){    char *accept_type = accept_r->name;    char *avail_type = avail->mime_type;    int len = strlen(accept_type);    if (accept_type[0] == '*') {        /* Anything matches star/star */        if (avail->mime_stars < 1) {            avail->mime_stars = 1;        }        return 1;    }    else if ((accept_type[len - 1] == '*') &&             !strncmp(accept_type, avail_type, len - 2)) {        if (avail->mime_stars < 2) {            avail->mime_stars = 2;        }        return 1;    }    else if (!strcmp(accept_type, avail_type)             || (!strcmp(accept_type, "text/html")                 && (!strcmp(avail_type, INCLUDES_MAGIC_TYPE)                     || !strcmp(avail_type, INCLUDES_MAGIC_TYPE3)))) {        if (accept_r->level >= avail->level) {            avail->level_matched = avail->level;            avail->mime_stars = 3;            return 1;        }    }    return OK;}/* This code implements a piece of the tie-breaking algorithm between * variants of equal quality.  This piece is the treatment of variants * of the same base media type, but different levels.  What we want to * return is the variant at the highest level that the client explicitly * claimed to accept. * * If all the variants available are at a higher level than that, or if * the client didn't say anything specific about this media type at all * and these variants just got in on a wildcard, we prefer the lowest * level, on grounds that that's the one that the client is least likely * to choke on. * * (This is all motivated by treatment of levels in HTML --- we only * want to give level 3 to browsers that explicitly ask for it; browsers * that don't, including HTTP/0.9 browsers that only get the implicit * "Accept: * / *" [space added to avoid confusing cpp --- no, that * syntax doesn't really work] should get HTML2 if available). * * (Note that this code only comes into play when we are choosing among * variants of equal quality, where the draft standard gives us a fair * bit of leeway about what to do.  It ain't specified by the standard; * rather, it is a choice made by this server about what to do in cases * where the standard does not specify a unique course of action). */static int level_cmp(var_rec *var1, var_rec *var2){    /* Levels are only comparable between matching media types */    if (var1->is_pseudo_html && !var2->is_pseudo_html) {        return 0;    }    if (!var1->is_pseudo_html && strcmp(var1->mime_type, var2->mime_type)) {        return 0;    }    /* The result of the above if statements is that, if we get to     * here, both variants have the same mime_type or both are     * pseudo-html.     */        /* Take highest level that matched, if either did match. */    if (var1->level_matched > var2->level_matched) {        return 1;    }    if (var1->level_matched < var2->level_matched) {        return -1;    }    /* Neither matched.  Take lowest level, if there's a difference. */    if (var1->level < var2->level) {        return 1;    }    if (var1->level > var2->level) {        return -1;    }    /* Tied */    return 0;}/* Finding languages.  The main entry point is set_language_quality() * which is called for each variant. It sets two elements in the * variant record: *    language_quality  - the 'q' value of the 'best' matching language *                        from Accept-Language: header (HTTP/1.1) *    lang_index    -     Pre HTTP/1.1 language priority, using *                        position of language on the Accept-Language: *                        header, if present, else LanguagePriority *                        directive order. * * When we do the variant checking for best variant, we use language * quality first, and if a tie, language_index next (this only applies * when _not_ using the RVSA/1.0 algorithm). If using the RVSA/1.0 * algorithm, lang_index is never used. * * set_language_quality() calls find_lang_index() and find_default_index() * to set lang_index.   */static int find_lang_index(array_header *accept_langs, char *lang){    accept_rec *accs;    int i;    if (!lang || !accept_langs) {        return -1;

⌨️ 快捷键说明

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