util.c revision b6055b7832a0e4d0818416252fff5925aaebae4b
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco/* ====================================================================
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * The Apache Software License, Version 1.1
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * Copyright (c) 2000 The Apache Software Foundation. All rights
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * Redistribution and use in source and binary forms, with or without
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * modification, are permitted provided that the following conditions
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * 1. Redistributions of source code must retain the above copyright
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * notice, this list of conditions and the following disclaimer.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * 2. Redistributions in binary form must reproduce the above copyright
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * notice, this list of conditions and the following disclaimer in
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * the documentation and/or other materials provided with the
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * distribution.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * 3. The end-user documentation included with the redistribution,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * if any, must include the following acknowledgment:
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * "This product includes software developed by the
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * Apache Software Foundation (http://www.apache.org/)."
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * Alternately, this acknowledgment may appear in the software itself,
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * if and wherever such third-party acknowledgments normally appear.
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * 4. The names "Apache" and "Apache Software Foundation" must
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * not be used to endorse or promote products derived from this
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * software without prior written permission. For written
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco * permission, please contact apache@apache.org.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * 5. Products derived from this software may not be called "Apache",
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * nor may "Apache" appear in their name, without prior written
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * permission of the Apache Software Foundation.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * SUCH DAMAGE.
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * ====================================================================
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * This software consists of voluntary contributions made by many
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * individuals on behalf of the Apache Software Foundation. For more
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * information on the Apache Software Foundation, please see
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * Portions of this software are based upon public domain software
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * originally written at the National Center for Supercomputing Applications,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * University of Illinois, Urbana-Champaign.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * util.c: string utility things
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * 3/21/93 Rob McCool
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * 1995-96 Many changes by the Apache Software Foundation
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* Debugging aid:
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * #define DEBUG to trace all cfg_open*()/cfg_closefile() calls
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * #define DEBUG_CFG_LINES to trace every line read from the config files
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* A bunch of functions in util.c scan strings looking for certain characters.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * To make that more efficient we encode a lookup table. The test_char_table
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * is generated automatically by gen_test_char.c.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* we assume the folks using this ensure 0 <= c < 256... which means
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * you need a cast to (unsigned char) first, you can't just plug a
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * char in here and get it to work, because if char is signed then it
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * will first be sign extended.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#define TEST_CHAR(c, f) (test_char_table[(unsigned)(c)] & (f))
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * Examine a field value (such as a media-/content-type) string and return
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco * it sans any parameters; e.g., strip off any ';charset=foo' and the like.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián RiescoAPI_EXPORT(char *) ap_field_noparam(ap_pool_t *p, const char *intype)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco while ((semi > intype) && ap_isspace(semi[-1])) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián RiescoAPI_EXPORT(char *) ap_ht_time(ap_pool_t *p, ap_time_t t, const char *fmt, int gmt)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco const char *f;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Convert %Z to "GMT" and %z to "+0000";
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * on hosts that do not have a time zone string in struct tm,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * strftime must assume its argument is local time.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco for(strp = tf, f = fmt; strp < tf + sizeof(tf) - 6 && (*strp = *f)
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco if (*f != '%') continue;
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco switch (f[1]) {
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco /* check return code? */
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco ap_strftime(ts, &retcode, MAX_STRING_LEN, fmt, &xt);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco/* Roy owes Rob beer. */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco/* Rob owes Roy dinner. */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco/* These legacy comments would make a lot more sense if Roy hadn't
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco * replaced the old later_than() routine with util_date.c.
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco * Well, okay, they still wouldn't make any sense.
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco/* Match = 0, NoMatch = 1, Abort = -1
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * Based loosely on sections of wildmat.c by Rich Salz
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * Hmmm... shouldn't this really go component by component?
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián RiescoAPI_EXPORT(int) ap_strcmp_match(const char *str, const char *exp)
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco for (x = 0, y = 0; exp[y]; ++y, ++x) {
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco while (str[x]) {
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco if ((ret = ap_strcmp_match(&str[x++], &exp[y])) != 1)
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco else if ((exp[y] != '?') && (str[x] != exp[y]))
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián RiescoAPI_EXPORT(int) ap_strcasecmp_match(const char *str, const char *exp)
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco for (x = 0, y = 0; exp[y]; ++y, ++x) {
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco while (str[x]) {
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco if ((ret = ap_strcasecmp_match(&str[x++], &exp[y])) != 1)
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco else if ((exp[y] != '?') && (ap_tolower(str[x]) != ap_tolower(exp[y])))
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián RiescoAPI_EXPORT(int) ap_is_matchexp(const char *str)
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco register int x;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco for (x = 0; str[x]; x++)
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * Here's a pool-based interface to POSIX regex's regcomp().
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * Note that we return regex_t instead of being passed one.
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * The reason is that if you use an already-used regex_t structure,
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * the memory that you've already allocated gets forgotten, and
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * regfree() doesn't clear it. So we don't allow it.
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián RiescoAPI_EXPORT(regex_t *) ap_pregcomp(ap_pool_t *p, const char *pattern,
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco regex_t *preg = ap_palloc(p, sizeof(regex_t));
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco ap_register_cleanup(p, (void *) preg, regex_cleanup, regex_cleanup);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián RiescoAPI_EXPORT(void) ap_pregfree(ap_pool_t *p, regex_t * reg)
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco ap_kill_cleanup(p, (void *) reg, regex_cleanup);
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco * Similar to standard strstr() but we ignore case in this version.
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco * Based on the strstr() implementation further below.
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián RiescoAPI_EXPORT(char *) ap_strcasestr(const char *s1, const char *s2)
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /* an empty s2 */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco return((char *)s1);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco for ( ; (*s1 != '\0') && (ap_tolower(*s1) != ap_tolower(*s2)); s1++);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /* found first character of s2, see if the rest matches */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco while (ap_tolower(*++p1) == ap_tolower(*++p2)) {
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco /* both strings ended together */
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco return((char *)s1);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* second string ended, a match */
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco /* didn't find a match here, try starting at next character in s1 */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return((char *)s1);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * Apache stub function for the regex libraries regexec() to make sure the
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco * whole regex(3) API is available through the Apache (exported) namespace.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * This is especially important for the DSO situations of modules.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * DO NOT MAKE A MACRO OUT OF THIS FUNCTION!
fecce42517d20490f893c4a9dee29b000e1653eaAdrián RiescoAPI_EXPORT(int) ap_regexec(regex_t *preg, const char *string,
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco size_t nmatch, regmatch_t pmatch[], int eflags)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return regexec(preg, string, nmatch, pmatch, eflags);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián RiescoAPI_EXPORT(size_t) ap_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco return regerror(errcode, preg, errbuf, errbuf_size);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* This function substitutes for $0-$9, filling in regular expression
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * submatches. Pass it the same nmatch and pmatch arguments that you
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * passed ap_regexec(). pmatch should not be greater than the maximum number
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * of subexpressions - i.e. one more than the re_nsub member of regex_t.
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco * input should be the string with the $-expressions, source should be the
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * string that was matched against.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * It returns the substituted string, or NULL on error.
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco * Parts of this code are based on Henry Spencer's regsub(), from his
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco * AT&T V8 regexp package.
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián RiescoAPI_EXPORT(char *) ap_pregsub(ap_pool_t *p, const char *input, const char *source,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* First pass, find the size */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (c == '&')
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco if (c == '\\' && (*src == '$' || *src == '&'))
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else if (no < nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Now actually fill in the string */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (c == '&')
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (c == '\\' && (*src == '$' || *src == '&'))
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else if (no < nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * Parse .. so we don't compromise security
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Four paseses, as per RFC 1808 */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* a) remove ./ path segments */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (name[l] == '.' && name[l + 1] == '/' && (l == 0 || name[l - 1] == '/'))
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* b) remove trailing . path, segment */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else if (w > 1 && name[w - 1] == '.' && name[w - 2] == '/')
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* c) remove all xx/../ segments. (including leading ../ and /../) */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (name[l] == '.' && name[l + 1] == '.' && name[l + 2] == '/' &&
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco register int m = l + 3, n;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (l >= 0) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* d) remove trailing xx/.. segment. */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (l == 2 && name[0] == '.' && name[1] == '.')
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco else if (l > 2 && name[l - 1] == '.' && name[l - 2] == '.' && name[l - 3] == '/') {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (l >= 0) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Check for UNC names. Leave leading two slashes. */
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco if ((*d++ = *s) == '/') {
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco } while (*s == '/');
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco * copy at most n leading directories of s into d
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco * d should be at least as large as s plus 1 extra byte
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco * assumes n > 0
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco * the return value is the ever useful pointer to the trailing \0 of d
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco * /a/b, 1 ==> /
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco * /a/b, 2 ==> /a/
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco * /a/b, 3 ==> /a/b/
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco * /a/b, 4 ==> /a/b/
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián RiescoAPI_EXPORT(char *) ap_make_dirstr_prefix(char *d, const char *s, int n)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (*s == '\0' || (*s == '/' && (--n) == 0)) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * return the parent directory name including trailing / of the file s
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián RiescoAPI_EXPORT(char *) ap_make_dirstr_parent(ap_pool_t *p, const char *s)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco const char *last_slash = ap_strrchr_c(s, '/');
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* XXX: well this is really broken if this happens */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * This function is deprecated. Use one of the preceeding two functions
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * which are faster.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián RiescoAPI_EXPORT(char *) ap_make_dirstr(ap_pool_t *p, const char *s, int n)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco register int x, f;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco for (x = 0, f = 0; s[x]; x++) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (s[x] == '/')
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if ((++f) == n) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián RiescoAPI_EXPORT(int) ap_count_dirs(const char *path)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco register int x, n;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco for (x = 0, n = 0; path[x]; x++)
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián RiescoAPI_EXPORT(void) ap_chdir_file(const char *file)
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco const char *x;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco /* XXX: well, this is a silly function, no method of reporting an
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco * error... ah well. */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián RiescoAPI_EXPORT(char *) ap_getword_nc(ap_pool_t *atrans, char **line, char stop)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return ap_getword(atrans, (const char **) line, stop);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián RiescoAPI_EXPORT(char *) ap_getword(ap_pool_t *atrans, const char **line, char stop)
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco res = ap_pstrndup(atrans, *line, pos - *line);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián RiescoAPI_EXPORT(char *) ap_getword_white_nc(ap_pool_t *atrans, char **line)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return ap_getword_white(atrans, (const char **) line);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián RiescoAPI_EXPORT(char *) ap_getword_white(ap_pool_t *atrans, const char **line)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco for (x = 0; (*line)[x]; x++) {
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián RiescoAPI_EXPORT(char *) ap_getword_nulls_nc(ap_pool_t *atrans, char **line, char stop)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return ap_getword_nulls(atrans, (const char **) line, stop);
7474965b2e6323002c96c0b39a59843cde201870Adrián RiescoAPI_EXPORT(char *) ap_getword_nulls(ap_pool_t *atrans, const char **line, char stop)
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco res = ap_pstrndup(atrans, *line, pos - *line);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco/* Get a word, (new) config-file style --- quoted strings and backslashes
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * all honored
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riescostatic char *substring_conf(ap_pool_t *p, const char *start, int len, char quote)
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco for (i = 0; i < len; ++i) {
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián RiescoAPI_EXPORT(char *) ap_getword_conf_nc(ap_pool_t *p, char **line)
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco return ap_getword_conf(p, (const char **) line);
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián RiescoAPI_EXPORT(char *) ap_getword_conf(ap_pool_t *p, const char **line)
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco if (*strend == '\\' && strend[1] && strend[1] == quote)
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco res = substring_conf(p, str + 1, strend - str - 1, quote);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco res = substring_conf(p, str, strend - str, 0);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* Check a string for any ${ENV} environment variable
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * construct and replace each them by the value of
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * that environment variable, if it exists. If the
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * environment value does not exist, leave the ${ENV}
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * construct alone; it means something else.
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián RiescoAPI_EXPORT(const char *) ap_resolve_env(ap_pool_t *p, const char * word)
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco const char *s, *e;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco /* XXX - relies on strncat() to add '\0'
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco if ((s[1] == '{') && (e=ap_strchr_c(s,'}'))) {
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco const char *e2 = e;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* ignore invalid strings */
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián RiescoAPI_EXPORT(int) ap_cfg_closefile(configfile_t *cfp)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return (cfp->close == NULL) ? 0 : cfp->close(cfp->param);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return (int)EOF;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic void *cfg_getstr(void *buf, size_t bufsiz, void *param)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (ap_fgets(buf, bufsiz, cfp) == APR_SUCCESS)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* Open a configfile_t as FILE, return open configfile_t struct pointer */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián RiescoAPI_EXPORT(ap_status_t) ap_pcfg_openfile(configfile_t **ret_cfg, ap_pool_t *p, const char *name)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, NULL,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "Internal error: pcfg_openfile() called with NULL filename");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, NULL,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "Access to config file %s denied: not a valid filename",
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco status = ap_open(&file, name, APR_READ | APR_BUFFERED, APR_OS_DEFAULT, p);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, NULL,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "Opening config file %s (%s)",
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_strerror(status, buf, sizeof(buf)) : "successful");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco strcasecmp(name + strlen(name) - 4, "/nul") == 0))) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#endif /* WIN32 || OS2 */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, NULL,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "Access to file %s denied by server: not a regular file",
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco new_cfg->getstr = (void *(*)(void *, size_t, void *)) cfg_getstr;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* Allocate a configfile_t handle with user defined functions and params */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián RiescoAPI_EXPORT(configfile_t *) ap_pcfg_open_custom(ap_pool_t *p, const char *descr,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco void *(*getstr) (void *buf, size_t bufsiz, void *param),
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco configfile_t *new_cfg = ap_palloc(p, sizeof(*new_cfg));
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, NULL, "Opening config handler %s", descr);
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco/* Read one character from a configfile_t */
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco/* Read one line from open configfile_t, strip LF, increase line number */
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco/* If custom handler does not define a getstr() function, read char by char */
fecce42517d20490f893c4a9dee29b000e1653eaAdrián RiescoAPI_EXPORT(int) ap_cfg_getline(char *buf, size_t bufsize, configfile_t *cfp)
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco /* If a "get string" function is defined, use it */
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco if (cfp->getstr(cbuf, cbufsize, cfp->param) == NULL)
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco * check for line continuation,
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco * i.e. match [^\\]\\[\r]\n only
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco * line continuation requested -
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco * then remove backslash and continue
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco * no real continuation because escaped -
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco * then just remove escape character
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco for ( ; cp < cbuf+cbufsize && *cp != '\0'; 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;
#ifndef 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;
#ifdef CHARSET_EBCDIC
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 ap_pstrndup(p, s, i);
const char *src2)
#ifndef HAVE_INITGROUPS
#if defined(QNX) || defined(MPE) || defined(BEOS) || defined(_OSD_POSIX) || defined(TPF) || defined(__TANDEM) || defined(OS2) || defined(WIN32)
struct group *g;
int index = 0;
setgrent();
char **names;
endgrent();
while (*str) {
++str;
#ifdef WIN32
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "%s: bad user name %s", ap_server_argv0, name);
#ifdef WIN32
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "%s: bad group name %s", ap_server_argv0, name);
unsigned long my_addr;
*ports = 0;
if (p != NULL)
if (p != NULL)
if (p != NULL)
return my_addr;
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "Cannot resolve host name %s --- exiting!", w);
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "Host %s has multiple addresses ---", w);
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "you must choose one explicitly for use as");
if (p != NULL)
for (x = 0; p->h_aliases[x]; ++x) {
return NULL;
#ifndef MAXHOSTNAMELEN
struct hostent *p;
#ifdef BEOS
return server_hostname;
if (!server_hostname)
return server_hostname;
/* simple 'pool' alloc()ing glue to ap_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;