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

📄 mod_negotiation.c

📁 apache简化版
💻 C
📖 第 1 页 / 共 5 页
字号:
 * Dealing with header lines ... * * Accept, Accept-Charset, Accept-Language and Accept-Encoding * are handled by do_header_line() - they all have the same * basic structure of a list of items of the format *    name; q=N; charset=TEXT * * where q is only valid in Accept, Accept-Charset and Accept-Languages, * and charset is only valid in Accept. */static array_header *do_header_line(pool *p, const char *accept_line){    array_header *accept_recs = ap_make_array(p, 40, sizeof(accept_rec));    if (!accept_line) {        return accept_recs;    }    while (*accept_line) {        accept_rec *new = (accept_rec *) ap_push_array(accept_recs);        accept_line = get_entry(p, new, accept_line);    }    return accept_recs;}/* Given the text of the Content-Languages: line from the var map file, * return an array containing the languages of this variant */static array_header *do_languages_line(pool *p, const char **lang_line){    array_header *lang_recs = ap_make_array(p, 2, sizeof(char *));    if (!lang_line) {        return lang_recs;    }    while (**lang_line) {        char **new = (char **) ap_push_array(lang_recs);        *new = ap_get_token(p, lang_line, 0);        ap_str_tolower(*new);        if (**lang_line == ',' || **lang_line == ';') {            ++(*lang_line);        }    }    return lang_recs;}/***************************************************************** * * Handling header lines from clients... */static negotiation_state *parse_accept_headers(request_rec *r){    negotiation_state *new = (negotiation_state *) ap_pcalloc(r->pool,                                                 sizeof(negotiation_state));    accept_rec *elts;    table *hdrs = r->headers_in;    int i;    const char *hdr;    new->pool = r->pool;    new->r = r;    new->dir_name = ap_make_dirstr_parent(r->pool, r->filename);    new->accepts = do_header_line(r->pool, ap_table_get(hdrs, "Accept"));    hdr = ap_table_get(hdrs, "Accept-encoding");    if (hdr) {        new->have_accept_header = 1;    }    new->accept_encodings = do_header_line(r->pool, hdr);    new->accept_langs = do_header_line(r->pool,                                       ap_table_get(hdrs, "Accept-language"));    new->accept_charsets = do_header_line(r->pool,                                          ap_table_get(hdrs, "Accept-charset"));    new->avail_vars = ap_make_array(r->pool, 40, sizeof(var_rec));#ifdef TCN_02    if (ap_table_get(r->headers_in, "Negotiate")) {        /* Negotiate: header tells us UA does transparent negotiation         * We have to decide whether we want to ... for now, yes,         * we do */        new->ua_can_negotiate = 1;        if (r->method_number == M_GET) {            new->use_transparent_neg = 1;       /* should be configurable */        }        /* Check for 'Short Accept', ie either no Accept: header,         * or just "Accept: * / *" */        if (new->accepts->nelts == 0 ||            (new->accepts->nelts == 1 &&             (!strcmp(((accept_rec *) new->accepts->elts)[0].type_name,                      "*/*")))) {            /* Using short accept header */            new->short_accept_headers = 1;        }    }#endif    if (!new->use_transparent_neg) {        /* Now we check for q-values. If they're all 1.0, we assume the         * client is "broken", and we are allowed to fiddle with the         * values later. Otherwise, we leave them alone.         */        elts = (accept_rec *) new->accepts->elts;        for (i = 0; i < new->accepts->nelts; ++i) {            if (elts[i].quality < 1.0) {                new->accept_q = 1;            }        }    }    else {        new->accept_q = 1;    }    return new;}/* Sometimes clients will give us no Accept info at all; this routine sets * up the standard default for that case, and also arranges for us to be * willing to run a CGI script if we find one.  (In fact, we set up to * dramatically prefer CGI scripts in cases where that's appropriate, * e.g., POST). */static void maybe_add_default_encodings(negotiation_state *neg, int prefer_scripts){    accept_rec *new_accept = (accept_rec *) ap_push_array(neg->accepts);    new_accept->type_name = CGI_MAGIC_TYPE;    new_accept->quality = prefer_scripts ? 1e-20f : 1e20f;    new_accept->level = 0.0f;    new_accept->max_bytes = 0.0f;    if (neg->accepts->nelts > 1) {        return;    }    new_accept = (accept_rec *) ap_push_array(neg->accepts);    new_accept->type_name = "*/*";    new_accept->quality = 1.0f;    new_accept->level = 0.0f;    new_accept->max_bytes = 0.0f;}/***************************************************************** * * Parsing type-map files, in Roy's meta/http format augmented with * #-comments. *//* Reading RFC822-style header lines, ignoring #-comments and * handling continuations. */enum header_state {    header_eof, header_seen, header_sep};static enum header_state get_header_line(char *buffer, int len, FILE *map){    char *buf_end = buffer + len;    char *cp;    int c;    /* Get a noncommented line */    do {        if (fgets(buffer, MAX_STRING_LEN, map) == NULL) {            return header_eof;        }    } while (buffer[0] == '#');    /* If blank, just return it --- this ends information on this variant */    for (cp = buffer; (*cp && ap_isspace(*cp)); ++cp) {        continue;    }    if (*cp == '\0') {        return header_sep;    }    /* If non-blank, go looking for header lines, but note that we still     * have to treat comments specially...     */    cp += strlen(cp);    while ((c = getc(map)) != EOF) {        if (c == '#') {            /* Comment line */            while ((c = getc(map)) != EOF && c != '\n') {                continue;            }        }        else if (ap_isspace(c)) {            /* Leading whitespace.  POSSIBLE continuation line             * Also, possibly blank --- if so, we ungetc() the final newline             * so that we will pick up the blank line the next time 'round.             */            while (c != EOF && c != '\n' && ap_isspace(c)) {                c = getc(map);            }            ungetc(c, map);            if (c == '\n') {                return header_seen;     /* Blank line */            }            /* Continuation */            while (cp < buf_end - 2 && (c = getc(map)) != EOF && c != '\n') {                *cp++ = c;            }            *cp++ = '\n';            *cp = '\0';        }        else {            /* Line beginning with something other than whitespace */            ungetc(c, map);            return header_seen;        }    }    return header_seen;}/* Stripping out RFC822 comments */static void strip_paren_comments(char *hdr){    /* Hmmm... is this correct?  In Roy's latest draft, (comments) can nest! */    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 = ap_tolower(*cp);    }    if (!*cp) {        ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,                    "Syntax error in type map --- no ':': %s", r->filename);        return NULL;    }    do {        ++cp;    } while (*cp && ap_isspace(*cp));    if (!*cp) {        ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,                    "Syntax error in type map --- no header body: %s",                    r->filename);        return NULL;    }    return cp;}static int read_type_map(negotiation_state *neg, request_rec *rr){    request_rec *r = neg->r;    FILE *map;    char buffer[MAX_STRING_LEN];    enum header_state hstate;    struct var_rec mime_info;    /* We are not using multiviews */    neg->count_multiviews_variants = 0;    map = ap_pfopen(neg->pool, rr->filename, "r");    if (map == NULL) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, r,                    "cannot access type map file: %s", rr->filename);        return HTTP_FORBIDDEN;    }    clean_var_rec(&mime_info);    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 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);            }            else if (!strncmp(buffer, "content-length:", 15)) {                mime_info.bytes = atof(body);            }            else if (!strncmp(buffer, "content-language:", 17)) {                mime_info.content_languages = do_languages_line(neg->pool,                                                                &body);            }            else if (!strncmp(buffer, "content-encoding:", 17)) {                mime_info.content_encoding = ap_get_token(neg->pool, &body, 0);            }            else if (!strncmp(buffer, "description:", 12)) {                mime_info.description = ap_get_token(neg->pool, &body, 0);            }        }        else {            if (mime_info.type_quality > 0 && *mime_info.file_name) {                void *new_var = ap_push_array(neg->avail_vars);                memcpy(new_var, (void *) &mime_info, sizeof(var_rec));            }            clean_var_rec(&mime_info);        }    } while (hstate != header_eof);    ap_pfclose(neg->pool, map);    return OK;}/***************************************************************** * * Same, 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;    clean_var_rec(&mime_info);    if (!(filp = strrchr(r->filename, '/'))) {        return DECLINED;        /* Weird... */    }    if (strncmp(r->filename, "proxy:", 6) == 0) {        return DECLINED;    }

⌨️ 快捷键说明

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