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

📄 mod_negotiation.c

📁 最新apache的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* put a copy of the tag *after* the data read from the file     * so that strstr() will find something with no reliance on     * terminating '\0'     */    memcpy(buffer + *len, tag, taglen);    endbody = strstr(buffer, tag);    if (endbody == buffer + *len) {        return -1;    }    bodylen = endbody - buffer;    endbody += strlen(tag);    /* Skip all the trailing cruft after the end tag to the next line */    while (*endbody) {        if (*endbody == '\n') {            ++endbody;            break;        }        ++endbody;    }    pos = -(apr_off_t)(*len - (endbody - buffer));    if (apr_file_seek(map, APR_CUR, &pos) != APR_SUCCESS) {        return -1;    }    /* Give the caller back the actual body's file offset and length */    *len = bodylen;    return pos - (endbody - buffer);}/* Stripping out RFC822 comments */static void strip_paren_comments(char *hdr){    /* Hmmm... is this correct?  In Roy's latest draft, (comments) can nest! */    /* Nope, it isn't correct.  Fails to handle backslash escape as well.    */    while (*hdr) {        if (*hdr == '"') {            hdr = strchr(hdr, '"');            if (hdr == NULL) {                return;            }            ++hdr;        }        else if (*hdr == '(') {            while (*hdr && *hdr != ')') {                *hdr++ = ' ';            }            if (*hdr) {                *hdr++ = ' ';            }        }        else {            ++hdr;        }    }}/* Getting to a header body from the header */static char *lcase_header_name_return_body(char *header, request_rec *r){    char *cp = header;    for ( ; *cp && *cp != ':' ; ++cp) {        *cp = apr_tolower(*cp);    }    if (!*cp) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      "Syntax error in type map, no ':' in %s for header %s",                      r->filename, header);        return NULL;    }    do {        ++cp;    } while (*cp && apr_isspace(*cp));    if (!*cp) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      "Syntax error in type map --- no header body: %s for %s",                      r->filename, header);        return NULL;    }    return cp;}static int read_type_map(apr_file_t **map, negotiation_state *neg,                         request_rec *rr){    request_rec *r = neg->r;    apr_file_t *map_ = NULL;    apr_status_t status;    char buffer[MAX_STRING_LEN];    enum header_state hstate;    struct var_rec mime_info;    int has_content;    if (!map)        map = &map_;    /* We are not using multiviews */    neg->count_multiviews_variants = 0;    if ((status = apr_file_open(map, rr->filename, APR_READ | APR_BUFFERED,                APR_OS_DEFAULT, neg->pool)) != APR_SUCCESS) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,                      "cannot access type map file: %s", rr->filename);        return HTTP_FORBIDDEN;    }    clean_var_rec(&mime_info);    has_content = 0;    do {        hstate = get_header_line(buffer, MAX_STRING_LEN, *map);        if (hstate == header_seen) {            char *body1 = lcase_header_name_return_body(buffer, neg->r);            const char *body;            if (body1 == NULL) {                return HTTP_INTERNAL_SERVER_ERROR;            }            strip_paren_comments(body1);            body = body1;            if (!strncmp(buffer, "uri:", 4)) {                mime_info.file_name = ap_get_token(neg->pool, &body, 0);            }            else if (!strncmp(buffer, "content-type:", 13)) {                struct accept_rec accept_info;                get_entry(neg->pool, &accept_info, body);                set_mime_fields(&mime_info, &accept_info);                has_content = 1;            }            else if (!strncmp(buffer, "content-length:", 15)) {                mime_info.bytes = apr_atoi64((char *)body);                has_content = 1;            }            else if (!strncmp(buffer, "content-language:", 17)) {                mime_info.content_languages = do_languages_line(neg->pool,                                                                &body);                has_content = 1;            }            else if (!strncmp(buffer, "content-encoding:", 17)) {                mime_info.content_encoding = ap_get_token(neg->pool, &body, 0);                has_content = 1;            }            else if (!strncmp(buffer, "description:", 12)) {                char *desc = apr_pstrdup(neg->pool, body);                char *cp;                for (cp = desc; *cp; ++cp) {                    if (*cp=='\n') *cp=' ';                }                if (cp>desc) *(cp-1)=0;                mime_info.description = desc;            }            else if (!strncmp(buffer, "body:", 5)) {                char *tag = apr_pstrdup(neg->pool, body);                char *eol = strchr(tag, '\0');                apr_size_t len = MAX_STRING_LEN;                while (--eol >= tag && apr_isspace(*eol))                    *eol = '\0';                if ((mime_info.body = get_body(buffer, &len, tag, *map)) < 0) {                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                                  "Syntax error in type map, no end tag '%s'"                                  "found in %s for Body: content.",                                  tag, r->filename);                     break;                }                mime_info.bytes = len;                mime_info.file_name = apr_filename_of_pathname(rr->filename);            }        }        else {            if (*mime_info.file_name && has_content) {                void *new_var = apr_array_push(neg->avail_vars);                memcpy(new_var, (void *) &mime_info, sizeof(var_rec));            }            clean_var_rec(&mime_info);            has_content = 0;        }    } while (hstate != header_eof);    if (map_)        apr_file_close(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;    apr_dir_t *dirp;    apr_finfo_t dirent;    apr_status_t status;    struct var_rec mime_info;    struct accept_rec accept_info;    void *new_var;    int anymatch = 0;    clean_var_rec(&mime_info);    if (r->proxyreq || !r->filename                    || !ap_os_is_path_absolute(neg->pool, r->filename)) {        return DECLINED;    }    /* Only absolute paths here */    if (!(filp = strrchr(r->filename, '/'))) {        return DECLINED;    }    ++filp;    prefix_len = strlen(filp);    if ((status = apr_dir_open(&dirp, neg->dir_name,                               neg->pool)) != APR_SUCCESS) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,                    "cannot read directory for multi: %s", neg->dir_name);        return HTTP_FORBIDDEN;    }    while (apr_dir_read(&dirent, APR_FINFO_DIRENT, dirp) == APR_SUCCESS) {        apr_array_header_t *exception_list;        request_rec *sub_req;        /* Do we have a match? */#ifdef CASE_BLIND_FILESYSTEM        if (strncasecmp(dirent.name, filp, prefix_len)) {#else        if (strncmp(dirent.name, filp, prefix_len)) {#endif            continue;        }        if (dirent.name[prefix_len] != '.') {            continue;        }        /* Don't negotiate directories and other unusual files         * Really shouldn't see anything but DIR/LNK/REG here,         * and we aught to discover if the LNK was interesting.         *         * Of course, this only helps platforms that capture the         * the filetype in apr_dir_read(), which most can once         * they are optimized with some magic [it's known to the         * dirent, not associated to the inode, on most FS's.]         */        if ((dirent.valid & APR_FINFO_TYPE) && (dirent.filetype == APR_DIR))            continue;        /* Ok, something's here.  Maybe nothing useful.  Remember that         * we tried, if we completely fail, so we can reject the request!         */        anymatch = 1;        /* 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_dirent(&dirent, r, AP_SUBREQ_MERGE_ARGS,                                           NULL);        /* Double check, we still don't multi-resolve non-ordinary files         */        if (sub_req->finfo.filetype != APR_REG)            continue;        /* 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) {            ap_set_content_type(sub_req, CGI_MAGIC_TYPE);        }        /*         * 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 =            (apr_array_header_t *)apr_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) &&

⌨️ 快捷键说明

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