util.c revision a47a604a8bd3897c793e22c119150d085a7d2243
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein/* Licensed to the Apache Software Foundation (ASF) under one or more
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * contributor license agreements. See the NOTICE file distributed with
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * this work for additional information regarding copyright ownership.
bc8fd1b0b1afdf89b8d28eefa8cd74e26ba97986fielding * The ASF licenses this file to You under the Apache License, Version 2.0
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * (the "License"); you may not use this file except in compliance with
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * the License. You may obtain a copy of the License at
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Unless required by applicable law or agreed to in writing, software
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * distributed under the License is distributed on an "AS IS" BASIS,
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * See the License for the specific language governing permissions and
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * limitations under the License.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * util.c: string utility things
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * 3/21/93 Rob McCool
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * 1995-96 Many changes by the Apache Software Foundation
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein/* Debugging aid:
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * #define DEBUG to trace all cfg_open*()/cfg_closefile() calls
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * #define DEBUG_CFG_LINES to trace every line read from the config files
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* A bunch of functions in util.c scan strings looking for certain characters.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * To make that more efficient we encode a lookup table. The test_char_table
f4c310fd2555c6faca1f980f00b161eadb089023gstein * is generated automatically by gen_test_char.c.
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* we assume the folks using this ensure 0 <= c < 256... which means
f4c310fd2555c6faca1f980f00b161eadb089023gstein * you need a cast to (unsigned char) first, you can't just plug a
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe * char in here and get it to work, because if char is signed then it
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe * will first be sign extended.
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define TEST_CHAR(c, f) (test_char_table[(unsigned)(c)] & (f))
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Win32/NetWare/OS2 need to check for both forward and back slashes
f4c310fd2555c6faca1f980f00b161eadb089023gstein * in ap_getparents() and ap_escape_url.
5b03ba47ff7225cacb131f14b019332af27da960gstein/* we know core's module_index is 0 */
5b03ba47ff7225cacb131f14b019332af27da960gstein * Examine a field value (such as a media-/content-type) string and return
5b03ba47ff7225cacb131f14b019332af27da960gstein * it sans any parameters; e.g., strip off any ';charset=foo' and the like.
5b03ba47ff7225cacb131f14b019332af27da960gsteinAP_DECLARE(char *) ap_field_noparam(apr_pool_t *p, const char *intype)
5b03ba47ff7225cacb131f14b019332af27da960gstein const char *semi;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(char *) ap_ht_time(apr_pool_t *p, apr_time_t t, const char *fmt,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *f;
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Convert %Z to "GMT" and %z to "+0000";
f4c310fd2555c6faca1f980f00b161eadb089023gstein * on hosts that do not have a time zone string in struct tm,
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe * strftime must assume its argument is local time.
f4c310fd2555c6faca1f980f00b161eadb089023gstein for(strp = tf, f = fmt; strp < tf + sizeof(tf) - 6 && (*strp = *f)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ; f++, strp++) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (*f != '%') continue;
f4c310fd2555c6faca1f980f00b161eadb089023gstein switch (f[1]) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* check return code? */
58fd79b56eb624bf011772994e9761d3c2e228c1orlikowski apr_strftime(ts, &retcode, MAX_STRING_LEN, fmt, &xt);
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Roy owes Rob beer. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Rob owes Roy dinner. */
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe/* These legacy comments would make a lot more sense if Roy hadn't
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe * replaced the old later_than() routine with util_date.c.
58fd79b56eb624bf011772994e9761d3c2e228c1orlikowski * Well, okay, they still wouldn't make any sense.
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Match = 0, NoMatch = 1, Abort = -1
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Based loosely on sections of wildmat.c by Rich Salz
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Hmmm... shouldn't this really go component by component?
98e9c4a310bb623ff788680f88b6bd200ff36a24wroweAP_DECLARE(int) ap_strcmp_match(const char *str, const char *expected)
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (x = 0, y = 0; expected[y]; ++y, ++x) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (str[x]) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((ret = ap_strcmp_match(&str[x++], &expected[y])) != 1)
48f35e10f195dd594d75738fc536bb885eda537cgstein else if ((expected[y] != '?') && (str[x] != expected[y]))
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(int) ap_strcasecmp_match(const char *str, const char *expected)
8b99f2a316c5e2fa6ab208206fdd7fc2bfc4a921dougm for (x = 0, y = 0; expected[y]; ++y, ++x) {
48f35e10f195dd594d75738fc536bb885eda537cgstein while (str[x]) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ((ret = ap_strcasecmp_match(&str[x++], &expected[y])) != 1)
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* We actually compare the canonical root to this root, (but we don't
48f35e10f195dd594d75738fc536bb885eda537cgstein * waste time checking the case), since every use of this function in
48f35e10f195dd594d75738fc536bb885eda537cgstein * httpd-2.1 tests if the path is 'proper', meaning we've already passed
48f35e10f195dd594d75738fc536bb885eda537cgstein * it through apr_filepath_merge, or we haven't.
48f35e10f195dd594d75738fc536bb885eda537cgsteinAP_DECLARE(int) ap_os_is_path_absolute(apr_pool_t *p, const char *dir)
48f35e10f195dd594d75738fc536bb885eda537cgstein const char *newpath;
48f35e10f195dd594d75738fc536bb885eda537cgstein if (apr_filepath_root(&newpath, &dir, 0, p) != APR_SUCCESS
24efed0910118b762a4eb84830875d4714b8d315ianh register int x;
48f35e10f195dd594d75738fc536bb885eda537cgstein for (x = 0; str[x]; x++)
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein * Here's a pool-based interface to the POSIX-esque ap_regcomp().
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein * Note that we return ap_regex_t instead of being passed one.
48f35e10f195dd594d75738fc536bb885eda537cgstein * The reason is that if you use an already-used ap_regex_t structure,
48f35e10f195dd594d75738fc536bb885eda537cgstein * the memory that you've already allocated gets forgotten, and
48f35e10f195dd594d75738fc536bb885eda537cgstein * regfree() doesn't clear it. So we don't allow it.
48f35e10f195dd594d75738fc536bb885eda537cgsteinAP_DECLARE(ap_regex_t *) ap_pregcomp(apr_pool_t *p, const char *pattern,
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pool_cleanup_register(p, (void *) preg, regex_cleanup,
48f35e10f195dd594d75738fc536bb885eda537cgsteinAP_DECLARE(void) ap_pregfree(apr_pool_t *p, ap_regex_t *reg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pool_cleanup_kill(p, (void *) reg, regex_cleanup);
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Similar to standard strstr() but we ignore case in this version.
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein * Based on the strstr() implementation further below.
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_strcasestr(const char *s1, const char *s2)
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* an empty s2 */
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein return((char *)s1);
f4c310fd2555c6faca1f980f00b161eadb089023gstein for ( ; (*s1 != '\0') && (apr_tolower(*s1) != apr_tolower(*s2)); s1++);
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* found first character of s2, see if the rest matches */
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (++p1, ++p2; apr_tolower(*p1) == apr_tolower(*p2); ++p1, ++p2) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* both strings ended together */
f958dac1550254a59b45f4655138bb34dad5e76egstein return((char *)s1);
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* second string ended, a match */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* didn't find a match here, try starting at next character in s1 */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return((char *)s1);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * Returns an offsetted pointer in bigstring immediately after
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * prefix. Returns bigstring if bigstring doesn't start with
f4c310fd2555c6faca1f980f00b161eadb089023gstein * prefix or if prefix is longer than bigstring while still matching.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * NOTE: pointer returned is relative to bigstring, so we
f4c310fd2555c6faca1f980f00b161eadb089023gstein * can use standard pointer comparisons in the calling function
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe * (eg: test if ap_stripprefix(a,b) == a)
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wroweAP_DECLARE(const char *) ap_stripprefix(const char *bigstring,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *prefix)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *p1;
f39230a531b23d94f86a087963299bbe2e431a4agstein /* hit the end of bigstring! */
f39230a531b23d94f86a087963299bbe2e431a4agstein/* This function substitutes for $0-$9, filling in regular expression
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * submatches. Pass it the same nmatch and pmatch arguments that you
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * passed ap_regexec(). pmatch should not be greater than the maximum number
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * of subexpressions - i.e. one more than the re_nsub member of ap_regex_t.
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * nmatch must be <=AP_MAX_REG_MATCH (10).
f39230a531b23d94f86a087963299bbe2e431a4agstein * input should be the string with the $-expressions, source should be the
f39230a531b23d94f86a087963299bbe2e431a4agstein * string that was matched against.
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * It returns the substituted string, or NULL if a vbuf is used.
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * On errors, returns the orig string.
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * Parts of this code are based on Henry Spencer's regsub(), from his
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * AT&T V8 regexp package.
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gsteinstatic apr_status_t regsub_core(apr_pool_t *p, char **result,
f39230a531b23d94f86a087963299bbe2e431a4agstein AP_DEBUG_ASSERT((result && p && !vb) || (vb && !p && !result));
f39230a531b23d94f86a087963299bbe2e431a4agstein /* First pass, find the size */
f39230a531b23d94f86a087963299bbe2e431a4agstein if (no >= AP_MAX_REG_MATCH) { /* Ordinary character. */
f39230a531b23d94f86a087963299bbe2e431a4agstein else if (no < nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) {
f39230a531b23d94f86a087963299bbe2e431a4agstein if (APR_SIZE_MAX - len <= pmatch[no].rm_eo - pmatch[no].rm_so)
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein /* Now actually fill in the string */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein if (no >= AP_MAX_REG_MATCH) { /* Ordinary character. */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein else if (no < nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) {
b5989e567e4fac5b3ab1252024ae19b0a54893a7gsteinAP_DECLARE(char *) ap_pregsub(apr_pool_t *p, const char *input,
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein apr_status_t rc = regsub_core(p, &result, NULL, input, source, nmatch,
b5989e567e4fac5b3ab1252024ae19b0a54893a7gsteinAP_DECLARE(apr_status_t) ap_pregsub_ex(apr_pool_t *p, char **result,
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_status_t rc = regsub_core(p, result, NULL, input, source, nmatch,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Parse .. so we don't compromise security
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Four paseses, as per RFC 1808 */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* a) remove ./ path segments */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* b) remove trailing . path, segment */
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (w > 1 && name[w - 1] == '.' && IS_SLASH(name[w - 2]))
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* c) remove all xx/../ segments. (including leading ../ and /../) */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (name[l] == '.' && name[l + 1] == '.' && IS_SLASH(name[l + 2])
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe register int m = l + 3, n;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (l >= 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein (++n, ++m);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* d) remove trailing xx/.. segment. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (l > 2 && name[l - 1] == '.' && name[l - 2] == '.'
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (l >= 0) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe char *d, *s;
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Check for UNC names. Leave leading two slashes. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein *d++ = *s++;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while (*s) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((*d++ = *s) == '/') {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe } while (*s == '/');
f4c310fd2555c6faca1f980f00b161eadb089023gstein * copy at most n leading directories of s into d
f4c310fd2555c6faca1f980f00b161eadb089023gstein * d should be at least as large as s plus 1 extra byte
f4c310fd2555c6faca1f980f00b161eadb089023gstein * assumes n > 0
f4c310fd2555c6faca1f980f00b161eadb089023gstein * the return value is the ever useful pointer to the trailing \0 of d
f4c310fd2555c6faca1f980f00b161eadb089023gstein * MODIFIED FOR HAVE_DRIVE_LETTERS and NETWARE environments,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * so that if n == 0, "/" is returned in d with n == 1
f4c310fd2555c6faca1f980f00b161eadb089023gstein * and s == "e:/test.html", "e:/" is returned in d
f4c310fd2555c6faca1f980f00b161eadb089023gstein * *** See also directory_walk in modules/http/http_request.c
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * examples:
f4c310fd2555c6faca1f980f00b161eadb089023gstein * /a/b, 0 ==> / (true for all platforms)
f4c310fd2555c6faca1f980f00b161eadb089023gstein * /a/b, 1 ==> /
f4c310fd2555c6faca1f980f00b161eadb089023gstein * /a/b, 2 ==> /a/
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * /a/b, 3 ==> /a/b/
f4c310fd2555c6faca1f980f00b161eadb089023gstein * /a/b, 4 ==> /a/b/
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * c:/a/b 0 ==> /
f4c310fd2555c6faca1f980f00b161eadb089023gstein * c:/a/b 1 ==> c:/
f4c310fd2555c6faca1f980f00b161eadb089023gstein * c:/a/b 2 ==> c:/a/
f4c310fd2555c6faca1f980f00b161eadb089023gstein * c:/a/b 3 ==> c:/a/b
f4c310fd2555c6faca1f980f00b161eadb089023gstein * c:/a/b 4 ==> c:/a/b
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(char *) ap_make_dirstr_prefix(char *d, const char *s, int n)
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (n < 1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein *++d = '\0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein return (d);
f4c310fd2555c6faca1f980f00b161eadb089023gstein *d++ = *s++;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return (d);
f4c310fd2555c6faca1f980f00b161eadb089023gstein * return the parent directory name including trailing / of the file s
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_make_dirstr_parent(apr_pool_t *p, const char *s)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe d = apr_pstrmemdup(p, s, l);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return (d);
f4c310fd2555c6faca1f980f00b161eadb089023gstein register int x, n;
8b99f2a316c5e2fa6ab208206fdd7fc2bfc4a921dougm for (x = 0, n = 0; path[x]; x++)
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_getword_nc(apr_pool_t *atrans, char **line, char stop)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return ap_getword(atrans, (const char **) line, stop);
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_getword(apr_pool_t *atrans, const char **line, char stop)
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_getword_white_nc(apr_pool_t *atrans, char **line)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return ap_getword_white(atrans, (const char **) line);
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_getword_white(apr_pool_t *atrans, const char **line)
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_getword_nulls_nc(apr_pool_t *atrans, char **line,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return ap_getword_nulls(atrans, (const char **) line, stop);
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_getword_nulls(apr_pool_t *atrans, const char **line,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* Get a word, (new) config-file style --- quoted strings and backslashes
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * all honored
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic char *substring_conf(apr_pool_t *p, const char *start, int len,
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (i = 0; i < len; ++i) {
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(char *) ap_getword_conf_nc(apr_pool_t *p, char **line)
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_getword_conf(apr_pool_t *p, const char **line)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe res = substring_conf(p, str + 1, strend - str - 1, quote);
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(int) ap_cfg_closefile(ap_configfile_t *cfp)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, APLOGNO(00551)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return (cfp->close == NULL) ? 0 : cfp->close(cfp->param);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* we can't use apr_file_* directly because of linking issues on Windows */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic apr_status_t cfg_getstr(void *buf, apr_size_t bufsiz, void *param)
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Open a ap_configfile_t as FILE, return open ap_configfile_t struct pointer */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(apr_status_t) ap_pcfg_openfile(ap_configfile_t **ret_cfg,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, APLOGNO(00552)
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Internal error: pcfg_openfile() called with NULL filename");
f4c310fd2555c6faca1f980f00b161eadb089023gstein status = apr_file_open(&file, name, APR_READ | APR_BUFFERED,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, APLOGNO(00553)
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Opening config file %s (%s)",
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_strerror(status, buf, sizeof(buf)) : "successful");
f4c310fd2555c6faca1f980f00b161eadb089023gstein status = apr_file_info_get(&finfo, APR_FINFO_TYPE, file);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#if defined(WIN32) || defined(OS2) || defined(NETWARE)
f4c310fd2555c6faca1f980f00b161eadb089023gstein strcasecmp(apr_filepath_name_get(name), "nul") != 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* WIN32 || OS2 */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, APLOGNO(00554)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Access to file %s denied by server: not a regular file",
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Some twisted character [no pun intended] at MS decided that a
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * zero width joiner as the lead wide character would be ideal for
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * describing Unicode text files. This was further convoluted to
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * another MSism that the same character mapped into utf-8, EF BB BF
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * would signify utf-8 text files.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * Since MS configuration files are all protecting utf-8 encoded
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * Unicode path, file and resource names, we already have the correct
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * WinNT encoding. But at least eat the stupid three bytes up front.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* Allocate a ap_configfile_t handle with user defined functions and params */
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_status_t (*gets_func) (void *buf, apr_size_t bufsize, void *param),
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_configfile_t *new_cfg = apr_palloc(p, sizeof(*new_cfg));
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Read one character from a configfile_t */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(apr_status_t) ap_cfg_getc(char *ch, ap_configfile_t *cfp)
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(const char *) ap_pcfg_strerror(apr_pool_t *p, ap_configfile_t *cfp,
f4c310fd2555c6faca1f980f00b161eadb089023gstein return apr_psprintf(p, "Error reading %s at line %d: %s",
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Read one line from open ap_configfile_t, strip LF, increase line number */
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* If custom handler does not define a getstr() function, read char by char */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic apr_status_t ap_cfg_getline_core(char *buf, apr_size_t bufsize,
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If a "get string" function is defined, use it */
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein * check for line continuation,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * i.e. match [^\\]\\[\r]\n only
f4c310fd2555c6faca1f980f00b161eadb089023gstein * line continuation requested -
f4c310fd2555c6faca1f980f00b161eadb089023gstein * then remove backslash and continue
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* No "get string" function defined; read character by character */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* too small, assume caller is crazy */
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (1) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (c == LF) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* check for line continuation */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * Leading and trailing white space is eliminated completely
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* blast trailing whitespace */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Zap leading whitespace by shifting */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL, APLOGNO(00555) "Read config: '%s'", buf);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* Read one line from open ap_configfile_t, strip LF, increase line number */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* If custom handler does not define a getstr() function, read char by char */
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(apr_status_t) ap_cfg_getline(char *buf, apr_size_t bufsize,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_status_t rc = ap_cfg_getline_core(buf, bufsize, cfp);
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(apr_status_t) ap_varbuf_cfg_getline(struct ap_varbuf *vb,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe rc = ap_cfg_getline_core(vb->buf + vb->strlen, vb->avail - vb->strlen, cfp);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* Size an HTTP header field list item, as separated by a comma.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * The return value is a pointer to the beginning of the non-empty list item
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * within the original string (or NULL if there is none) and the address
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * of field is shifted to the next non-comma, non-whitespace character.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * len is the length of the item excluding any beginning whitespace.
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(const char *) ap_size_list_item(const char **field, int *len)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const unsigned char *ptr = (const unsigned char *)*field;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const unsigned char *token;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Find first non-comma, non-whitespace byte */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Find the end of this item, skipping over dead bits */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe switch (*ptr) {
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein default : break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Advance field pointer to the next non-comma, non-white byte */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return (const char *)token;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* Retrieve an HTTP header field list item, as separated by a comma,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * while stripping insignificant whitespace and lowercasing anything not in
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * a quoted string or comment. The return value is a new string containing
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * the converted list item (or NULL if none) and the address pointed to by
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * field is shifted to the next non-comma, non-whitespace.
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_get_list_item(apr_pool_t *p, const char **field)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *tok_start;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const unsigned char *ptr;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe unsigned char *pos;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int addspace = 0, in_qpair = 0, in_qstr = 0, in_com = 0, tok_len = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Find the beginning and maximum length of the list item so that
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * we can allocate a buffer for the new string and reset the field.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ((tok_start = ap_size_list_item(field, &tok_len)) == NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Scan the token again, but this time copy only the good bytes.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * We skip extra whitespace and any whitespace around a '=', '/',
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * or ';' and lowercase normal characters not within a comment,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * quoted-string or quoted-pair.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (ptr = (const unsigned char *)tok_start, pos = (unsigned char *)token;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe switch (*ptr) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* Find an item in canonical form (lowercase, no extra spaces) within
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * an HTTP field value list. Returns 1 if found, 0 if not found.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * This would be much more efficient if we stored header fields as
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * an array of list items as they are received instead of a plain string.
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(int) ap_find_list_item(apr_pool_t *p, const char *line,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *tok)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const unsigned char *pos;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const unsigned char *ptr = (const unsigned char *)line;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int good = 0, addspace = 0, in_qpair = 0, in_qstr = 0, in_com = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe do { /* loop for each item in line's list */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Find first non-comma, non-whitespace byte */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break; /* no items left and nothing good found */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* We skip extra whitespace and any whitespace around a '=', '/',
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * or ';' and lowercase normal characters not within a comment,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * quoted-string or quoted-pair.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');
f4c310fd2555c6faca1f980f00b161eadb089023gstein switch (*ptr) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe default : if (!good)
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Retrieve a token, spacing over it and returning a pointer to
f4c310fd2555c6faca1f980f00b161eadb089023gstein * the first non-white byte afterwards. Note that these tokens
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein * are delimited by semis and commas; and can also be delimited
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein * by whitespace at the caller's option.
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(char *) ap_get_token(apr_pool_t *p, const char **accept_line,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *tok_start;
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Find first non-white byte */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* find token end, skipping over quoted strings.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * (comments are already gone).
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Advance accept_line pointer to the next non-white byte */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* find http tokens, see the definition of token from RFC2068 */
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(int) ap_find_token(apr_pool_t *p, const char *line, const char *tok)
f4c310fd2555c6faca1f980f00b161eadb089023gstein const unsigned char *start_token;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const unsigned char *s;
f4c310fd2555c6faca1f980f00b161eadb089023gstein s = (const unsigned char *)line;
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* find start of token, skip all stop characters, note NUL
f4c310fd2555c6faca1f980f00b161eadb089023gstein * isn't a token stop, so we don't need to test for it
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* find end of the token */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!strncasecmp((const char *)start_token, (const char *)tok,
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(int) ap_find_last_token(apr_pool_t *p, const char *line,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *tok)
f4c310fd2555c6faca1f980f00b161eadb089023gstein (lidx > 0 && !(apr_isspace(line[lidx - 1]) || line[lidx - 1] == ',')))
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(char *) ap_escape_shell_cmd(apr_pool_t *p, const char *str)
f4c310fd2555c6faca1f980f00b161eadb089023gstein unsigned char *d;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const unsigned char *s;
f4c310fd2555c6faca1f980f00b161eadb089023gstein cmd = apr_palloc(p, 2 * strlen(str) + 1); /* Be safe */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein d = (unsigned char *)cmd;
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein s = (const unsigned char *)str;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein for (; *s; ++s) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * Newlines to Win32/OS2 CreateProcess() are ill advised.
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein * Convert them to spaces since they are effectively white
f4c310fd2555c6faca1f980f00b161eadb089023gstein * space to most applications
f4c310fd2555c6faca1f980f00b161eadb089023gstein *d++ = ' ';
f4c310fd2555c6faca1f980f00b161eadb089023gstein *d++ = '\\';
f4c310fd2555c6faca1f980f00b161eadb089023gstein register char digit;
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein digit = ((what[0] >= 'A') ? ((what[0] & 0xdf) - 'A') + 10
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A') + 10
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#else /*APR_CHARSET_EBCDIC*/
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#endif /*APR_CHARSET_EBCDIC*/
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * Unescapes a URL, leaving reserved characters intact.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * Returns 0 on success, non-zero on error
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * Failure is due to
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * bad % escape returns HTTP_BAD_REQUEST
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * decoding %00 or a forbidden character returns HTTP_NOT_FOUND
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic int unescape_url(char *url, const char *forbid, const char *reserved)
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm char *x, *y;
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Initial scan for first '%'. Don't bother writing values before
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * seeing a '%' */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (y == NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (x = y; *y; ++x, ++y) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (*y != '%') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!apr_isxdigit(*(y + 1)) || !apr_isxdigit(*(y + 2))) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (reserved && ap_strchr_c(reserved, decoded)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein *x++ = *y++;
f4c310fd2555c6faca1f980f00b161eadb089023gstein *x++ = *y++;
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Traditional */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(int) ap_unescape_url_keep2f(char *url, int decode_slashes)
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* AllowEncodedSlashes (corrected) */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* no chars reserved */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* reserve (do not decode) encoded slashes */
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* IFDEF these out until they've been thought through.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Just a germ of an API extension for now
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* leave RFC1738 reserved characters intact, * so proxied URLs
f4c310fd2555c6faca1f980f00b161eadb089023gstein * don't get mangled. Where does that leave encoded '&' ?
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(int) ap_unescape_url_reserved(char *url, const char *reserved)
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* replace plus with a space */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* unescape everything else */
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_construct_server(apr_pool_t *p, const char *hostname,
f39230a531b23d94f86a087963299bbe2e431a4agstein/* c2x takes an unsigned, and expects the caller has guaranteed that
f39230a531b23d94f86a087963299bbe2e431a4agstein * 0 <= what < 256... which usually means that you have to cast to
50bd75672ef114fb839dd9643c192b432fdf344cgstein * unsigned char first, because (unsigned)(char)(x) first goes through
50bd75672ef114fb839dd9643c192b432fdf344cgstein * signed extension to an int before the unsigned cast.
50bd75672ef114fb839dd9643c192b432fdf344cgstein * The reason for this assumption is to assist gcc code generation --
50bd75672ef114fb839dd9643c192b432fdf344cgstein * the unsigned char -> unsigned extension is already done earlier in
50bd75672ef114fb839dd9643c192b432fdf344cgstein * both uses of this code, so there's no need to waste time doing it
50bd75672ef114fb839dd9643c192b432fdf344cgsteinstatic APR_INLINE unsigned char *c2x(unsigned what, unsigned char prefix,
50bd75672ef114fb839dd9643c192b432fdf344cgstein unsigned char *where)
50bd75672ef114fb839dd9643c192b432fdf344cgstein what = apr_xlate_conv_byte(ap_hdrs_to_ascii, (unsigned char)what);
50bd75672ef114fb839dd9643c192b432fdf344cgstein#endif /*APR_CHARSET_EBCDIC*/
f39230a531b23d94f86a087963299bbe2e431a4agstein * escape_path_segment() escapes a path segment, as defined in RFC 1808. This
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein * routine is (should be) OS independent.
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein * os_escape_path() converts an OS path to a URL, in an OS dependent way. In all
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein * cases if a ':' occurs before the first '/' in the URL, the URL should be
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein * prefixed with "./" (or the ':' escaped). In the case of Unix, this means
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein * leaving '/' alone, but otherwise doing what escape_path_segment() does. For
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein * efficiency reasons, we don't use escape_path_segment(), which is provided for
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * reference. Again, RFC 1808 is where this stuff is defined.
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein * If partial is set, os_escape_path() assumes that the path will be appended to
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein * something with a '/' in it (and thus does not prefix "./").
f39230a531b23d94f86a087963299bbe2e431a4agsteinAP_DECLARE(char *) ap_escape_path_segment_buffer(char *copy, const char *segment)
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein const unsigned char *s = (const unsigned char *)segment;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein unsigned char *d = (unsigned char *)copy;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein unsigned c;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while ((c = *s)) {
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(char *) ap_escape_path_segment(apr_pool_t *p, const char *segment)
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein return ap_escape_path_segment_buffer(apr_palloc(p, 3 * strlen(segment) + 1), segment);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gsteinAP_DECLARE(char *) ap_os_escape_path(apr_pool_t *p, const char *path, int partial)
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein const unsigned char *s = (const unsigned char *)path;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein unsigned char *d = (unsigned char *)copy;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein unsigned c;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = '.';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = '/';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein while ((c = *s)) {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gsteinAP_DECLARE(char *) ap_escape_urlencoded_buffer(char *copy, const char *buffer)
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein const unsigned char *s = (const unsigned char *)buffer;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein unsigned char *d = (unsigned char *)copy;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein unsigned c;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein while ((c = *s)) {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein else if (c == ' ') {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *d++ = '+';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gsteinAP_DECLARE(char *) ap_escape_urlencoded(apr_pool_t *p, const char *buffer)
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein return ap_escape_urlencoded_buffer(apr_palloc(p, 3 * strlen(buffer) + 1), buffer);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein/* ap_escape_uri is now a macro for os_escape_path */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gsteinAP_DECLARE(char *) ap_escape_html2(apr_pool_t *p, const char *s, int toasc)
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein /* first, count the number of extra characters */
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (i = 0, j = 0; s[i] != '\0'; i++)
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (s[i] == '&')
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein else if (s[i] == '"')
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (j == 0)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return apr_pstrmemdup(p, s, i);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein for (i = 0, j = 0; s[i] != '\0'; i++, j++)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (s[i] == '<') {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else if (s[i] == '>') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (s[i] == '&') {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein else if (s[i] == '"') {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein char *esc = apr_psprintf(p, "&#%3.3d;", (unsigned char)s[i]);
f4c310fd2555c6faca1f980f00b161eadb089023gstein x[j] = s[i];
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe x[j] = '\0';
83719c22db4a6d0575bb4f7f34382d7b185a6f74gsteinAP_DECLARE(char *) ap_escape_logitem(apr_pool_t *p, const char *str)
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein unsigned char *d;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein const unsigned char *s;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ret = apr_palloc(p, 4 * strlen(str) + 1); /* Be safe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe d = (unsigned char *)ret;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe s = (const unsigned char *)str;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (; *s; ++s) {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = '\\';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe switch(*s) {
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein *d++ = 'b';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = 'n';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = 'r';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = 't';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = 'v';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gsteinAP_DECLARE(apr_size_t) ap_escape_errorlog_item(char *dest, const char *source,
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein unsigned char *d, *ep;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein const unsigned char *s;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein d = (unsigned char *)dest;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein s = (const unsigned char *)source;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein for (; d < ep && *s; ++s) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *d++ = '\\';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (d >= ep) {
50bd75672ef114fb839dd9643c192b432fdf344cgstein switch(*s) {
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein *d++ = 'b';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = 'n';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = 'r';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = 't';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = 'v';
50bd75672ef114fb839dd9643c192b432fdf344cgstein d[-1] = *s;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein return (d - (unsigned char *)dest);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gsteinAP_DECLARE(int) ap_is_directory(apr_pool_t *p, const char *path)
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if (apr_stat(&finfo, path, APR_FINFO_TYPE, p) != APR_SUCCESS)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return 0; /* in error condition, just return no */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gsteinAP_DECLARE(int) ap_is_rdirectory(apr_pool_t *p, const char *path)
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if (apr_stat(&finfo, path, APR_FINFO_LINK | APR_FINFO_TYPE, p) != APR_SUCCESS)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return 0; /* in error condition, just return no */
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_make_full_path(apr_pool_t *a, const char *src1,
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein const char *src2)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* allocate +3 for '/' delimiter, trailing NULL and overallocate
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * one extra byte to allow the caller to add a trailing '/'
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (len1 == 0) {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein * Check for an absoluteURI syntax (see section 3.2 in RFC2068).
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein register int x;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (x = 0; u[x] != ':'; x++) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ((!u[x]) ||
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein return (x ? 1 : 0); /* If the first character is ':', it's broken, too */
cdcb6937fbc9f4283e1783a0d43b62e9e8ad08d3gstein const char *p = ap_strchr_c(s, c);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein return p - s;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *p = ap_strrchr_c(s, c);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return p - s;
++str;
while (*str) {
++str;
#ifndef MAXHOSTNAMELEN
char *hostname;
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) {
if (semi) {
int newlen = 0;
newlen++;
newlen++;
inchr++;
newlen++;
inchr++;
return outstring;
* a macro, to avoid unistd.h dependency
const char *delim)
const char *timeout_parameter,
const char *default_time_unit)
char *endp;
const char *time_str;
if (errno) {
return errno;
switch (*time_str) {
switch (*(++time_str)) {
return APR_EGENERAL;
return APR_EGENERAL;
return APR_SUCCESS;
char *estr;
const char *cls;
int has_body;
&& (r->kept_body
&& (!*estr)
&& (cl > 0) )
return has_body;
return APR_SUCCESS;
return APR_SUCCESS;
const char **dest)
if (!new)
return APR_ENOMEM;
* type application/x-www-form-urlencoded.
int seen_eos = 0;
const char *ct;
char hi = 0;
char low = 0;
return ap_discard_request_body(r);
f = r->input_filters;
const char *data;
if (last) {
return HTTP_BAD_REQUEST;
char c = *data++;
switch (state) {
case FORM_AMP:
if (pair) {
offset = 0;
num--;
case FORM_NAME:
offset = 0;
size--;
case FORM_VALUE:
offset = 0;
size--;
} while (!seen_eos);
return HTTP_REQUEST_ENTITY_TOO_LARGE;
return OK;
struct ap_varbuf_info {
return APR_SUCCESS;
char *new;
if (!new_node) {
int len)
if (len == 0)
apr_size_t i = 0;
if (prepend) {
if (append) {
if (new_len)
*new_len = 0;
const char *input,
const char *source,
if (written > 0) {
abort();