util.c revision 3e0494829cf6e8ac61e80fd82b1133111a52614c
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* ====================================================================
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * The Apache Software License, Version 1.1
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * Copyright (c) 2000-2002 The Apache Software Foundation. All rights
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * reserved.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Redistribution and use in source and binary forms, with or without
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * modification, are permitted provided that the following conditions
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * 1. Redistributions of source code must retain the above copyright
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * notice, this list of conditions and the following disclaimer.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * 2. Redistributions in binary form must reproduce the above copyright
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * notice, this list of conditions and the following disclaimer in
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * the documentation and/or other materials provided with the
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * distribution.
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * 3. The end-user documentation included with the redistribution,
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * if any, must include the following acknowledgment:
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * "This product includes software developed by the
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * Apache Software Foundation (http://www.apache.org/)."
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * Alternately, this acknowledgment may appear in the software itself,
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * if and wherever such third-party acknowledgments normally appear.
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * 4. The names "Apache" and "Apache Software Foundation" must
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * not be used to endorse or promote products derived from this
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * software without prior written permission. For written
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * permission, please contact apache@apache.org.
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * 5. Products derived from this software may not be called "Apache",
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * nor may "Apache" appear in their name, without prior written
64185f9824e42f21ca7b9ae6c004484215c031a7rbb * permission of the Apache Software Foundation.
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * SUCH DAMAGE.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * ====================================================================
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * This software consists of voluntary contributions made by many
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * individuals on behalf of the Apache Software Foundation. For more
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * information on the Apache Software Foundation, please see
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * Portions of this software are based upon public domain software
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * originally written at the National Center for Supercomputing Applications,
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * University of Illinois, Urbana-Champaign.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * util.c: string utility things
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * 3/21/93 Rob McCool
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * 1995-96 Many changes by the Apache Software Foundation
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* Debugging aid:
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * #define DEBUG to trace all cfg_open*()/cfg_closefile() calls
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * #define DEBUG_CFG_LINES to trace every line read from the config files
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* A bunch of functions in util.c scan strings looking for certain characters.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * To make that more efficient we encode a lookup table. The test_char_table
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * is generated automatically by gen_test_char.c.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* we assume the folks using this ensure 0 <= c < 256... which means
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * you need a cast to (unsigned char) first, you can't just plug a
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * char in here and get it to work, because if char is signed then it
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * will first be sign extended.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#define TEST_CHAR(c, f) (test_char_table[(unsigned)(c)] & (f))
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Examine a field value (such as a media-/content-type) string and return
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * it sans any parameters; e.g., strip off any ';charset=foo' and the like.
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingAP_DECLARE(char *) ap_field_noparam(apr_pool_t *p, const char *intype)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding const char *semi;
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingAP_DECLARE(char *) ap_ht_time(apr_pool_t *p, apr_time_t t, const char *fmt, int gmt)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding const char *f;
024cd9589e52cf11ce765dfddb5b5f0c6e421a48gstein /* Convert %Z to "GMT" and %z to "+0000";
024cd9589e52cf11ce765dfddb5b5f0c6e421a48gstein * on hosts that do not have a time zone string in struct tm,
024cd9589e52cf11ce765dfddb5b5f0c6e421a48gstein * strftime must assume its argument is local time.
024cd9589e52cf11ce765dfddb5b5f0c6e421a48gstein for(strp = tf, f = fmt; strp < tf + sizeof(tf) - 6 && (*strp = *f)
024cd9589e52cf11ce765dfddb5b5f0c6e421a48gstein ; f++, strp++) {
024cd9589e52cf11ce765dfddb5b5f0c6e421a48gstein if (*f != '%') continue;
024cd9589e52cf11ce765dfddb5b5f0c6e421a48gstein switch (f[1]) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* check return code? */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* Roy owes Rob beer. */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* Rob owes Roy dinner. */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* These legacy comments would make a lot more sense if Roy hadn't
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * replaced the old later_than() routine with util_date.c.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Well, okay, they still wouldn't make any sense.
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm/* Match = 0, NoMatch = 1, Abort = -1
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Based loosely on sections of wildmat.c by Rich Salz
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Hmmm... shouldn't this really go component by component?
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingAP_DECLARE(int) ap_strcmp_match(const char *str, const char *exp)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding for (x = 0, y = 0; exp[y]; ++y, ++x) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding while (str[x]) {
ba09062ce0c7e0d6904a53aaf99896f5924b3989trawick if ((ret = ap_strcmp_match(&str[x++], &exp[y])) != 1)
ba09062ce0c7e0d6904a53aaf99896f5924b3989trawickAP_DECLARE(int) ap_strcasecmp_match(const char *str, const char *exp)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding for (x = 0, y = 0; exp[y]; ++y, ++x) {
ba09062ce0c7e0d6904a53aaf99896f5924b3989trawick while (str[x]) {
ba09062ce0c7e0d6904a53aaf99896f5924b3989trawick if ((ret = ap_strcasecmp_match(&str[x++], &exp[y])) != 1)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding else if ((exp[y] != '?') && (apr_tolower(str[x]) != apr_tolower(exp[y])))
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* We actually compare the canonical root to this root, (but we don't
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * waste time checking the case), since every use of this function in
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * httpd-2.0 tests if the path is 'proper', meaning we've already passed
066877f1a045103acfdd376d48cdd473c33f409bdougm * it through apr_filepath_merge, or we haven't.
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingAP_DECLARE(int) ap_os_is_path_absolute(apr_pool_t *p, const char *dir)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding const char *newpath;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (apr_filepath_root(&newpath, &dir, 0, p) != APR_SUCCESS
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding || strncmp(newpath, ourdir, strlen(newpath)) != 0) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding register int x;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding for (x = 0; str[x]; x++)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Here's a pool-based interface to POSIX regex's regcomp().
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Note that we return regex_t instead of being passed one.
10a4cdd68ef1ca0e54af296fe1d08ac00150c90bwrowe * The reason is that if you use an already-used regex_t structure,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * the memory that you've already allocated gets forgotten, and
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * regfree() doesn't clear it. So we don't allow it.
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmAP_DECLARE(regex_t *) ap_pregcomp(apr_pool_t *p, const char *pattern,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_pool_cleanup_register(p, (void *) preg, regex_cleanup, regex_cleanup);
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingAP_DECLARE(void) ap_pregfree(apr_pool_t *p, regex_t * reg)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding apr_pool_cleanup_kill(p, (void *) reg, regex_cleanup);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Similar to standard strstr() but we ignore case in this version.
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * Based on the strstr() implementation further below.
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingAP_DECLARE(char *) ap_strcasestr(const char *s1, const char *s2)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* an empty s2 */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return((char *)s1);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding for ( ; (*s1 != '\0') && (apr_tolower(*s1) != apr_tolower(*s2)); s1++);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* found first character of s2, see if the rest matches */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding for (++p1, ++p2; apr_tolower(*p1) == apr_tolower(*p2); ++p1, ++p2) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* both strings ended together */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return((char *)s1);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* second string ended, a match */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* didn't find a match here, try starting at next character in s1 */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return((char *)s1);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Returns an offsetted pointer in bigstring immediately after
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * prefix. Returns bigstring if bigstring doesn't start with
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * prefix or if prefix is longer than bigstring while still matching.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * NOTE: pointer returned is relative to bigstring, so we
b79b743d4cff02d6a830bb7118826a2fd608742amartin * can use standard pointer comparisons in the calling function
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * (eg: test if ap_stripprefix(a,b) == a)
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingAP_DECLARE(const char *) ap_stripprefix(const char *bigstring,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding const char *prefix)
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm const char *p1;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* hit the end of bigstring! */
066877f1a045103acfdd376d48cdd473c33f409bdougm * Apache stub function for the regex libraries regexec() to make sure the
1465b960f95b4afba4f4221054dd09e11509bd40rbb * whole regex(3) API is available through the Apache (exported) namespace.
1c65e34ff5b278afbc676c99cff3bf6c4fce2733wrowe * This is especially important for the DSO situations of modules.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * DO NOT MAKE A MACRO OUT OF THIS FUNCTION!
b79b743d4cff02d6a830bb7118826a2fd608742amartinAP_DECLARE(int) ap_regexec(regex_t *preg, const char *string,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return regexec(preg, string, nmatch, pmatch, eflags);
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingAP_DECLARE(size_t) ap_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return regerror(errcode, preg, errbuf, errbuf_size);
73e8b26287de5c06fa470d36162e103dbac9c7e5wrowe/* This function substitutes for $0-$9, filling in regular expression
577a76180006add04a166b12f1ad130aeedeaa5estoddard * submatches. Pass it the same nmatch and pmatch arguments that you
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe * passed ap_regexec(). pmatch should not be greater than the maximum number
577a76180006add04a166b12f1ad130aeedeaa5estoddard * of subexpressions - i.e. one more than the re_nsub member of regex_t.
3d96ee83babeec32482c9082c9426340cee8c44dwrowe * input should be the string with the $-expressions, source should be the
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * string that was matched against.
577a76180006add04a166b12f1ad130aeedeaa5estoddard * It returns the substituted string, or NULL on error.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Parts of this code are based on Henry Spencer's regsub(), from his
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * AT&T V8 regexp package.
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingAP_DECLARE(char *) ap_pregsub(apr_pool_t *p, const char *input, const char *source,
int len;
if (!source)
return NULL;
if (!nmatch)
len = 0;
no = 0;
c = *src++;
len++;
no = 0;
c = *src++;
*dst++ = c;
return dest;
char *next;
int l, w, first_dot;
l = first_dot;
s = d = name;
#ifdef HAVE_UNC_PATHS
* and s == "e:/test.html", "e:/" is returned in d
* *** See also directory_walk in modules/http/http_request.c
memcpy(d, s, l);
for (x = 0, n = 0; path[x]; x++)
int len;
char *res;
++pos;
if (stop) {
++pos;
return res;
int len;
char *res;
++pos;
++pos;
return res;
char *res;
if (!pos) {
return res;
++pos;
return res;
for (i = 0; i < len; ++i) {
return result;
char *res;
char quote;
++str;
if (!*str) {
++strend;
++strend;
++strend;
++strend;
return res;
return word;
const char *e2 = e;
#ifdef DEBUG
char ch;
return ch;
return (int)EOF;
return buf;
return NULL;
AP_DECLARE(apr_status_t) ap_pcfg_openfile(ap_configfile_t **ret_cfg, apr_pool_t *p, const char *name)
#ifdef DEBUG
return APR_EBADF;
#ifdef DEBUG
return status;
return status;
name);
return APR_EBADF;
#ifdef WIN32
return APR_SUCCESS;
void *param,
#ifdef DEBUG
return new_cfg;
return ch;
char *cp;
cp++;
cp--;
cp--;
cp--;
++src;
#ifdef DEBUG_CFG_LINES
register size_t i = 0;
if (c == EOF)
if (c == CR) {
if (c == LF) {
#ifdef DEBUG_CFG_LINES
buf[i] = c;
const unsigned char *token;
++ptr;
++ptr) {
if (in_qpair) {
in_qpair = 0;
switch (*ptr) {
++in_com;
--in_com;
return NULL;
++ptr;
return (const char *)token;
const char *tok_start;
const unsigned char *ptr;
unsigned char *pos;
char *token;
return NULL;
++ptr) {
if (in_qpair) {
in_qpair = 0;
switch (*ptr) {
addspace = 0;
addspace = 0;
++in_com;
addspace = 0;
--in_com;
addspace = 0;
addspace = 0;
return token;
const unsigned char *pos;
++ptr;
if (*ptr)
++ptr) {
if (in_qpair) {
in_qpair = 0;
if (good)
switch (*ptr) {
addspace = 0;
addspace = 0;
++in_com;
addspace = 0;
--in_com;
addspace = 0;
default : if (!good)
addspace = 0;
return good;
const char *tok_start;
char *token;
int tok_len;
++ptr;
while (*ptr)
++ptr;
return token;
const unsigned char *start_token;
if (!line)
s = (const unsigned char *)line;
start_token = s;
if (!line)
if ((lidx < 0) ||
char *cmd;
d = (unsigned char *)cmd;
s = (const unsigned char *)str;
return cmd;
register char digit;
#if !APR_CHARSET_EBCDIC
return (digit);
badesc = 0;
badpath = 0;
if (y == NULL) {
return OK;
if (badesc)
return HTTP_BAD_REQUEST;
else if (badpath)
return HTTP_NOT_FOUND;
return OK;
return where;
const unsigned char *s = (const unsigned char *)segment;
unsigned char *d = (unsigned char *)copy;
d = c2x(c, d);
return copy;
const unsigned char *s = (const unsigned char *)path;
unsigned char *d = (unsigned char *)copy;
if (!partial) {
d = c2x(c, d);
return copy;
return apr_pstrmemdup(p, s, i);
const char *src2)
char *path;
if (len1 == 0) {
char *next;
return path;
const char *p = ap_strchr_c(s, c);
if (p == NULL)
const char *p = ap_strrchr_c(s, c);
if (p == NULL)
while (*str) {
++str;
if (p->h_aliases) {
for (x = 0; p->h_aliases[x]; ++x) {
return NULL;
#ifndef MAXHOSTNAMELEN
struct hostent *p;
#ifdef BEOS_R5
if (p && p->h_addr_list[0]) {
return server_hostname;
if (!server_hostname)
return server_hostname;
/* simple 'pool' alloc()ing glue to apr_base64.c
char *decoded;
return decoded;
char *encoded;
return encoded;
char *semi;
if (semi) {
while (*str) {
++str;
if (semi) {
int newlen = 0;
newlen++;
newlen++;
inchr++;
newlen++;
inchr++;
return outstring;