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

📄 util.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Copyright 1999-2005 The Apache Software Foundation or its licensors, as * applicable. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * util.c: string utility things *  * 3/21/93 Rob McCool * 1995-96 Many changes by the Apache Software Foundation *  *//* Debugging aid: * #define DEBUG            to trace all cfg_open*()/cfg_closefile() calls * #define DEBUG_CFG_LINES  to trace every line read from the config files */#include "apr.h"#include "apr_strings.h"#include "apr_lib.h"#define APR_WANT_STDIO#define APR_WANT_STRFUNC#include "apr_want.h"#if APR_HAVE_UNISTD_H#include <unistd.h>#endif#if APR_HAVE_NETDB_H#include <netdb.h>              /* for gethostbyname() */#endif#define CORE_PRIVATE#include "ap_config.h"#include "apr_base64.h"#include "httpd.h"#include "http_main.h"#include "http_log.h"#include "http_protocol.h"#include "http_config.h"#include "util_ebcdic.h"#ifdef HAVE_PWD_H#include <pwd.h>#endif#ifdef HAVE_GRP_H#include <grp.h>#endif/* A bunch of functions in util.c scan strings looking for certain characters. * To make that more efficient we encode a lookup table.  The test_char_table * is generated automatically by gen_test_char.c. */#include "test_char.h"/* we assume the folks using this ensure 0 <= c < 256... which means * you need a cast to (unsigned char) first, you can't just plug a * char in here and get it to work, because if char is signed then it * will first be sign extended. */#define TEST_CHAR(c, f)        (test_char_table[(unsigned)(c)] & (f))/* Win32/NetWare/OS2 need to check for both forward and back slashes * in ap_getparents() and ap_escape_url. */#ifdef CASE_BLIND_FILESYSTEM#define IS_SLASH(s) ((s == '/') || (s == '\\'))#else#define IS_SLASH(s) (s == '/')#endif/* * Examine a field value (such as a media-/content-type) string and return * it sans any parameters; e.g., strip off any ';charset=foo' and the like. */AP_DECLARE(char *) ap_field_noparam(apr_pool_t *p, const char *intype){    const char *semi;    if (intype == NULL) return NULL;    semi = ap_strchr_c(intype, ';');    if (semi == NULL) {        return apr_pstrdup(p, intype);    }     else {        while ((semi > intype) && apr_isspace(semi[-1])) {            semi--;        }        return apr_pstrndup(p, intype, semi - intype);    }}AP_DECLARE(char *) ap_ht_time(apr_pool_t *p, apr_time_t t, const char *fmt,                              int gmt){    apr_size_t retcode;    char ts[MAX_STRING_LEN];    char tf[MAX_STRING_LEN];    apr_time_exp_t xt;    if (gmt) {        const char *f;        char *strp;        apr_time_exp_gmt(&xt, t);        /* Convert %Z to "GMT" and %z to "+0000";         * on hosts that do not have a time zone string in struct tm,         * strftime must assume its argument is local time.         */        for(strp = tf, f = fmt; strp < tf + sizeof(tf) - 6 && (*strp = *f)            ; f++, strp++) {            if (*f != '%') continue;            switch (f[1]) {            case '%':                *++strp = *++f;                break;            case 'Z':                *strp++ = 'G';                *strp++ = 'M';                *strp = 'T';                f++;                break;            case 'z': /* common extension */                *strp++ = '+';                *strp++ = '0';                *strp++ = '0';                *strp++ = '0';                *strp = '0';                f++;                break;            }        }        *strp = '\0';        fmt = tf;    }    else {        apr_time_exp_lt(&xt, t);    }    /* check return code? */    apr_strftime(ts, &retcode, MAX_STRING_LEN, fmt, &xt);    ts[MAX_STRING_LEN - 1] = '\0';    return apr_pstrdup(p, ts);}/* Roy owes Rob beer. *//* Rob owes Roy dinner. *//* These legacy comments would make a lot more sense if Roy hadn't * replaced the old later_than() routine with util_date.c. * * Well, okay, they still wouldn't make any sense. *//* Match = 0, NoMatch = 1, Abort = -1 * Based loosely on sections of wildmat.c by Rich Salz * Hmmm... shouldn't this really go component by component? */AP_DECLARE(int) ap_strcmp_match(const char *str, const char *expected){    int x, y;    for (x = 0, y = 0; expected[y]; ++y, ++x) {        if ((!str[x]) && (expected[y] != '*'))            return -1;        if (expected[y] == '*') {            while (expected[++y] == '*');            if (!expected[y])                return 0;            while (str[x]) {                int ret;                if ((ret = ap_strcmp_match(&str[x++], &expected[y])) != 1)                    return ret;            }            return -1;        }        else if ((expected[y] != '?') && (str[x] != expected[y]))            return 1;    }    return (str[x] != '\0');}AP_DECLARE(int) ap_strcasecmp_match(const char *str, const char *expected){    int x, y;    for (x = 0, y = 0; expected[y]; ++y, ++x) {        if (!str[x] && expected[y] != '*')            return -1;        if (expected[y] == '*') {            while (expected[++y] == '*');            if (!expected[y])                return 0;            while (str[x]) {                int ret;                if ((ret = ap_strcasecmp_match(&str[x++], &expected[y])) != 1)                    return ret;            }            return -1;        }        else if (expected[y] != '?'                 && apr_tolower(str[x]) != apr_tolower(expected[y]))            return 1;    }    return (str[x] != '\0');}/* We actually compare the canonical root to this root, (but we don't * waste time checking the case), since every use of this function in  * httpd-2.0 tests if the path is 'proper', meaning we've already passed * it through apr_filepath_merge, or we haven't. */AP_DECLARE(int) ap_os_is_path_absolute(apr_pool_t *p, const char *dir) {    const char *newpath;    const char *ourdir = dir;    if (apr_filepath_root(&newpath, &dir, 0, p) != APR_SUCCESS            || strncmp(newpath, ourdir, strlen(newpath)) != 0) {        return 0;    }    return 1;}AP_DECLARE(int) ap_is_matchexp(const char *str){    register int x;    for (x = 0; str[x]; x++)        if ((str[x] == '*') || (str[x] == '?'))            return 1;    return 0;}/* * Here's a pool-based interface to POSIX regex's regcomp(). * Note that we return regex_t instead of being passed one. * The reason is that if you use an already-used regex_t structure, * the memory that you've already allocated gets forgotten, and * regfree() doesn't clear it. So we don't allow it. */static apr_status_t regex_cleanup(void *preg){    regfree((regex_t *) preg);    return APR_SUCCESS;}AP_DECLARE(regex_t *) ap_pregcomp(apr_pool_t *p, const char *pattern,                                   int cflags){    regex_t *preg = apr_palloc(p, sizeof(regex_t));    if (regcomp(preg, pattern, cflags)) {        return NULL;    }    apr_pool_cleanup_register(p, (void *) preg, regex_cleanup,                              apr_pool_cleanup_null);    return preg;}AP_DECLARE(void) ap_pregfree(apr_pool_t *p, regex_t * reg){    regfree(reg);    apr_pool_cleanup_kill(p, (void *) reg, regex_cleanup);}/* * Similar to standard strstr() but we ignore case in this version. * Based on the strstr() implementation further below. */AP_DECLARE(char *) ap_strcasestr(const char *s1, const char *s2){    char *p1, *p2;    if (*s2 == '\0') {        /* an empty s2 */        return((char *)s1);    }    while(1) {        for ( ; (*s1 != '\0') && (apr_tolower(*s1) != apr_tolower(*s2)); s1++);        if (*s1 == '\0') {            return(NULL);        }        /* found first character of s2, see if the rest matches */        p1 = (char *)s1;        p2 = (char *)s2;        for (++p1, ++p2; apr_tolower(*p1) == apr_tolower(*p2); ++p1, ++p2) {            if (*p1 == '\0') {                /* both strings ended together */                return((char *)s1);            }        }        if (*p2 == '\0') {            /* second string ended, a match */            break;        }        /* didn't find a match here, try starting at next character in s1 */        s1++;    }    return((char *)s1);}/* * Returns an offsetted pointer in bigstring immediately after * prefix. Returns bigstring if bigstring doesn't start with * prefix or if prefix is longer than bigstring while still matching. * NOTE: pointer returned is relative to bigstring, so we * can use standard pointer comparisons in the calling function * (eg: test if ap_stripprefix(a,b) == a) */AP_DECLARE(const char *) ap_stripprefix(const char *bigstring,                                        const char *prefix){    const char *p1;    if (*prefix == '\0')        return bigstring;    p1 = bigstring;    while (*p1 && *prefix) {        if (*p1++ != *prefix++)            return bigstring;    }    if (*prefix == '\0')        return p1;    /* hit the end of bigstring! */    return bigstring;}/*  * Apache stub function for the regex libraries regexec() to make sure the * whole regex(3) API is available through the Apache (exported) namespace. * This is especially important for the DSO situations of modules. * DO NOT MAKE A MACRO OUT OF THIS FUNCTION! */AP_DECLARE(int) ap_regexec(regex_t *preg, const char *string,                           size_t nmatch, regmatch_t pmatch[], int eflags){    return regexec(preg, string, nmatch, pmatch, eflags);}AP_DECLARE(size_t) ap_regerror(int errcode, const regex_t *preg, char *errbuf,                               size_t errbuf_size){    return regerror(errcode, preg, errbuf, errbuf_size);}/* This function substitutes for $0-$9, filling in regular expression * submatches. Pass it the same nmatch and pmatch arguments that you * passed ap_regexec(). pmatch should not be greater than the maximum number * of subexpressions - i.e. one more than the re_nsub member of regex_t. * * input should be the string with the $-expressions, source should be the * string that was matched against. * * It returns the substituted string, or NULL on error. * * Parts of this code are based on Henry Spencer's regsub(), from his * AT&T V8 regexp package. */AP_DECLARE(char *) ap_pregsub(apr_pool_t *p, const char *input,                              const char *source, size_t nmatch,                              regmatch_t pmatch[]){    const char *src = input;    char *dest, *dst;    char c;    size_t no;    int len;    if (!source)        return NULL;    if (!nmatch)        return apr_pstrdup(p, src);    /* First pass, find the size */    len = 0;    while ((c = *src++) != '\0') {        if (c == '&')            no = 0;        else if (c == '$' && apr_isdigit(*src))            no = *src++ - '0';        else            no = 10;        if (no > 9) {                /* Ordinary character. */            if (c == '\\' && (*src == '$' || *src == '&'))                c = *src++;            len++;        }        else if (no < nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) {            len += pmatch[no].rm_eo - pmatch[no].rm_so;        }    }    dest = dst = apr_pcalloc(p, len + 1);    /* Now actually fill in the string */    src = input;    while ((c = *src++) != '\0') {        if (c == '&')            no = 0;        else if (c == '$' && apr_isdigit(*src))            no = *src++ - '0';        else            no = 10;        if (no > 9) {                /* Ordinary character. */            if (c == '\\' && (*src == '$' || *src == '&'))                c = *src++;            *dst++ = c;        }        else if (no < nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) {            len = pmatch[no].rm_eo - pmatch[no].rm_so;            memcpy(dst, source + pmatch[no].rm_so, len);            dst += len;        }    }    *dst = '\0';    return dest;}/* * Parse .. so we don't compromise security */AP_DECLARE(void) ap_getparents(char *name){    char *next;    int l, w, first_dot;    /* Four paseses, as per RFC 1808 */    /* a) remove ./ path segments */    for (next = name; *next && (*next != '.'); next++) {    }        l = w = first_dot = next - name;    while (name[l] != '\0') {        if (name[l] == '.' && IS_SLASH(name[l + 1])            && (l == 0 || IS_SLASH(name[l - 1])))            l += 2;        else            name[w++] = name[l++];    }    /* b) remove trailing . path, segment */    if (w == 1 && name[0] == '.')        w--;    else if (w > 1 && name[w - 1] == '.' && IS_SLASH(name[w - 2]))        w--;    name[w] = '\0';    /* c) remove all xx/../ segments. (including leading ../ and /../) */    l = first_dot;    while (name[l] != '\0') {        if (name[l] == '.' && name[l + 1] == '.' && IS_SLASH(name[l + 2])            && (l == 0 || IS_SLASH(name[l - 1]))) {            register int m = l + 3, n;            l = l - 2;            if (l >= 0) {                while (l >= 0 && !IS_SLASH(name[l]))                    l--;                l++;            }            else                l = 0;            n = l;            while ((name[n] = name[m]))                (++n, ++m);        }        else            ++l;    }    /* d) remove trailing xx/.. segment. */    if (l == 2 && name[0] == '.' && name[1] == '.')        name[0] = '\0';    else if (l > 2 && name[l - 1] == '.' && name[l - 2] == '.'             && IS_SLASH(name[l - 3])) {        l = l - 4;        if (l >= 0) {            while (l >= 0 && !IS_SLASH(name[l]))                l--;            l++;        }        else            l = 0;        name[l] = '\0';    }}AP_DECLARE(void) ap_no2slash(char *name){    char *d, *s;    s = d = name;#ifdef HAVE_UNC_PATHS    /* Check for UNC names.  Leave leading two slashes. */    if (s[0] == '/' && s[1] == '/')        *d++ = *s++;#endif    while (*s) {        if ((*d++ = *s) == '/') {            do {                ++s;            } while (*s == '/');        }        else {            ++s;        }    }    *d = '\0';}

⌨️ 快捷键说明

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