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

📄 util.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 4 页
字号:
        register int c;        register size_t i = 0;        buf[0] = '\0';        /* skip leading whitespace */        do {            c = cfp->getch(cfp->param);        } while (c == '\t' || c == ' ');        if (c == EOF)            return 1;                if(bufsize < 2) {            /* too small, assume caller is crazy */            return 1;        }        while (1) {            if ((c == '\t') || (c == ' ')) {                buf[i++] = ' ';                while ((c == '\t') || (c == ' '))                    c = cfp->getch(cfp->param);            }            if (c == CR) {                /* silently ignore CR (_assume_ that a LF follows) */                c = cfp->getch(cfp->param);            }            if (c == LF) {                /* increase line number and return on LF */                ++cfp->line_number;            }            if (c == EOF || c == 0x4 || c == LF || i >= (bufsize - 2)) {                /*                  *  check for line continuation                 */                if (i > 0 && buf[i-1] == '\\') {                    i--;                    if (!(i > 0 && buf[i-1] == '\\')) {                        /* line is continued */                        c = cfp->getch(cfp->param);                        continue;                    }                    /* else nothing needs be done because                     * then the backslash is escaped and                     * we just strip to a single one                     */                }                /* blast trailing whitespace */                while (i > 0 && apr_isspace(buf[i - 1]))                    --i;                buf[i] = '\0';#ifdef DEBUG_CFG_LINES                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,                             "Read config: %s", buf);#endif                return 0;            }            buf[i] = c;            ++i;            c = cfp->getch(cfp->param);        }    }}/* Size an HTTP header field list item, as separated by a comma. * The return value is a pointer to the beginning of the non-empty list item * within the original string (or NULL if there is none) and the address * of field is shifted to the next non-comma, non-whitespace character. * len is the length of the item excluding any beginning whitespace. */AP_DECLARE(const char *) ap_size_list_item(const char **field, int *len){    const unsigned char *ptr = (const unsigned char *)*field;    const unsigned char *token;    int in_qpair, in_qstr, in_com;    /* Find first non-comma, non-whitespace byte */    while (*ptr == ',' || apr_isspace(*ptr))        ++ptr;    token = ptr;    /* Find the end of this item, skipping over dead bits */    for (in_qpair = in_qstr = in_com = 0;         *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');         ++ptr) {        if (in_qpair) {            in_qpair = 0;        }        else {            switch (*ptr) {                case '\\': in_qpair = 1;      /* quoted-pair         */                           break;                case '"' : if (!in_com)       /* quoted string delim */                               in_qstr = !in_qstr;                           break;                case '(' : if (!in_qstr)      /* comment (may nest)  */                               ++in_com;                           break;                case ')' : if (in_com)        /* end comment         */                               --in_com;                           break;                default  : break;            }        }    }    if ((*len = (ptr - token)) == 0) {        *field = (const char *)ptr;        return NULL;    }    /* Advance field pointer to the next non-comma, non-white byte */    while (*ptr == ',' || apr_isspace(*ptr))        ++ptr;    *field = (const char *)ptr;    return (const char *)token;}/* Retrieve an HTTP header field list item, as separated by a comma, * while stripping insignificant whitespace and lowercasing anything not in * a quoted string or comment.  The return value is a new string containing * the converted list item (or NULL if none) and the address pointed to by * field is shifted to the next non-comma, non-whitespace. */AP_DECLARE(char *) ap_get_list_item(apr_pool_t *p, const char **field){    const char *tok_start;    const unsigned char *ptr;    unsigned char *pos;    char *token;    int addspace = 0, in_qpair = 0, in_qstr = 0, in_com = 0, tok_len = 0;    /* Find the beginning and maximum length of the list item so that     * we can allocate a buffer for the new string and reset the field.     */    if ((tok_start = ap_size_list_item(field, &tok_len)) == NULL) {        return NULL;    }    token = apr_palloc(p, tok_len + 1);    /* Scan the token again, but this time copy only the good bytes.     * We skip extra whitespace and any whitespace around a '=', '/',     * or ';' and lowercase normal characters not within a comment,     * quoted-string or quoted-pair.     */    for (ptr = (const unsigned char *)tok_start, pos = (unsigned char *)token;         *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');         ++ptr) {        if (in_qpair) {            in_qpair = 0;            *pos++ = *ptr;        }        else {            switch (*ptr) {                case '\\': in_qpair = 1;                           if (addspace == 1)                               *pos++ = ' ';                           *pos++ = *ptr;                           addspace = 0;                           break;                case '"' : if (!in_com)                               in_qstr = !in_qstr;                           if (addspace == 1)                               *pos++ = ' ';                           *pos++ = *ptr;                           addspace = 0;                           break;                case '(' : if (!in_qstr)                               ++in_com;                           if (addspace == 1)                               *pos++ = ' ';                           *pos++ = *ptr;                           addspace = 0;                           break;                case ')' : if (in_com)                               --in_com;                           *pos++ = *ptr;                           addspace = 0;                           break;                case ' ' :                case '\t': if (addspace)                               break;                           if (in_com || in_qstr)                               *pos++ = *ptr;                           else                               addspace = 1;                           break;                case '=' :                case '/' :                case ';' : if (!(in_com || in_qstr))                               addspace = -1;                           *pos++ = *ptr;                           break;                default  : if (addspace == 1)                               *pos++ = ' ';                           *pos++ = (in_com || in_qstr) ? *ptr                                                        : apr_tolower(*ptr);                           addspace = 0;                           break;            }        }    }    *pos = '\0';    return token;}/* Find an item in canonical form (lowercase, no extra spaces) within * an HTTP field value list.  Returns 1 if found, 0 if not found. * This would be much more efficient if we stored header fields as * an array of list items as they are received instead of a plain string. */AP_DECLARE(int) ap_find_list_item(apr_pool_t *p, const char *line,                                  const char *tok){    const unsigned char *pos;    const unsigned char *ptr = (const unsigned char *)line;    int good = 0, addspace = 0, in_qpair = 0, in_qstr = 0, in_com = 0;    if (!line || !tok)        return 0;    do {  /* loop for each item in line's list */        /* Find first non-comma, non-whitespace byte */        while (*ptr == ',' || apr_isspace(*ptr))            ++ptr;        if (*ptr)            good = 1;  /* until proven otherwise for this item */        else            break;     /* no items left and nothing good found */        /* We skip extra whitespace and any whitespace around a '=', '/',         * or ';' and lowercase normal characters not within a comment,         * quoted-string or quoted-pair.         */        for (pos = (const unsigned char *)tok;             *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');             ++ptr) {            if (in_qpair) {                in_qpair = 0;                if (good)                    good = (*pos++ == *ptr);            }            else {                switch (*ptr) {                    case '\\': in_qpair = 1;                               if (addspace == 1)                                   good = good && (*pos++ == ' ');                               good = good && (*pos++ == *ptr);                               addspace = 0;                               break;                    case '"' : if (!in_com)                                   in_qstr = !in_qstr;                               if (addspace == 1)                                   good = good && (*pos++ == ' ');                               good = good && (*pos++ == *ptr);                               addspace = 0;                               break;                    case '(' : if (!in_qstr)                                   ++in_com;                               if (addspace == 1)                                   good = good && (*pos++ == ' ');                               good = good && (*pos++ == *ptr);                               addspace = 0;                               break;                    case ')' : if (in_com)                                   --in_com;                               good = good && (*pos++ == *ptr);                               addspace = 0;                               break;                    case ' ' :                    case '\t': if (addspace || !good)                                   break;                               if (in_com || in_qstr)                                   good = (*pos++ == *ptr);                               else                                   addspace = 1;                               break;                    case '=' :                    case '/' :                    case ';' : if (!(in_com || in_qstr))                                   addspace = -1;                               good = good && (*pos++ == *ptr);                               break;                    default  : if (!good)                                   break;                               if (addspace == 1)                                   good = (*pos++ == ' ');                               if (in_com || in_qstr)                                   good = good && (*pos++ == *ptr);                               else                                   good = good && (*pos++ == apr_tolower(*ptr));                               addspace = 0;                               break;                }            }        }        if (good && *pos)            good = 0;          /* not good if only a prefix was matched */    } while (*ptr && !good);    return good;}/* Retrieve a token, spacing over it and returning a pointer to * the first non-white byte afterwards.  Note that these tokens * are delimited by semis and commas; and can also be delimited * by whitespace at the caller's option. */AP_DECLARE(char *) ap_get_token(apr_pool_t *p, const char **accept_line,                                int accept_white){    const char *ptr = *accept_line;    const char *tok_start;    char *token;    int tok_len;    /* Find first non-white byte */    while (*ptr && apr_isspace(*ptr))        ++ptr;    tok_start = ptr;    /* find token end, skipping over quoted strings.     * (comments are already gone).     */    while (*ptr && (accept_white || !apr_isspace(*ptr))           && *ptr != ';' && *ptr != ',') {        if (*ptr++ == '"')            while (*ptr)                if (*ptr++ == '"')                    break;    }    tok_len = ptr - tok_start;    token = apr_pstrndup(p, tok_start, tok_len);    /* Advance accept_line pointer to the next non-white byte */    while (*ptr && apr_isspace(*ptr))        ++ptr;    *accept_line = ptr;    return token;}/* find http tokens, see the definition of token from RFC2068 */AP_DECLARE(int) ap_find_token(apr_pool_t *p, const char *line, const char *tok){    const unsigned char *start_token;    const unsigned char *s;    if (!line)        return 0;    s = (const unsigned char *)line;    for (;;) {        /* find start of token, skip all stop characters, note NUL         * isn't a token stop, so we don't need to test for it         */        while (TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) {            ++s;        }        if (!*s) {            return 0;        }        start_token = s;        /* find end of the token */        while (*s && !TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) {            ++s;        }        if (!strncasecmp((const char *)start_token, (const char *)tok,                         s - start_token)) {            return 1;        }        if (!*s) {            return 0;        }    }}AP_DECLARE(int) ap_find_last_token(apr_pool_t *p, const char *line,                                   const char *tok){    int llen, tlen, lidx;    if (!line)        return 0;    llen = strlen(line);    tlen = strlen(tok);    lidx = llen - tlen;    if (lidx < 0 ||        (lidx > 0 && !(apr_isspace(line[lidx - 1]) || line[lidx - 1] == ',')))        return 0;    return (strncasecmp(&line[lidx], tok, tlen) == 0);}AP_DECLARE(char *) ap_escape_shell_cmd(apr_pool_t *p, const char *str){    char *cmd;    unsigned char *d;    const unsigned char *s;    cmd = apr_palloc(p, 2 * strlen(str) + 1);        /* Be safe */    d = (unsigned char *)cmd;    s = (const unsigned char *)str;    for (; *s; ++s) {#if defined(OS2) || defined(WIN32)        /*          * Newlines to Win32/OS2 CreateProcess() are ill advised.         * Convert them to spaces since they are effectively white         * space to most applications         */        if (*s == '\r' || *s == '\n') {             *d++ = ' ';             continue;         }#endif        if (TEST_CHAR(*s, T_ESCAPE_SHELL_CMD)) {            *d++ = '\\';        }        *d++ = *s;    }    *d = '\0';    return cmd;}static char x2c(const char *what){    register char digit;#if !APR_CHARSET_EBCDIC    digit = ((what[0] >= 'A') ? ((what[0] & 0xdf) - 'A') + 10             : (what[0] - '0'));    digit *= 16;    digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A') + 10              : (what[1] - '0'));#else /*APR_CHARSET_EBCDIC*/    char xstr[5];    xstr[0]='0';    xstr[1]='x';    xstr[2]=what[0];    xstr[3]=what[1];    xstr[4]='\0';    digit = apr_xlate_conv_byte(ap_hdrs_from_ascii,                                0xFF & strtol(xstr, NULL, 16));#endif /*APR_CHARSET_EBCDIC*/    return (digit);}/* * Unescapes a URL. * Returns 0 on success, non-zero on error * Failure is due to *   bad % escape       returns HTTP_BAD_REQUEST * *   decoding %00 -> \0  (the null character) *   decoding %2f -> /   (a special character) *                      returns HTTP_NOT_FOUND */AP_DECLARE(int) ap_unescape_url(char *url){    register int badesc, badpath;    char *x, *y;    badesc = 0;    badpath = 0;    /* Initial scan for first '%'. Don't bother writing values before     * seeing a '%' */    y = strchr(url, '%');    if (y == NULL) {        return OK;    }    for (x = y; *y; ++x, ++y) {        if (*y != '%')            *x = *y;        else {            if (!apr_isxdigit(*(y + 1)) || !apr_isxdigit(*(y + 2))) {                badesc = 1;                *x = '%';            }            else {                *x = x2c(y + 1);                y += 2;                if (IS_SLASH(*x) || *x == '\0')                    badpath = 1;            }        }    }    *x = '\0';    if (badesc)        return HTTP_BAD_REQUEST;    else if (badpath)        return HTTP_NOT_FOUND;    else        return OK;}AP_DECLARE(int) ap_unescape_url_keep2f(char *url){    register int badesc, badpath;    char *x, *y;    badesc = 0;    badpath = 0;    /* Initial scan for first '%'. Don't bother writing values before     * seeing a '%' */    y = strchr(url, '%');    if (y == NULL) {        return OK;    }    for (x = y; *y; ++x, ++y) {        if (*y != '%') {            *x = *y;        }        else {            if (!apr_isxdigit(*(y + 1)) || !apr_isxdigit(*(y + 2))) {                badesc = 1;

⌨️ 快捷键说明

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