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 *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * http://www.apache.org/licenses/LICENSE-2.0
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
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 */
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein/*
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * util.c: string utility things
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * 3/21/93 Rob McCool
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * 1995-96 Many changes by the Apache Software Foundation
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein */
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein
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
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein */
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "apr.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "apr_strings.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "apr_lib.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#define APR_WANT_STDIO
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#define APR_WANT_STRFUNC
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "apr_want.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#if APR_HAVE_UNISTD_H
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include <unistd.h>
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#endif
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#if APR_HAVE_PROCESS_H
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include <process.h> /* for getpid() on Win32 */
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#endif
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#if APR_HAVE_NETDB_H
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include <netdb.h> /* for gethostbyname() */
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#endif
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "ap_config.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "apr_base64.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "httpd.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "http_main.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "http_log.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "http_protocol.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "http_config.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "http_core.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "util_ebcdic.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "util_varbuf.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef HAVE_PWD_H
1b21d7b3d97def358b2e923655edeb16613a1c31gstein#include <pwd.h>
952023a04a2f9d51553babd9094fb857f1c97548trawick#endif
1b21d7b3d97def358b2e923655edeb16613a1c31gstein#ifdef HAVE_GRP_H
1b21d7b3d97def358b2e923655edeb16613a1c31gstein#include <grp.h>
1b21d7b3d97def358b2e923655edeb16613a1c31gstein#endif
1b21d7b3d97def358b2e923655edeb16613a1c31gstein
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 */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "test_char.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein
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 */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define TEST_CHAR(c, f) (test_char_table[(unsigned)(c)] & (f))
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Win32/NetWare/OS2 need to check for both forward and back slashes
f4c310fd2555c6faca1f980f00b161eadb089023gstein * in ap_getparents() and ap_escape_url.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef CASE_BLIND_FILESYSTEM
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define IS_SLASH(s) ((s == '/') || (s == '\\'))
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define SLASHES "/\\"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#else
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define IS_SLASH(s) (s == '/')
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define SLASHES "/"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
5b03ba47ff7225cacb131f14b019332af27da960gstein/* we know core's module_index is 0 */
5b03ba47ff7225cacb131f14b019332af27da960gstein#undef APLOG_MODULE_INDEX
5b03ba47ff7225cacb131f14b019332af27da960gstein#define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
5b03ba47ff7225cacb131f14b019332af27da960gstein
5b03ba47ff7225cacb131f14b019332af27da960gstein
5b03ba47ff7225cacb131f14b019332af27da960gstein/*
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.
5b03ba47ff7225cacb131f14b019332af27da960gstein */
5b03ba47ff7225cacb131f14b019332af27da960gsteinAP_DECLARE(char *) ap_field_noparam(apr_pool_t *p, const char *intype)
5b03ba47ff7225cacb131f14b019332af27da960gstein{
5b03ba47ff7225cacb131f14b019332af27da960gstein const char *semi;
5b03ba47ff7225cacb131f14b019332af27da960gstein
5b03ba47ff7225cacb131f14b019332af27da960gstein if (intype == NULL) return NULL;
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe semi = ap_strchr_c(intype, ';');
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe if (semi == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return apr_pstrdup(p, intype);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein while ((semi > intype) && apr_isspace(semi[-1])) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein semi--;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein return apr_pstrndup(p, intype, semi - intype);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(char *) ap_ht_time(apr_pool_t *p, apr_time_t t, const char *fmt,
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe int gmt)
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe{
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_size_t retcode;
f4c310fd2555c6faca1f980f00b161eadb089023gstein char ts[MAX_STRING_LEN];
f4c310fd2555c6faca1f980f00b161eadb089023gstein char tf[MAX_STRING_LEN];
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_time_exp_t xt;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (gmt) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *f;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe char *strp;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_time_exp_gmt(&xt, t);
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.
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe */
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 case '%':
f4c310fd2555c6faca1f980f00b161eadb089023gstein *++strp = *++f;
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case 'Z':
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *strp++ = 'G';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *strp++ = 'M';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *strp = 'T';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe f++;
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe case 'z': /* common extension */
f4c310fd2555c6faca1f980f00b161eadb089023gstein *strp++ = '+';
f4c310fd2555c6faca1f980f00b161eadb089023gstein *strp++ = '0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein *strp++ = '0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein *strp++ = '0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein *strp = '0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein f++;
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe break;
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein *strp = '\0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein fmt = tf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_time_exp_lt(&xt, t);
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe }
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* check return code? */
58fd79b56eb624bf011772994e9761d3c2e228c1orlikowski apr_strftime(ts, &retcode, MAX_STRING_LEN, fmt, &xt);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ts[MAX_STRING_LEN - 1] = '\0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein return apr_pstrdup(p, ts);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Roy owes Rob beer. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Rob owes Roy dinner. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
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.
f4c310fd2555c6faca1f980f00b161eadb089023gstein *
58fd79b56eb624bf011772994e9761d3c2e228c1orlikowski * Well, okay, they still wouldn't make any sense.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
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?
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
98e9c4a310bb623ff788680f88b6bd200ff36a24wroweAP_DECLARE(int) ap_strcmp_match(const char *str, const char *expected)
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe{
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe int x, y;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (x = 0, y = 0; expected[y]; ++y, ++x) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((!str[x]) && (expected[y] != '*'))
f4c310fd2555c6faca1f980f00b161eadb089023gstein return -1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (expected[y] == '*') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (expected[++y] == '*');
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!expected[y])
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (str[x]) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein int ret;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((ret = ap_strcmp_match(&str[x++], &expected[y])) != 1)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return ret;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein return -1;
48f35e10f195dd594d75738fc536bb885eda537cgstein }
48f35e10f195dd594d75738fc536bb885eda537cgstein else if ((expected[y] != '?') && (str[x] != expected[y]))
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein return (str[x] != '\0');
91644a5f4d3e992dc208304b50e80bbb236fca89trawick}
8b99f2a316c5e2fa6ab208206fdd7fc2bfc4a921dougm
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(int) ap_strcasecmp_match(const char *str, const char *expected)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein int x, y;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
8b99f2a316c5e2fa6ab208206fdd7fc2bfc4a921dougm for (x = 0, y = 0; expected[y]; ++y, ++x) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (!str[x] && expected[y] != '*')
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return -1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (expected[y] == '*') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (expected[++y] == '*');
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!expected[y])
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 0;
48f35e10f195dd594d75738fc536bb885eda537cgstein while (str[x]) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int ret;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ((ret = ap_strcasecmp_match(&str[x++], &expected[y])) != 1)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return ret;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein return -1;
48f35e10f195dd594d75738fc536bb885eda537cgstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (expected[y] != '?'
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe && apr_tolower(str[x]) != apr_tolower(expected[y]))
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return (str[x] != '\0');
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
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.
48f35e10f195dd594d75738fc536bb885eda537cgstein */
48f35e10f195dd594d75738fc536bb885eda537cgsteinAP_DECLARE(int) ap_os_is_path_absolute(apr_pool_t *p, const char *dir)
48f35e10f195dd594d75738fc536bb885eda537cgstein{
48f35e10f195dd594d75738fc536bb885eda537cgstein const char *newpath;
48f35e10f195dd594d75738fc536bb885eda537cgstein const char *ourdir = dir;
48f35e10f195dd594d75738fc536bb885eda537cgstein if (apr_filepath_root(&newpath, &dir, 0, p) != APR_SUCCESS
48f35e10f195dd594d75738fc536bb885eda537cgstein || strncmp(newpath, ourdir, strlen(newpath)) != 0) {
48f35e10f195dd594d75738fc536bb885eda537cgstein return 0;
48f35e10f195dd594d75738fc536bb885eda537cgstein }
48f35e10f195dd594d75738fc536bb885eda537cgstein return 1;
48f35e10f195dd594d75738fc536bb885eda537cgstein}
48f35e10f195dd594d75738fc536bb885eda537cgstein
48f35e10f195dd594d75738fc536bb885eda537cgsteinAP_DECLARE(int) ap_is_matchexp(const char *str)
48f35e10f195dd594d75738fc536bb885eda537cgstein{
24efed0910118b762a4eb84830875d4714b8d315ianh register int x;
48f35e10f195dd594d75738fc536bb885eda537cgstein
48f35e10f195dd594d75738fc536bb885eda537cgstein for (x = 0; str[x]; x++)
48f35e10f195dd594d75738fc536bb885eda537cgstein if ((str[x] == '*') || (str[x] == '?'))
48f35e10f195dd594d75738fc536bb885eda537cgstein return 1;
48f35e10f195dd594d75738fc536bb885eda537cgstein return 0;
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein}
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein/*
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.
48f35e10f195dd594d75738fc536bb885eda537cgstein */
48f35e10f195dd594d75738fc536bb885eda537cgstein
48f35e10f195dd594d75738fc536bb885eda537cgsteinstatic apr_status_t regex_cleanup(void *preg)
48f35e10f195dd594d75738fc536bb885eda537cgstein{
48f35e10f195dd594d75738fc536bb885eda537cgstein ap_regfree((ap_regex_t *) preg);
48f35e10f195dd594d75738fc536bb885eda537cgstein return APR_SUCCESS;
48f35e10f195dd594d75738fc536bb885eda537cgstein}
48f35e10f195dd594d75738fc536bb885eda537cgstein
48f35e10f195dd594d75738fc536bb885eda537cgsteinAP_DECLARE(ap_regex_t *) ap_pregcomp(apr_pool_t *p, const char *pattern,
48f35e10f195dd594d75738fc536bb885eda537cgstein int cflags)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_regex_t *preg = apr_palloc(p, sizeof *preg);
f4c310fd2555c6faca1f980f00b161eadb089023gstein int err = ap_regcomp(preg, pattern, cflags);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err == AP_REG_ESPACE)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_abort_on_oom();
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pool_cleanup_register(p, (void *) preg, regex_cleanup,
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pool_cleanup_null);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return preg;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
48f35e10f195dd594d75738fc536bb885eda537cgstein
48f35e10f195dd594d75738fc536bb885eda537cgsteinAP_DECLARE(void) ap_pregfree(apr_pool_t *p, ap_regex_t *reg)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_regfree(reg);
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pool_cleanup_kill(p, (void *) reg, regex_cleanup);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Similar to standard strstr() but we ignore case in this version.
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein * Based on the strstr() implementation further below.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_strcasestr(const char *s1, const char *s2)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe char *p1, *p2;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (*s2 == '\0') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* an empty s2 */
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein return((char *)s1);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein while(1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein for ( ; (*s1 != '\0') && (apr_tolower(*s1) != apr_tolower(*s2)); s1++);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (*s1 == '\0') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return(NULL);
8b99f2a316c5e2fa6ab208206fdd7fc2bfc4a921dougm }
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* found first character of s2, see if the rest matches */
f4c310fd2555c6faca1f980f00b161eadb089023gstein p1 = (char *)s1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein p2 = (char *)s2;
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (++p1, ++p2; apr_tolower(*p1) == apr_tolower(*p2); ++p1, ++p2) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (*p1 == '\0') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* both strings ended together */
f958dac1550254a59b45f4655138bb34dad5e76egstein return((char *)s1);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (*p2 == '\0') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* second string ended, a match */
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* didn't find a match here, try starting at next character in s1 */
f4c310fd2555c6faca1f980f00b161eadb089023gstein s1++;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein return((char *)s1);
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
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)
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wroweAP_DECLARE(const char *) ap_stripprefix(const char *bigstring,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *prefix)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *p1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (*prefix == '\0')
f4c310fd2555c6faca1f980f00b161eadb089023gstein return bigstring;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f39230a531b23d94f86a087963299bbe2e431a4agstein p1 = bigstring;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe while (*p1 && *prefix) {
f39230a531b23d94f86a087963299bbe2e431a4agstein if (*p1++ != *prefix++)
f39230a531b23d94f86a087963299bbe2e431a4agstein return bigstring;
f39230a531b23d94f86a087963299bbe2e431a4agstein }
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe if (*prefix == '\0')
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe return p1;
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agstein /* hit the end of bigstring! */
f39230a531b23d94f86a087963299bbe2e431a4agstein return bigstring;
1e2133fe37e6cbcd683233057ef62236bc8e5826trawick}
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein
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 *
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * nmatch must be <=AP_MAX_REG_MATCH (10).
f39230a531b23d94f86a087963299bbe2e431a4agstein *
f39230a531b23d94f86a087963299bbe2e431a4agstein * input should be the string with the $-expressions, source should be the
f39230a531b23d94f86a087963299bbe2e431a4agstein * string that was matched against.
f39230a531b23d94f86a087963299bbe2e431a4agstein *
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * It returns the substituted string, or NULL if a vbuf is used.
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * On errors, returns the orig string.
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein *
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * Parts of this code are based on Henry Spencer's regsub(), from his
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * AT&T V8 regexp package.
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein */
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gsteinstatic apr_status_t regsub_core(apr_pool_t *p, char **result,
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein struct ap_varbuf *vb, const char *input,
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein const char *source, apr_size_t nmatch,
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein ap_regmatch_t pmatch[], apr_size_t maxlen)
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein{
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein const char *src = input;
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein char *dst;
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein char c;
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein apr_size_t no;
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein apr_size_t len = 0;
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein
f39230a531b23d94f86a087963299bbe2e431a4agstein AP_DEBUG_ASSERT((result && p && !vb) || (vb && !p && !result));
f39230a531b23d94f86a087963299bbe2e431a4agstein if (!source || nmatch>AP_MAX_REG_MATCH)
f39230a531b23d94f86a087963299bbe2e431a4agstein return APR_EINVAL;
f39230a531b23d94f86a087963299bbe2e431a4agstein if (!nmatch) {
f39230a531b23d94f86a087963299bbe2e431a4agstein len = strlen(src);
f39230a531b23d94f86a087963299bbe2e431a4agstein if (maxlen > 0 && len >= maxlen)
f39230a531b23d94f86a087963299bbe2e431a4agstein return APR_ENOMEM;
f39230a531b23d94f86a087963299bbe2e431a4agstein if (!vb) {
f39230a531b23d94f86a087963299bbe2e431a4agstein *result = apr_pstrmemdup(p, src, len);
f39230a531b23d94f86a087963299bbe2e431a4agstein return APR_SUCCESS;
f39230a531b23d94f86a087963299bbe2e431a4agstein }
f39230a531b23d94f86a087963299bbe2e431a4agstein else {
f39230a531b23d94f86a087963299bbe2e431a4agstein ap_varbuf_strmemcat(vb, src, len);
f39230a531b23d94f86a087963299bbe2e431a4agstein return APR_SUCCESS;
f39230a531b23d94f86a087963299bbe2e431a4agstein }
f39230a531b23d94f86a087963299bbe2e431a4agstein }
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agstein /* First pass, find the size */
f39230a531b23d94f86a087963299bbe2e431a4agstein while ((c = *src++) != '\0') {
f39230a531b23d94f86a087963299bbe2e431a4agstein if (c == '$' && apr_isdigit(*src))
f39230a531b23d94f86a087963299bbe2e431a4agstein no = *src++ - '0';
f39230a531b23d94f86a087963299bbe2e431a4agstein else
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein no = AP_MAX_REG_MATCH;
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agstein if (no >= AP_MAX_REG_MATCH) { /* Ordinary character. */
f39230a531b23d94f86a087963299bbe2e431a4agstein if (c == '\\' && *src)
f39230a531b23d94f86a087963299bbe2e431a4agstein src++;
f39230a531b23d94f86a087963299bbe2e431a4agstein len++;
f39230a531b23d94f86a087963299bbe2e431a4agstein }
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)
f39230a531b23d94f86a087963299bbe2e431a4agstein return APR_ENOMEM;
f39230a531b23d94f86a087963299bbe2e431a4agstein len += pmatch[no].rm_eo - pmatch[no].rm_so;
f39230a531b23d94f86a087963299bbe2e431a4agstein }
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agstein }
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein if (len >= maxlen && maxlen > 0)
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein return APR_ENOMEM;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
6810bf1570bed88d16239b27ce47d48408bb2e51gstein if (!vb) {
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein *result = dst = apr_palloc(p, len + 1);
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein }
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein else {
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein if (vb->strlen == AP_VARBUF_UNKNOWN)
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein vb->strlen = strlen(vb->buf);
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein ap_varbuf_grow(vb, vb->strlen + len);
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein dst = vb->buf + vb->strlen;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein vb->strlen += len;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein }
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein /* Now actually fill in the string */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein src = input;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein while ((c = *src++) != '\0') {
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein if (c == '$' && apr_isdigit(*src))
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein no = *src++ - '0';
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein else
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein no = AP_MAX_REG_MATCH;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein if (no >= AP_MAX_REG_MATCH) { /* Ordinary character. */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein if (c == '\\' && *src)
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein c = *src++;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein *dst++ = c;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein }
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein else if (no < nmatch && pmatch[no].rm_so < pmatch[no].rm_eo) {
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein len = pmatch[no].rm_eo - pmatch[no].rm_so;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein memcpy(dst, source + pmatch[no].rm_so, len);
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein dst += len;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein }
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein }
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein *dst = '\0';
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein return APR_SUCCESS;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein}
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein#ifndef AP_PREGSUB_MAXLEN
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein#define AP_PREGSUB_MAXLEN (HUGE_STRING_LEN * 8)
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein#endif
b5989e567e4fac5b3ab1252024ae19b0a54893a7gsteinAP_DECLARE(char *) ap_pregsub(apr_pool_t *p, const char *input,
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein const char *source, apr_size_t nmatch,
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein ap_regmatch_t pmatch[])
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein{
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein char *result;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein apr_status_t rc = regsub_core(p, &result, NULL, input, source, nmatch,
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein pmatch, AP_PREGSUB_MAXLEN);
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein if (rc != APR_SUCCESS)
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein result = NULL;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein return result;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein}
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gsteinAP_DECLARE(apr_status_t) ap_pregsub_ex(apr_pool_t *p, char **result,
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein const char *input, const char *source,
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein apr_size_t nmatch, ap_regmatch_t pmatch[],
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein apr_size_t maxlen)
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein{
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_status_t rc = regsub_core(p, result, NULL, input, source, nmatch,
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein pmatch, maxlen);
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein if (rc != APR_SUCCESS)
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein *result = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return rc;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Parse .. so we don't compromise security
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(void) ap_getparents(char *name)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *next;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int l, w, first_dot;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Four paseses, as per RFC 1808 */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* a) remove ./ path segments */
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (next = name; *next && (*next != '.'); next++) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein l = w = first_dot = next - name;
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (name[l] != '\0') {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm if (name[l] == '.' && IS_SLASH(name[l + 1])
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm && (l == 0 || IS_SLASH(name[l - 1])))
f4c310fd2555c6faca1f980f00b161eadb089023gstein l += 2;
f4c310fd2555c6faca1f980f00b161eadb089023gstein else
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe name[w++] = name[l++];
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* b) remove trailing . path, segment */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (w == 1 && name[0] == '.')
f4c310fd2555c6faca1f980f00b161eadb089023gstein w--;
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (w > 1 && name[w - 1] == '.' && IS_SLASH(name[w - 2]))
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe w--;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe name[w] = '\0';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* c) remove all xx/../ segments. (including leading ../ and /../) */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe l = first_dot;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while (name[l] != '\0') {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (name[l] == '.' && name[l + 1] == '.' && IS_SLASH(name[l + 2])
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe && (l == 0 || IS_SLASH(name[l - 1]))) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe register int m = l + 3, n;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe l = l - 2;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (l >= 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (l >= 0 && !IS_SLASH(name[l]))
f4c310fd2555c6faca1f980f00b161eadb089023gstein l--;
f4c310fd2555c6faca1f980f00b161eadb089023gstein l++;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else
f4c310fd2555c6faca1f980f00b161eadb089023gstein l = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein n = l;
f4c310fd2555c6faca1f980f00b161eadb089023gstein while ((name[n] = name[m]))
f4c310fd2555c6faca1f980f00b161eadb089023gstein (++n, ++m);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else
f4c310fd2555c6faca1f980f00b161eadb089023gstein ++l;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* d) remove trailing xx/.. segment. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (l == 2 && name[0] == '.' && name[1] == '.')
f4c310fd2555c6faca1f980f00b161eadb089023gstein name[0] = '\0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (l > 2 && name[l - 1] == '.' && name[l - 2] == '.'
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm && IS_SLASH(name[l - 3])) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe l = l - 4;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (l >= 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (l >= 0 && !IS_SLASH(name[l]))
f4c310fd2555c6faca1f980f00b161eadb089023gstein l--;
f4c310fd2555c6faca1f980f00b161eadb089023gstein l++;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else
f4c310fd2555c6faca1f980f00b161eadb089023gstein l = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein name[l] = '\0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(void) ap_no2slash(char *name)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe char *d, *s;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein s = d = name;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm#ifdef HAVE_UNC_PATHS
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Check for UNC names. Leave leading two slashes. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (s[0] == '/' && s[1] == '/')
f4c310fd2555c6faca1f980f00b161eadb089023gstein *d++ = *s++;
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while (*s) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((*d++ = *s) == '/') {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe do {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++s;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe } while (*s == '/');
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ++s;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein *d = '\0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
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 *
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
f4c310fd2555c6faca1f980f00b161eadb089023gstein
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/
f4c310fd2555c6faca1f980f00b161eadb089023gstein *
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
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(char *) ap_make_dirstr_prefix(char *d, const char *s, int n)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (n < 1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein *d = '/';
f4c310fd2555c6faca1f980f00b161eadb089023gstein *++d = '\0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein return (d);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (;;) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (*s == '\0' || (*s == '/' && (--n) == 0)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein *d = '/';
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein *d++ = *s++;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein *++d = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return (d);
58fd79b56eb624bf011772994e9761d3c2e228c1orlikowski}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
8b99f2a316c5e2fa6ab208206fdd7fc2bfc4a921dougm
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * return the parent directory name including trailing / of the file s
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_make_dirstr_parent(apr_pool_t *p, const char *s)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *last_slash = ap_strrchr_c(s, '/');
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm char *d;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int l;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (last_slash == NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return apr_pstrdup(p, "");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe l = (last_slash - s) + 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe d = apr_pstrmemdup(p, s, l);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return (d);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(int) ap_count_dirs(const char *path)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein register int x, n;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
8b99f2a316c5e2fa6ab208206fdd7fc2bfc4a921dougm for (x = 0, n = 0; path[x]; x++)
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (path[x] == '/')
f4c310fd2555c6faca1f980f00b161eadb089023gstein n++;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return n;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_getword_nc(apr_pool_t *atrans, char **line, char stop)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return ap_getword(atrans, (const char **) line, stop);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_getword(apr_pool_t *atrans, const char **line, char stop)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *pos = *line;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int len;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe char *res;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while ((*pos != stop) && *pos) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++pos;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe len = pos - *line;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe res = apr_pstrmemdup(atrans, *line, len);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (stop) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while (*pos == stop) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++pos;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *line = pos;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return res;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_getword_white_nc(apr_pool_t *atrans, char **line)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return ap_getword_white(atrans, (const char **) line);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_getword_white(apr_pool_t *atrans, const char **line)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *pos = *line;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int len;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe char *res;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while (!apr_isspace(*pos) && *pos) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++pos;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe len = pos - *line;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe res = apr_pstrmemdup(atrans, *line, len);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while (apr_isspace(*pos)) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++pos;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *line = pos;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return res;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_getword_nulls_nc(apr_pool_t *atrans, char **line,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe char stop)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return ap_getword_nulls(atrans, (const char **) line, stop);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_getword_nulls(apr_pool_t *atrans, const char **line,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe char stop)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *pos = ap_strchr_c(*line, stop);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe char *res;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (!pos) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_size_t len = strlen(*line);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe res = apr_pstrmemdup(atrans, *line, len);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *line += len;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return res;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe res = apr_pstrndup(atrans, *line, pos - *line);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++pos;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *line = pos;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return res;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* Get a word, (new) config-file style --- quoted strings and backslashes
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * all honored
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic char *substring_conf(apr_pool_t *p, const char *start, int len,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe char quote)
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm{
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *result = apr_palloc(p, len + 2);
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *resp = result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int i;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (i = 0; i < len; ++i) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (start[i] == '\\' && (start[i + 1] == '\\'
f4c310fd2555c6faca1f980f00b161eadb089023gstein || (quote && start[i + 1] == quote)))
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *resp++ = start[++i];
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *resp++ = start[i];
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *resp++ = '\0';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#if RESOLVE_ENV_PER_TOKEN
f4c310fd2555c6faca1f980f00b161eadb089023gstein return (char *)ap_resolve_env(p,result);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#else
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return result;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#endif
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(char *) ap_getword_conf_nc(apr_pool_t *p, char **line)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein return ap_getword_conf(p, (const char **) line);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_getword_conf(apr_pool_t *p, const char **line)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *str = *line, *strend;
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *res;
f4c310fd2555c6faca1f980f00b161eadb089023gstein char quote;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (*str && apr_isspace(*str))
f4c310fd2555c6faca1f980f00b161eadb089023gstein ++str;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (!*str) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein *line = str;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return "";
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ((quote = *str) == '"' || quote == '\'') {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe strend = str + 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while (*strend && *strend != quote) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (*strend == '\\' && strend[1] &&
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe (strend[1] == quote || strend[1] == '\\')) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe strend += 2;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++strend;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe res = substring_conf(p, str + 1, strend - str - 1, quote);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (*strend == quote)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++strend;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe strend = str;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while (*strend && !apr_isspace(*strend))
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++strend;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe res = substring_conf(p, str, strend - str, 0);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while (*strend && apr_isspace(*strend))
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++strend;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *line = strend;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return res;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(int) ap_cfg_closefile(ap_configfile_t *cfp)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef DEBUG
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, APLOGNO(00551)
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Done with config file %s", cfp->name);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein return (cfp->close == NULL) ? 0 : cfp->close(cfp->param);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* we can't use apr_file_* directly because of linking issues on Windows */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic apr_status_t cfg_close(void *param)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
f4c310fd2555c6faca1f980f00b161eadb089023gstein return apr_file_close(param);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic apr_status_t cfg_getch(char *ch, void *param)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein return apr_file_getc(ch, param);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic apr_status_t cfg_getstr(void *buf, apr_size_t bufsiz, void *param)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein return apr_file_gets(buf, bufsiz, param);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
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,
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe apr_pool_t *p, const char *name)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_configfile_t *new_cfg;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_file_t *file = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_finfo_t finfo;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_status_t status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef DEBUG
f4c310fd2555c6faca1f980f00b161eadb089023gstein char buf[120];
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (name == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, APLOGNO(00552)
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Internal error: pcfg_openfile() called with NULL filename");
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_EBADF;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein status = apr_file_open(&file, name, APR_READ | APR_BUFFERED,
f4c310fd2555c6faca1f980f00b161eadb089023gstein APR_OS_DEFAULT, p);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef DEBUG
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, APLOGNO(00553)
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Opening config file %s (%s)",
f4c310fd2555c6faca1f980f00b161eadb089023gstein name, (status != APR_SUCCESS) ?
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_strerror(status, buf, sizeof(buf)) : "successful");
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (status != APR_SUCCESS)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein status = apr_file_info_get(&finfo, APR_FINFO_TYPE, file);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (status != APR_SUCCESS)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (finfo.filetype != APR_REG &&
f4c310fd2555c6faca1f980f00b161eadb089023gstein#if defined(WIN32) || defined(OS2) || defined(NETWARE)
f4c310fd2555c6faca1f980f00b161eadb089023gstein strcasecmp(apr_filepath_name_get(name), "nul") != 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein#else
f4c310fd2555c6faca1f980f00b161eadb089023gstein strcmp(name, "/dev/null") != 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",
f4c310fd2555c6faca1f980f00b161eadb089023gstein name);
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_file_close(file);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return APR_EBADF;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#ifdef WIN32
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 *
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 */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe unsigned char buf[4];
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_size_t len = 3;
f4c310fd2555c6faca1f980f00b161eadb089023gstein status = apr_file_read(file, buf, &len);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((status != APR_SUCCESS) || (len < 3)
f4c310fd2555c6faca1f980f00b161eadb089023gstein || memcmp(buf, "\xEF\xBB\xBF", 3) != 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_off_t zero = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_file_seek(file, APR_SET, &zero);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe new_cfg = apr_palloc(p, sizeof(*new_cfg));
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe new_cfg->param = file;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe new_cfg->name = apr_pstrdup(p, name);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe new_cfg->getch = cfg_getch;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe new_cfg->getstr = cfg_getstr;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe new_cfg->close = cfg_close;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe new_cfg->line_number = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *ret_cfg = new_cfg;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return APR_SUCCESS;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* Allocate a ap_configfile_t handle with user defined functions and params */
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(ap_configfile_t *) ap_pcfg_open_custom(
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_pool_t *p, const char *descr, void *param,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_status_t (*getc_func) (char *ch, void *param),
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_status_t (*gets_func) (void *buf, apr_size_t bufsize, void *param),
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_status_t (*close_func) (void *param))
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_configfile_t *new_cfg = apr_palloc(p, sizeof(*new_cfg));
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe new_cfg->param = param;
f4c310fd2555c6faca1f980f00b161eadb089023gstein new_cfg->name = descr;
f4c310fd2555c6faca1f980f00b161eadb089023gstein new_cfg->getch = getc_func;
f4c310fd2555c6faca1f980f00b161eadb089023gstein new_cfg->getstr = gets_func;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe new_cfg->close = close_func;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe new_cfg->line_number = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return new_cfg;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Read one character from a configfile_t */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(apr_status_t) ap_cfg_getc(char *ch, ap_configfile_t *cfp)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_status_t rc = cfp->getch(ch, cfp->param);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (rc == APR_SUCCESS && *ch == LF)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++cfp->line_number;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return rc;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(const char *) ap_pcfg_strerror(apr_pool_t *p, ap_configfile_t *cfp,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_status_t rc)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
f4c310fd2555c6faca1f980f00b161eadb089023gstein char buf[MAX_STRING_LEN];
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rc == APR_SUCCESS)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return apr_psprintf(p, "Error reading %s at line %d: %s",
f4c310fd2555c6faca1f980f00b161eadb089023gstein cfp->name, cfp->line_number,
f4c310fd2555c6faca1f980f00b161eadb089023gstein rc == APR_ENOSPC ? "Line too long"
f4c310fd2555c6faca1f980f00b161eadb089023gstein : apr_strerror(rc, buf, sizeof(buf)));
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
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 ap_configfile_t *cfp)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_status_t rc;
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If a "get string" function is defined, use it */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (cfp->getstr != NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe char *cp;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe char *cbuf = buf;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_size_t cbufsize = bufsize;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ++cfp->line_number;
f4c310fd2555c6faca1f980f00b161eadb089023gstein rc = cfp->getstr(cbuf, cbufsize, cfp->param);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rc == APR_EOF) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (cbuf != buf) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein *cbuf = '\0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_EOF;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rc != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return rc;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * check for line continuation,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * i.e. match [^\\]\\[\r]\n only
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe cp = cbuf;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe cp += strlen(cp);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (cp > cbuf && cp[-1] == LF) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein cp--;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (cp > cbuf && cp[-1] == CR)
f4c310fd2555c6faca1f980f00b161eadb089023gstein cp--;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (cp > cbuf && cp[-1] == '\\') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein cp--;
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * line continuation requested -
f4c310fd2555c6faca1f980f00b161eadb089023gstein * then remove backslash and continue
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein cbufsize -= (cp-cbuf);
f4c310fd2555c6faca1f980f00b161eadb089023gstein cbuf = cp;
f4c310fd2555c6faca1f980f00b161eadb089023gstein continue;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (cp - buf >= bufsize - 1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_ENOSPC;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe } else {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* No "get string" function defined; read character by character */
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_size_t i = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (bufsize < 2) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* too small, assume caller is crazy */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_EINVAL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein buf[0] = '\0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein char c;
f4c310fd2555c6faca1f980f00b161eadb089023gstein rc = cfp->getch(&c, cfp->param);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rc == APR_EOF) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (i > 0)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return APR_EOF;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (rc != APR_SUCCESS)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return rc;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (c == LF) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++cfp->line_number;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* check for line continuation */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (i > 0 && buf[i-1] == '\\') {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe i--;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe continue;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else if (i >= bufsize - 2) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return APR_ENOSPC;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe buf[i] = c;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++i;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe buf[i] = '\0';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return APR_SUCCESS;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic int cfg_trim_line(char *buf)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe char *start, *end;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /*
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * Leading and trailing white space is eliminated completely
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe start = buf;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while (apr_isspace(*start))
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++start;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* blast trailing whitespace */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe end = &start[strlen(start)];
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while (--end >= start && apr_isspace(*end))
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *end = '\0';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Zap leading whitespace by shifting */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (start != buf)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe memmove(buf, start, end - start + 2);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#ifdef DEBUG_CFG_LINES
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL, APLOGNO(00555) "Read config: '%s'", buf);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#endif
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return end - start + 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
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 ap_configfile_t *cfp)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_status_t rc = ap_cfg_getline_core(buf, bufsize, cfp);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (rc == APR_SUCCESS)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe cfg_trim_line(buf);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return rc;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(apr_status_t) ap_varbuf_cfg_getline(struct ap_varbuf *vb,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_configfile_t *cfp,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_size_t max_len)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_status_t rc;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_size_t new_len;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe vb->strlen = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *vb->buf = '\0';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (vb->strlen == AP_VARBUF_UNKNOWN)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe vb->strlen = strlen(vb->buf);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (vb->avail - vb->strlen < 3) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe new_len = vb->avail * 2;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (new_len > max_len)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe new_len = max_len;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else if (new_len < 3)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe new_len = 3;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_varbuf_grow(vb, new_len);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (;;) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe rc = ap_cfg_getline_core(vb->buf + vb->strlen, vb->avail - vb->strlen, cfp);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (rc == APR_ENOSPC || rc == APR_SUCCESS)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe vb->strlen += strlen(vb->buf + vb->strlen);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (rc != APR_ENOSPC)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (vb->avail >= max_len)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return APR_ENOSPC;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe new_len = vb->avail * 2;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (new_len > max_len)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe new_len = max_len;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_varbuf_grow(vb, new_len);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe --cfp->line_number;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (vb->strlen > max_len)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return APR_ENOSPC;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (rc == APR_SUCCESS)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe vb->strlen = cfg_trim_line(vb->buf);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return rc;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
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.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(const char *) ap_size_list_item(const char **field, int *len)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const unsigned char *ptr = (const unsigned char *)*field;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const unsigned char *token;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int in_qpair, in_qstr, in_com;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Find first non-comma, non-whitespace byte */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while (*ptr == ',' || apr_isspace(*ptr))
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++ptr;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe token = ptr;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Find the end of this item, skipping over dead bits */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (in_qpair = in_qstr = in_com = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++ptr) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (in_qpair) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe in_qpair = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe switch (*ptr) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein case '\\': in_qpair = 1; /* quoted-pair */
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case '"' : if (!in_com) /* quoted string delim */
f4c310fd2555c6faca1f980f00b161eadb089023gstein in_qstr = !in_qstr;
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case '(' : if (!in_qstr) /* comment (may nest) */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ++in_com;
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case ')' : if (in_com) /* end comment */
f4c310fd2555c6faca1f980f00b161eadb089023gstein --in_com;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm break;
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein default : break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((*len = (ptr - token)) == 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein *field = (const char *)ptr;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return NULL;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Advance field pointer to the next non-comma, non-white byte */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while (*ptr == ',' || apr_isspace(*ptr))
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++ptr;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *field = (const char *)ptr;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return (const char *)token;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
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.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_get_list_item(apr_pool_t *p, const char **field)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *tok_start;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const unsigned char *ptr;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe unsigned char *pos;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe char *token;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int addspace = 0, in_qpair = 0, in_qstr = 0, in_com = 0, tok_len = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
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 */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ((tok_start = ap_size_list_item(field, &tok_len)) == NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return NULL;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe token = apr_palloc(p, tok_len + 1);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
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 */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (ptr = (const unsigned char *)tok_start, pos = (unsigned char *)token;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++ptr) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (in_qpair) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe in_qpair = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *pos++ = *ptr;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe switch (*ptr) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe case '\\': in_qpair = 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (addspace == 1)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *pos++ = ' ';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *pos++ = *ptr;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe addspace = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case '"' : if (!in_com)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe in_qstr = !in_qstr;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (addspace == 1)
f4c310fd2555c6faca1f980f00b161eadb089023gstein *pos++ = ' ';
f4c310fd2555c6faca1f980f00b161eadb089023gstein *pos++ = *ptr;
f4c310fd2555c6faca1f980f00b161eadb089023gstein addspace = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case '(' : if (!in_qstr)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ++in_com;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (addspace == 1)
f4c310fd2555c6faca1f980f00b161eadb089023gstein *pos++ = ' ';
f4c310fd2555c6faca1f980f00b161eadb089023gstein *pos++ = *ptr;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe addspace = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe case ')' : if (in_com)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe --in_com;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *pos++ = *ptr;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe addspace = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe case ' ' :
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe case '\t': if (addspace)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (in_com || in_qstr)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *pos++ = *ptr;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe addspace = 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe case '=' :
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe case '/' :
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe case ';' : if (!(in_com || in_qstr))
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe addspace = -1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *pos++ = *ptr;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe default : if (addspace == 1)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *pos++ = ' ';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *pos++ = (in_com || in_qstr) ? *ptr
f80b9e9d38dff8bc3f51406475adb99d7fe888cegstein : apr_tolower(*ptr);
f80b9e9d38dff8bc3f51406475adb99d7fe888cegstein addspace = 0;
f80b9e9d38dff8bc3f51406475adb99d7fe888cegstein break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *pos = '\0';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return token;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
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.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(int) ap_find_list_item(apr_pool_t *p, const char *line,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *tok)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
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
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (!line || !tok)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe do { /* loop for each item in line's list */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Find first non-comma, non-whitespace byte */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while (*ptr == ',' || apr_isspace(*ptr))
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++ptr;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (*ptr)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe good = 1; /* until proven otherwise for this item */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break; /* no items left and nothing good found */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
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 */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (pos = (const unsigned char *)tok;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *ptr && (in_qpair || in_qstr || in_com || *ptr != ',');
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++ptr) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (in_qpair) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein in_qpair = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (good)
f4c310fd2555c6faca1f980f00b161eadb089023gstein good = (*pos++ == *ptr);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein switch (*ptr) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein case '\\': in_qpair = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (addspace == 1)
f4c310fd2555c6faca1f980f00b161eadb089023gstein good = good && (*pos++ == ' ');
f4c310fd2555c6faca1f980f00b161eadb089023gstein good = good && (*pos++ == *ptr);
f4c310fd2555c6faca1f980f00b161eadb089023gstein addspace = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case '"' : if (!in_com)
f4c310fd2555c6faca1f980f00b161eadb089023gstein in_qstr = !in_qstr;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (addspace == 1)
f4c310fd2555c6faca1f980f00b161eadb089023gstein good = good && (*pos++ == ' ');
f4c310fd2555c6faca1f980f00b161eadb089023gstein good = good && (*pos++ == *ptr);
f4c310fd2555c6faca1f980f00b161eadb089023gstein addspace = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe case '(' : if (!in_qstr)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++in_com;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (addspace == 1)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe good = good && (*pos++ == ' ');
f4c310fd2555c6faca1f980f00b161eadb089023gstein good = good && (*pos++ == *ptr);
f4c310fd2555c6faca1f980f00b161eadb089023gstein addspace = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case ')' : if (in_com)
f4c310fd2555c6faca1f980f00b161eadb089023gstein --in_com;
f4c310fd2555c6faca1f980f00b161eadb089023gstein good = good && (*pos++ == *ptr);
f4c310fd2555c6faca1f980f00b161eadb089023gstein addspace = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case ' ' :
f4c310fd2555c6faca1f980f00b161eadb089023gstein case '\t': if (addspace || !good)
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (in_com || in_qstr)
f4c310fd2555c6faca1f980f00b161eadb089023gstein good = (*pos++ == *ptr);
f4c310fd2555c6faca1f980f00b161eadb089023gstein else
f4c310fd2555c6faca1f980f00b161eadb089023gstein addspace = 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe case '=' :
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe case '/' :
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe case ';' : if (!(in_com || in_qstr))
f4c310fd2555c6faca1f980f00b161eadb089023gstein addspace = -1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein good = good && (*pos++ == *ptr);
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe default : if (!good)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (addspace == 1)
f4c310fd2555c6faca1f980f00b161eadb089023gstein good = (*pos++ == ' ');
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (in_com || in_qstr)
f4c310fd2555c6faca1f980f00b161eadb089023gstein good = good && (*pos++ == *ptr);
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein else
f4c310fd2555c6faca1f980f00b161eadb089023gstein good = good && (*pos++ == apr_tolower(*ptr));
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein addspace = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (good && *pos)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe good = 0; /* not good if only a prefix was matched */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe } while (*ptr && !good);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return good;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein
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.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(char *) ap_get_token(apr_pool_t *p, const char **accept_line,
f4c310fd2555c6faca1f980f00b161eadb089023gstein int accept_white)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein const char *ptr = *accept_line;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *tok_start;
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *token;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int tok_len;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Find first non-white byte */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (*ptr && apr_isspace(*ptr))
f4c310fd2555c6faca1f980f00b161eadb089023gstein ++ptr;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein tok_start = ptr;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* find token end, skipping over quoted strings.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * (comments are already gone).
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (*ptr && (accept_white || !apr_isspace(*ptr))
f4c310fd2555c6faca1f980f00b161eadb089023gstein && *ptr != ';' && *ptr != ',') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (*ptr++ == '"')
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while (*ptr)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (*ptr++ == '"')
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein tok_len = ptr - tok_start;
f4c310fd2555c6faca1f980f00b161eadb089023gstein token = apr_pstrndup(p, tok_start, tok_len);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Advance accept_line pointer to the next non-white byte */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (*ptr && apr_isspace(*ptr))
f4c310fd2555c6faca1f980f00b161eadb089023gstein ++ptr;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein *accept_line = ptr;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return token;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gstein
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)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
f4c310fd2555c6faca1f980f00b161eadb089023gstein const unsigned char *start_token;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const unsigned char *s;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!line)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gstein s = (const unsigned char *)line;
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (;;) {
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
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while (TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ++s;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!*s) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe start_token = s;
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* find end of the token */
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (*s && !TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ++s;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!strncasecmp((const char *)start_token, (const char *)tok,
f4c310fd2555c6faca1f980f00b161eadb089023gstein s - start_token)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (!*s) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(int) ap_find_last_token(apr_pool_t *p, const char *line,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *tok)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int llen, tlen, lidx;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (!line)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein llen = strlen(line);
f4c310fd2555c6faca1f980f00b161eadb089023gstein tlen = strlen(tok);
f4c310fd2555c6faca1f980f00b161eadb089023gstein lidx = llen - tlen;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (lidx < 0 ||
f4c310fd2555c6faca1f980f00b161eadb089023gstein (lidx > 0 && !(apr_isspace(line[lidx - 1]) || line[lidx - 1] == ',')))
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return (strncasecmp(&line[lidx], tok, tlen) == 0);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(char *) ap_escape_shell_cmd(apr_pool_t *p, const char *str)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *cmd;
f4c310fd2555c6faca1f980f00b161eadb089023gstein unsigned char *d;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const unsigned char *s;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
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
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#if defined(OS2) || defined(WIN32)
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein /*
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * Newlines to Win32/OS2 CreateProcess() are ill advised.
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein * Convert them to spaces since they are effectively white
f4c310fd2555c6faca1f980f00b161eadb089023gstein * space to most applications
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (*s == '\r' || *s == '\n') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein *d++ = ' ';
f4c310fd2555c6faca1f980f00b161eadb089023gstein continue;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#endif
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (TEST_CHAR(*s, T_ESCAPE_SHELL_CMD)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein *d++ = '\\';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *d++ = *s;
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *d = '\0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return cmd;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic char x2c(const char *what)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein register char digit;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#if !APR_CHARSET_EBCDIC
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein digit = ((what[0] >= 'A') ? ((what[0] & 0xdf) - 'A') + 10
f4c310fd2555c6faca1f980f00b161eadb089023gstein : (what[0] - '0'));
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein digit *= 16;
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A') + 10
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe : (what[1] - '0'));
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#else /*APR_CHARSET_EBCDIC*/
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe char xstr[5];
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe xstr[0]='0';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe xstr[1]='x';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe xstr[2]=what[0];
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe xstr[3]=what[1];
f4c310fd2555c6faca1f980f00b161eadb089023gstein xstr[4]='\0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein digit = apr_xlate_conv_byte(ap_hdrs_from_ascii,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe 0xFF & strtol(xstr, NULL, 16));
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#endif /*APR_CHARSET_EBCDIC*/
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return (digit);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/*
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 *
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * decoding %00 or a forbidden character returns HTTP_NOT_FOUND
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic int unescape_url(char *url, const char *forbid, const char *reserved)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
f4c310fd2555c6faca1f980f00b161eadb089023gstein register int badesc, badpath;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm char *x, *y;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein badesc = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein badpath = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Initial scan for first '%'. Don't bother writing values before
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * seeing a '%' */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe y = strchr(url, '%');
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (y == NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return OK;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (x = y; *y; ++x, ++y) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (*y != '%') {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *x = *y;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!apr_isxdigit(*(y + 1)) || !apr_isxdigit(*(y + 2))) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein badesc = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein *x = '%';
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein char decoded;
f4c310fd2555c6faca1f980f00b161eadb089023gstein decoded = x2c(y + 1);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((decoded == '\0')
f4c310fd2555c6faca1f980f00b161eadb089023gstein || (forbid && ap_strchr_c(forbid, decoded))) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein badpath = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein *x = decoded;
f4c310fd2555c6faca1f980f00b161eadb089023gstein y += 2;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (reserved && ap_strchr_c(reserved, decoded)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein *x++ = *y++;
f4c310fd2555c6faca1f980f00b161eadb089023gstein *x++ = *y++;
f4c310fd2555c6faca1f980f00b161eadb089023gstein *x = *y;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein *x = decoded;
f4c310fd2555c6faca1f980f00b161eadb089023gstein y += 2;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein *x = '\0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (badesc) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (badpath) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm return HTTP_NOT_FOUND;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return OK;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(int) ap_unescape_url(char *url)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Traditional */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm return unescape_url(url, SLASHES, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(int) ap_unescape_url_keep2f(char *url, int decode_slashes)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* AllowEncodedSlashes (corrected) */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (decode_slashes) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* no chars reserved */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return unescape_url(url, NULL, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein } else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* reserve (do not decode) encoded slashes */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return unescape_url(url, NULL, SLASHES);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef NEW_APIS
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* IFDEF these out until they've been thought through.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Just a germ of an API extension for now
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(int) ap_unescape_url_proxy(char *url)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* leave RFC1738 reserved characters intact, * so proxied URLs
f4c310fd2555c6faca1f980f00b161eadb089023gstein * don't get mangled. Where does that leave encoded '&' ?
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return unescape_url(url, NULL, "/;?");
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(int) ap_unescape_url_reserved(char *url, const char *reserved)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein return unescape_url(url, NULL, reserved);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(int) ap_unescape_urlencoded(char *query)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *slider;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* replace plus with a space */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (query) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (slider = query; *slider; slider++) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (*slider == '+') {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *slider = ' ';
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* unescape everything else */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return unescape_url(query, NULL, NULL);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_construct_server(apr_pool_t *p, const char *hostname,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_port_t port, const request_rec *r)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (ap_is_default_port(port, r)) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return apr_pstrdup(p, hostname);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return apr_psprintf(p, "%s:%u", hostname, port);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(int) ap_unescape_all(char *url)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein return unescape_url(url, NULL, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
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 *
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
50bd75672ef114fb839dd9643c192b432fdf344cgstein * again.
50bd75672ef114fb839dd9643c192b432fdf344cgstein */
50bd75672ef114fb839dd9643c192b432fdf344cgsteinstatic const char c2x_table[] = "0123456789abcdef";
50bd75672ef114fb839dd9643c192b432fdf344cgstein
50bd75672ef114fb839dd9643c192b432fdf344cgsteinstatic APR_INLINE unsigned char *c2x(unsigned what, unsigned char prefix,
50bd75672ef114fb839dd9643c192b432fdf344cgstein unsigned char *where)
50bd75672ef114fb839dd9643c192b432fdf344cgstein{
50bd75672ef114fb839dd9643c192b432fdf344cgstein#if APR_CHARSET_EBCDIC
50bd75672ef114fb839dd9643c192b432fdf344cgstein what = apr_xlate_conv_byte(ap_hdrs_to_ascii, (unsigned char)what);
50bd75672ef114fb839dd9643c192b432fdf344cgstein#endif /*APR_CHARSET_EBCDIC*/
50bd75672ef114fb839dd9643c192b432fdf344cgstein *where++ = prefix;
50bd75672ef114fb839dd9643c192b432fdf344cgstein *where++ = c2x_table[what >> 4];
50bd75672ef114fb839dd9643c192b432fdf344cgstein *where++ = c2x_table[what & 0xf];
50bd75672ef114fb839dd9643c192b432fdf344cgstein return where;
50bd75672ef114fb839dd9643c192b432fdf344cgstein}
f39230a531b23d94f86a087963299bbe2e431a4agstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein/*
f39230a531b23d94f86a087963299bbe2e431a4agstein * escape_path_segment() escapes a path segment, as defined in RFC 1808. This
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein * routine is (should be) OS independent.
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein *
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.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *
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 "./").
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein */
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agsteinAP_DECLARE(char *) ap_escape_path_segment_buffer(char *copy, const char *segment)
f39230a531b23d94f86a087963299bbe2e431a4agstein{
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein const unsigned char *s = (const unsigned char *)segment;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein unsigned char *d = (unsigned char *)copy;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein unsigned c;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while ((c = *s)) {
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein if (TEST_CHAR(c, T_ESCAPE_PATH_SEGMENT)) {
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein d = c2x(c, '%', d);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *d++ = c;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++s;
f39230a531b23d94f86a087963299bbe2e431a4agstein }
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein *d = '\0';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return copy;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(char *) ap_escape_path_segment(apr_pool_t *p, const char *segment)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein return ap_escape_path_segment_buffer(apr_palloc(p, 3 * strlen(segment) + 1), segment);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein}
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gsteinAP_DECLARE(char *) ap_os_escape_path(apr_pool_t *p, const char *path, int partial)
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein{
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein char *copy = apr_palloc(p, 3 * strlen(path) + 3);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein const unsigned char *s = (const unsigned char *)path;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein unsigned char *d = (unsigned char *)copy;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein unsigned c;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if (!partial) {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein const char *colon = ap_strchr_c(path, ':');
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein const char *slash = ap_strchr_c(path, '/');
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if (colon && (!slash || colon < slash)) {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = '.';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = '/';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein while ((c = *s)) {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if (TEST_CHAR(c, T_OS_ESCAPE_PATH)) {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein d = c2x(c, '%', d);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein else {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = c;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein ++s;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d = '\0';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein return copy;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein}
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gsteinAP_DECLARE(char *) ap_escape_urlencoded_buffer(char *copy, const char *buffer)
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein{
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein const unsigned char *s = (const unsigned char *)buffer;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein unsigned char *d = (unsigned char *)copy;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein unsigned c;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein while ((c = *s)) {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if (TEST_CHAR(c, T_ESCAPE_URLENCODED)) {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein d = c2x(c, '%', d);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein else if (c == ' ') {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *d++ = '+';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *d++ = c;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein ++s;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d = '\0';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein return copy;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein}
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gsteinAP_DECLARE(char *) ap_escape_urlencoded(apr_pool_t *p, const char *buffer)
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein{
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein return ap_escape_urlencoded_buffer(apr_palloc(p, 3 * strlen(buffer) + 1), buffer);
50bd75672ef114fb839dd9643c192b432fdf344cgstein}
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein/* ap_escape_uri is now a macro for os_escape_path */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gsteinAP_DECLARE(char *) ap_escape_html2(apr_pool_t *p, const char *s, int toasc)
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein int i, j;
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *x;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein /* first, count the number of extra characters */
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (i = 0, j = 0; s[i] != '\0'; i++)
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein if (s[i] == '<' || s[i] == '>')
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein j += 3;
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (s[i] == '&')
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein j += 4;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein else if (s[i] == '"')
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein j += 5;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein else if (toasc && !apr_isascii(s[i]))
f4c310fd2555c6faca1f980f00b161eadb089023gstein j += 5;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (j == 0)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return apr_pstrmemdup(p, s, i);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein x = apr_palloc(p, i + j + 1);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein for (i = 0, j = 0; s[i] != '\0'; i++, j++)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (s[i] == '<') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein memcpy(&x[j], "&lt;", 4);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe j += 3;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else if (s[i] == '>') {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein memcpy(&x[j], "&gt;", 4);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe j += 3;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (s[i] == '&') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein memcpy(&x[j], "&amp;", 5);
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein j += 4;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein else if (s[i] == '"') {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe memcpy(&x[j], "&quot;", 6);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein j += 5;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein else if (toasc && !apr_isascii(s[i])) {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein char *esc = apr_psprintf(p, "&#%3.3d;", (unsigned char)s[i]);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein memcpy(&x[j], esc, 6);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein j += 5;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein else
f4c310fd2555c6faca1f980f00b161eadb089023gstein x[j] = s[i];
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe x[j] = '\0';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return x;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein}
83719c22db4a6d0575bb4f7f34382d7b185a6f74gsteinAP_DECLARE(char *) ap_escape_logitem(apr_pool_t *p, const char *str)
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein{
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein char *ret;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein unsigned char *d;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein const unsigned char *s;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (!str) {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein return NULL;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein }
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein
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) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if (TEST_CHAR(*s, T_ESCAPE_LOGITEM)) {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = '\\';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe switch(*s) {
50bd75672ef114fb839dd9643c192b432fdf344cgstein case '\b':
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein *d++ = 'b';
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe case '\n':
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = 'n';
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein case '\r':
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = 'r';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein break;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein case '\t':
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = 't';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein break;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein case '\v':
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = 'v';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe case '\\':
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe case '"':
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *d++ = *s;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein default:
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein c2x(*s, 'x', d);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe d += 3;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein *d++ = *s;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d = '\0';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein return ret;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein}
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gsteinAP_DECLARE(apr_size_t) ap_escape_errorlog_item(char *dest, const char *source,
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein apr_size_t buflen)
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein{
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein unsigned char *d, *ep;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein const unsigned char *s;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (!source || !buflen) { /* be safe */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein return 0;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein d = (unsigned char *)dest;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein s = (const unsigned char *)source;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ep = d + buflen - 1;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein for (; d < ep && *s; ++s) {
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if (TEST_CHAR(*s, T_ESCAPE_LOGITEM)) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *d++ = '\\';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (d >= ep) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe --d;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein break;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
50bd75672ef114fb839dd9643c192b432fdf344cgstein switch(*s) {
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein case '\b':
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein *d++ = 'b';
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case '\n':
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = 'n';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein break;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein case '\r':
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = 'r';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein break;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein case '\t':
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = 't';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein break;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein case '\v':
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = 'v';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein break;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein case '\\':
f4c310fd2555c6faca1f980f00b161eadb089023gstein *d++ = *s;
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case '"': /* no need for this in error log */
50bd75672ef114fb839dd9643c192b432fdf344cgstein d[-1] = *s;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein break;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein default:
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein if (d >= ep - 2) {
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein ep = --d; /* break the for loop as well */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein break;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein c2x(*s, 'x', d);
f4c310fd2555c6faca1f980f00b161eadb089023gstein d += 3;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein else {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d++ = *s;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *d = '\0';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein return (d - (unsigned char *)dest);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein}
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gsteinAP_DECLARE(int) ap_is_directory(apr_pool_t *p, const char *path)
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe apr_finfo_t finfo;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if (apr_stat(&finfo, path, APR_FINFO_TYPE, p) != APR_SUCCESS)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return 0; /* in error condition, just return no */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein return (finfo.filetype == APR_DIR);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gsteinAP_DECLARE(int) ap_is_rdirectory(apr_pool_t *p, const char *path)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein apr_finfo_t finfo;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if (apr_stat(&finfo, path, APR_FINFO_LINK | APR_FINFO_TYPE, p) != APR_SUCCESS)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return 0; /* in error condition, just return no */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return (finfo.filetype == APR_DIR);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(char *) ap_make_full_path(apr_pool_t *a, const char *src1,
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein const char *src2)
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_size_t len1, len2;
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *path;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein len1 = strlen(src1);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein len2 = strlen(src2);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* allocate +3 for '/' delimiter, trailing NULL and overallocate
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * one extra byte to allow the caller to add a trailing '/'
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein path = (char *)apr_palloc(a, len1 + len2 + 3);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (len1 == 0) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *path = '/';
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe memcpy(path + 1, src2, len2 + 1);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein else {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein char *next;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein memcpy(path, src1, len1);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein next = path + len1;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if (next[-1] != '/') {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein *next++ = '/';
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein memcpy(next, src2, len2 + 1);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein return path;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein}
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein/*
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein * Check for an absoluteURI syntax (see section 3.2 in RFC2068).
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gsteinAP_DECLARE(int) ap_is_url(const char *u)
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein{
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein register int x;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (x = 0; u[x] != ':'; x++) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ((!u[x]) ||
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ((!apr_isalpha(u[x])) && (!apr_isdigit(u[x])) &&
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe (u[x] != '+') && (u[x] != '-') && (u[x] != '.'))) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein return (x ? 1 : 0); /* If the first character is ':', it's broken, too */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein}
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
cdcb6937fbc9f4283e1783a0d43b62e9e8ad08d3gsteinAP_DECLARE(int) ap_ind(const char *s, char c)
cdcb6937fbc9f4283e1783a0d43b62e9e8ad08d3gstein{
cdcb6937fbc9f4283e1783a0d43b62e9e8ad08d3gstein const char *p = ap_strchr_c(s, c);
cdcb6937fbc9f4283e1783a0d43b62e9e8ad08d3gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if (p == NULL)
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein return -1;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein return p - s;
cdcb6937fbc9f4283e1783a0d43b62e9e8ad08d3gstein}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gsteinAP_DECLARE(int) ap_rind(const char *s, char c)
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *p = ap_strrchr_c(s, c);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (p == NULL)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return -1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return p - s;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(void) ap_str_tolower(char *str)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (*str) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein *str = apr_tolower(*str);
++str;
}
}
AP_DECLARE(void) ap_str_toupper(char *str)
{
while (*str) {
*str = apr_toupper(*str);
++str;
}
}
/*
* We must return a FQDN
*/
char *ap_get_local_host(apr_pool_t *a)
{
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 256
#endif
char str[MAXHOSTNAMELEN + 1];
char *server_hostname = NULL;
apr_sockaddr_t *sockaddr;
char *hostname;
if (apr_gethostname(str, sizeof(str) - 1, a) != APR_SUCCESS) {
ap_log_perror(APLOG_MARK, APLOG_STARTUP | APLOG_WARNING, 0, a, APLOGNO(00556)
"%s: apr_gethostname() failed to determine ServerName",
ap_server_argv0);
} else {
str[sizeof(str) - 1] = '\0';
if (apr_sockaddr_info_get(&sockaddr, str, APR_UNSPEC, 0, 0, a) == APR_SUCCESS) {
if ( (apr_getnameinfo(&hostname, sockaddr, 0) == APR_SUCCESS) &&
(ap_strchr_c(hostname, '.')) ) {
server_hostname = apr_pstrdup(a, hostname);
return server_hostname;
} else if (ap_strchr_c(str, '.')) {
server_hostname = apr_pstrdup(a, str);
} else {
apr_sockaddr_ip_get(&hostname, sockaddr);
server_hostname = apr_pstrdup(a, hostname);
}
} else {
ap_log_perror(APLOG_MARK, APLOG_STARTUP | APLOG_WARNING, 0, a, APLOGNO(00557)
"%s: apr_sockaddr_info_get() failed for %s",
ap_server_argv0, str);
}
}
if (!server_hostname)
server_hostname = apr_pstrdup(a, "127.0.0.1");
ap_log_perror(APLOG_MARK, APLOG_ALERT|APLOG_STARTUP, 0, a, APLOGNO(00558)
"%s: Could not reliably determine the server's fully qualified "
"domain name, using %s. Set the 'ServerName' directive globally "
"to suppress this message",
ap_server_argv0, server_hostname);
return server_hostname;
}
/* simple 'pool' alloc()ing glue to apr_base64.c
*/
AP_DECLARE(char *) ap_pbase64decode(apr_pool_t *p, const char *bufcoded)
{
char *decoded;
int l;
decoded = (char *) apr_palloc(p, 1 + apr_base64_decode_len(bufcoded));
l = apr_base64_decode(decoded, bufcoded);
decoded[l] = '\0'; /* make binary sequence into string */
return decoded;
}
AP_DECLARE(char *) ap_pbase64encode(apr_pool_t *p, char *string)
{
char *encoded;
int l = strlen(string);
encoded = (char *) apr_palloc(p, 1 + apr_base64_encode_len(l));
l = apr_base64_encode(encoded, string, l);
encoded[l] = '\0'; /* make binary sequence into string */
return encoded;
}
/* we want to downcase the type/subtype for comparison purposes
* but nothing else because ;parameter=foo values are case sensitive.
* XXX: in truth we want to downcase parameter names... but really,
* apache has never handled parameters and such correctly. You
* also need to compress spaces and such to be able to compare
* properly. -djg
*/
AP_DECLARE(void) ap_content_type_tolower(char *str)
{
char *semi;
semi = strchr(str, ';');
if (semi) {
*semi = '\0';
}
ap_str_tolower(str);
if (semi) {
*semi = ';';
}
}
/*
* Given a string, replace any bare " with \" .
*/
AP_DECLARE(char *) ap_escape_quotes(apr_pool_t *p, const char *instring)
{
int newlen = 0;
const char *inchr = instring;
char *outchr, *outstring;
/*
* Look through the input string, jogging the length of the output
* string up by an extra byte each time we find an unescaped ".
*/
while (*inchr != '\0') {
newlen++;
if (*inchr == '"') {
newlen++;
}
/*
* If we find a slosh, and it's not the last byte in the string,
* it's escaping something - advance past both bytes.
*/
if ((*inchr == '\\') && (inchr[1] != '\0')) {
inchr++;
newlen++;
}
inchr++;
}
outstring = apr_palloc(p, newlen + 1);
inchr = instring;
outchr = outstring;
/*
* Now copy the input string to the output string, inserting a slosh
* in front of every " that doesn't already have one.
*/
while (*inchr != '\0') {
if ((*inchr == '\\') && (inchr[1] != '\0')) {
*outchr++ = *inchr++;
*outchr++ = *inchr++;
}
if (*inchr == '"') {
*outchr++ = '\\';
}
if (*inchr != '\0') {
*outchr++ = *inchr++;
}
}
*outchr = '\0';
return outstring;
}
/*
* Given a string, append the PID deliminated by delim.
* Usually used to create a pid-appended filepath name
* (eg: /a/b/foo -> /a/b/foo.6726). A function, and not
* a macro, to avoid unistd.h dependency
*/
AP_DECLARE(char *) ap_append_pid(apr_pool_t *p, const char *string,
const char *delim)
{
return apr_psprintf(p, "%s%s%" APR_PID_T_FMT, string,
delim, getpid());
}
/**
* Parse a given timeout parameter string into an apr_interval_time_t value.
* The unit of the time interval is given as postfix string to the numeric
* string. Currently the following units are understood:
*
* ms : milliseconds
* s : seconds
* mi[n] : minutes
* h : hours
*
* If no unit is contained in the given timeout parameter the default_time_unit
* will be used instead.
* @param timeout_parameter The string containing the timeout parameter.
* @param timeout The timeout value to be returned.
* @param default_time_unit The default time unit to use if none is specified
* in timeout_parameter.
* @return Status value indicating whether the parsing was successful or not.
*/
AP_DECLARE(apr_status_t) ap_timeout_parameter_parse(
const char *timeout_parameter,
apr_interval_time_t *timeout,
const char *default_time_unit)
{
char *endp;
const char *time_str;
apr_int64_t tout;
tout = apr_strtoi64(timeout_parameter, &endp, 10);
if (errno) {
return errno;
}
if (!endp || !*endp) {
time_str = default_time_unit;
}
else {
time_str = endp;
}
switch (*time_str) {
/* Time is in seconds */
case 's':
*timeout = (apr_interval_time_t) apr_time_from_sec(tout);
break;
case 'h':
/* Time is in hours */
*timeout = (apr_interval_time_t) apr_time_from_sec(tout * 3600);
break;
case 'm':
switch (*(++time_str)) {
/* Time is in milliseconds */
case 's':
*timeout = (apr_interval_time_t) tout * 1000;
break;
/* Time is in minutes */
case 'i':
*timeout = (apr_interval_time_t) apr_time_from_sec(tout * 60);
break;
default:
return APR_EGENERAL;
}
break;
default:
return APR_EGENERAL;
}
return APR_SUCCESS;
}
/**
* Determine if a request has a request body or not.
*
* @param r the request_rec of the request
* @return truth value
*/
AP_DECLARE(int) ap_request_has_body(request_rec *r)
{
apr_off_t cl;
char *estr;
const char *cls;
int has_body;
has_body = (!r->header_only
&& (r->kept_body
|| apr_table_get(r->headers_in, "Transfer-Encoding")
|| ( (cls = apr_table_get(r->headers_in, "Content-Length"))
&& (apr_strtoff(&cl, cls, &estr, 10) == APR_SUCCESS)
&& (!*estr)
&& (cl > 0) )
)
);
return has_body;
}
AP_DECLARE_NONSTD(apr_status_t) ap_pool_cleanup_set_null(void *data_)
{
void **ptr = (void **)data_;
*ptr = NULL;
return APR_SUCCESS;
}
AP_DECLARE(apr_status_t) ap_str2_alnum(const char *src, char *dest) {
for ( ; *src; src++, dest++)
{
if (!apr_isprint(*src))
*dest = 'x';
else if (!apr_isalnum(*src))
*dest = '_';
else
*dest = (char)*src;
}
*dest = '\0';
return APR_SUCCESS;
}
AP_DECLARE(apr_status_t) ap_pstr2_alnum(apr_pool_t *p, const char *src,
const char **dest)
{
char *new = apr_palloc(p, strlen(src)+1);
if (!new)
return APR_ENOMEM;
*dest = new;
return ap_str2_alnum(src, new);
}
/**
* Read the body and parse any form found, which must be of the
* type application/x-www-form-urlencoded.
*
* Name/value pairs are returned in an array, with the names as
* strings with a maximum length of HUGE_STRING_LEN, and the
* values as bucket brigades. This allows values to be arbitrarily
* large.
*
* All url-encoding is removed from both the names and the values
* on the fly. The names are interpreted as strings, while the
* values are interpreted as blocks of binary data, that may
* contain the 0 character.
*
* In order to ensure that resource limits are not exceeded, a
* maximum size must be provided. If the sum of the lengths of
* the names and the values exceed this size, this function
* will return HTTP_REQUEST_ENTITY_TOO_LARGE.
*
* An optional number of parameters can be provided, if the number
* of parameters provided exceeds this amount, this function will
* return HTTP_REQUEST_ENTITY_TOO_LARGE. If this value is negative,
* no limit is imposed, and the number of parameters is in turn
* constrained by the size parameter above.
*
* This function honours any kept_body configuration, and the
* original raw request body will be saved to the kept_body brigade
* if so configured, just as ap_discard_request_body does.
*
* NOTE: File upload is not yet supported, but can be without change
* to the function call.
*/
/* form parsing stuff */
typedef enum {
FORM_NORMAL,
FORM_AMP,
FORM_NAME,
FORM_VALUE,
FORM_PERCENTA,
FORM_PERCENTB,
FORM_ABORT
} ap_form_type_t;
AP_DECLARE(int) ap_parse_form_data(request_rec *r, ap_filter_t *f,
apr_array_header_t **ptr,
apr_size_t num, apr_size_t usize)
{
apr_bucket_brigade *bb = NULL;
int seen_eos = 0;
char buffer[HUGE_STRING_LEN + 1];
const char *ct;
apr_size_t offset = 0;
apr_ssize_t size;
ap_form_type_t state = FORM_NAME, percent = FORM_NORMAL;
ap_form_pair_t *pair = NULL;
apr_array_header_t *pairs = apr_array_make(r->pool, 4, sizeof(ap_form_pair_t));
char hi = 0;
char low = 0;
*ptr = pairs;
/* sanity check - we only support forms for now */
ct = apr_table_get(r->headers_in, "Content-Type");
if (!ct || ap_strcmp_match(ct, "application/x-www-form-urlencoded*")) {
return ap_discard_request_body(r);
}
if (usize > APR_SIZE_MAX >> 1)
size = APR_SIZE_MAX >> 1;
else
size = usize;
if (!f) {
f = r->input_filters;
}
bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
do {
apr_bucket *bucket = NULL, *last = NULL;
int rv = ap_get_brigade(f, bb, AP_MODE_READBYTES,
APR_BLOCK_READ, HUGE_STRING_LEN);
if (rv != APR_SUCCESS) {
apr_brigade_destroy(bb);
return (rv == AP_FILTER_ERROR) ? rv : HTTP_BAD_REQUEST;
}
for (bucket = APR_BRIGADE_FIRST(bb);
bucket != APR_BRIGADE_SENTINEL(bb);
last = bucket, bucket = APR_BUCKET_NEXT(bucket)) {
const char *data;
apr_size_t len, slide;
if (last) {
apr_bucket_delete(last);
}
if (APR_BUCKET_IS_EOS(bucket)) {
seen_eos = 1;
break;
}
if (bucket->length == 0) {
continue;
}
rv = apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
if (rv != APR_SUCCESS) {
apr_brigade_destroy(bb);
return HTTP_BAD_REQUEST;
}
slide = len;
while (state != FORM_ABORT && slide-- > 0 && size >= 0 && num != 0) {
char c = *data++;
if ('+' == c) {
c = ' ';
}
else if ('&' == c) {
state = FORM_AMP;
}
if ('%' == c) {
percent = FORM_PERCENTA;
continue;
}
if (FORM_PERCENTA == percent) {
if (c >= 'a') {
hi = c - 'a' + 10;
}
else if (c >= 'A') {
hi = c - 'A' + 10;
}
else if (c >= '0') {
hi = c - '0';
}
hi = hi << 4;
percent = FORM_PERCENTB;
continue;
}
if (FORM_PERCENTB == percent) {
if (c >= 'a') {
low = c - 'a' + 10;
}
else if (c >= 'A') {
low = c - 'A' + 10;
}
else if (c >= '0') {
low = c - '0';
}
c = low | hi;
percent = FORM_NORMAL;
}
switch (state) {
case FORM_AMP:
if (pair) {
const char *tmp = apr_pmemdup(r->pool, buffer, offset);
apr_bucket *b = apr_bucket_pool_create(tmp, offset, r->pool, r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(pair->value, b);
}
state = FORM_NAME;
pair = NULL;
offset = 0;
num--;
break;
case FORM_NAME:
if (offset < HUGE_STRING_LEN) {
if ('=' == c) {
buffer[offset] = 0;
offset = 0;
pair = (ap_form_pair_t *) apr_array_push(pairs);
pair->name = apr_pstrdup(r->pool, buffer);
pair->value = apr_brigade_create(r->pool, r->connection->bucket_alloc);
state = FORM_VALUE;
}
else {
buffer[offset++] = c;
size--;
}
}
else {
state = FORM_ABORT;
}
break;
case FORM_VALUE:
if (offset >= HUGE_STRING_LEN) {
const char *tmp = apr_pmemdup(r->pool, buffer, offset);
apr_bucket *b = apr_bucket_pool_create(tmp, offset, r->pool, r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(pair->value, b);
offset = 0;
}
buffer[offset++] = c;
size--;
break;
default:
break;
}
}
}
apr_brigade_cleanup(bb);
} while (!seen_eos);
if (FORM_ABORT == state || size < 0 || num == 0) {
return HTTP_REQUEST_ENTITY_TOO_LARGE;
}
else if (FORM_VALUE == state && pair && offset > 0) {
const char *tmp = apr_pmemdup(r->pool, buffer, offset);
apr_bucket *b = apr_bucket_pool_create(tmp, offset, r->pool, r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(pair->value, b);
}
return OK;
}
#define VARBUF_SMALL_SIZE 2048
#define VARBUF_MAX_SIZE (APR_SIZE_MAX - 1 - \
APR_ALIGN_DEFAULT(sizeof(struct ap_varbuf_info)))
struct ap_varbuf_info {
struct apr_memnode_t *node;
apr_allocator_t *allocator;
};
static apr_status_t varbuf_cleanup(void *info_)
{
struct ap_varbuf_info *info = info_;
info->node->next = NULL;
apr_allocator_free(info->allocator, info->node);
return APR_SUCCESS;
}
const char nul = '\0';
static char * const varbuf_empty = (char *)&nul;
AP_DECLARE(void) ap_varbuf_init(apr_pool_t *p, struct ap_varbuf *vb,
apr_size_t init_size)
{
vb->buf = varbuf_empty;
vb->avail = 0;
vb->strlen = AP_VARBUF_UNKNOWN;
vb->pool = p;
vb->info = NULL;
ap_varbuf_grow(vb, init_size);
}
AP_DECLARE(void) ap_varbuf_grow(struct ap_varbuf *vb, apr_size_t new_len)
{
apr_memnode_t *new_node = NULL;
apr_allocator_t *allocator;
struct ap_varbuf_info *new_info;
char *new;
AP_DEBUG_ASSERT(vb->strlen == AP_VARBUF_UNKNOWN || vb->avail >= vb->strlen);
if (new_len <= vb->avail)
return;
if (new_len < 2 * vb->avail && vb->avail < VARBUF_MAX_SIZE/2) {
/* at least double the size, to avoid repeated reallocations */
new_len = 2 * vb->avail;
}
else if (new_len > VARBUF_MAX_SIZE) {
apr_abortfunc_t abort_fn = apr_pool_abort_get(vb->pool);
ap_assert(abort_fn != NULL);
abort_fn(APR_ENOMEM);
return;
}
new_len++; /* add space for trailing \0 */
if (new_len <= VARBUF_SMALL_SIZE) {
new_len = APR_ALIGN_DEFAULT(new_len);
new = apr_palloc(vb->pool, new_len);
if (vb->avail && vb->strlen != 0) {
AP_DEBUG_ASSERT(vb->buf != NULL);
AP_DEBUG_ASSERT(vb->buf != varbuf_empty);
if (new == vb->buf + vb->avail + 1) {
/* We are lucky: the new memory lies directly after our old
* buffer, we can now use both.
*/
vb->avail += new_len;
return;
}
else {
/* copy up to vb->strlen + 1 bytes */
memcpy(new, vb->buf, vb->strlen == AP_VARBUF_UNKNOWN ?
vb->avail + 1 : vb->strlen + 1);
}
}
else {
*new = '\0';
}
vb->avail = new_len - 1;
vb->buf = new;
return;
}
/* The required block is rather larger. Use allocator directly so that
* the memory can be freed independently from the pool. */
allocator = apr_pool_allocator_get(vb->pool);
if (new_len <= VARBUF_MAX_SIZE)
new_node = apr_allocator_alloc(allocator,
new_len + APR_ALIGN_DEFAULT(sizeof(*new_info)));
if (!new_node) {
apr_abortfunc_t abort_fn = apr_pool_abort_get(vb->pool);
ap_assert(abort_fn != NULL);
abort_fn(APR_ENOMEM);
return;
}
new_info = (struct ap_varbuf_info *)new_node->first_avail;
new_node->first_avail += APR_ALIGN_DEFAULT(sizeof(*new_info));
new_info->node = new_node;
new_info->allocator = allocator;
new = new_node->first_avail;
AP_DEBUG_ASSERT(new_node->endp - new_node->first_avail >= new_len);
new_len = new_node->endp - new_node->first_avail;
if (vb->avail && vb->strlen != 0)
memcpy(new, vb->buf, vb->strlen == AP_VARBUF_UNKNOWN ?
vb->avail + 1 : vb->strlen + 1);
else
*new = '\0';
if (vb->info)
apr_pool_cleanup_run(vb->pool, vb->info, varbuf_cleanup);
apr_pool_cleanup_register(vb->pool, new_info, varbuf_cleanup,
apr_pool_cleanup_null);
vb->info = new_info;
vb->buf = new;
vb->avail = new_len - 1;
}
AP_DECLARE(void) ap_varbuf_strmemcat(struct ap_varbuf *vb, const char *str,
int len)
{
if (len == 0)
return;
if (!vb->avail) {
ap_varbuf_grow(vb, len);
memcpy(vb->buf, str, len);
vb->buf[len] = '\0';
vb->strlen = len;
return;
}
if (vb->strlen == AP_VARBUF_UNKNOWN)
vb->strlen = strlen(vb->buf);
ap_varbuf_grow(vb, vb->strlen + len);
memcpy(vb->buf + vb->strlen, str, len);
vb->strlen += len;
vb->buf[vb->strlen] = '\0';
}
AP_DECLARE(void) ap_varbuf_free(struct ap_varbuf *vb)
{
if (vb->info) {
apr_pool_cleanup_run(vb->pool, vb->info, varbuf_cleanup);
vb->info = NULL;
}
vb->buf = NULL;
}
AP_DECLARE(char *) ap_varbuf_pdup(apr_pool_t *p, struct ap_varbuf *buf,
const char *prepend, apr_size_t prepend_len,
const char *append, apr_size_t append_len,
apr_size_t *new_len)
{
apr_size_t i = 0;
struct iovec vec[3];
if (prepend) {
vec[i].iov_base = (void *)prepend;
vec[i].iov_len = prepend_len;
i++;
}
if (buf->avail && buf->strlen) {
if (buf->strlen == AP_VARBUF_UNKNOWN)
buf->strlen = strlen(buf->buf);
vec[i].iov_base = (void *)buf->buf;
vec[i].iov_len = buf->strlen;
i++;
}
if (append) {
vec[i].iov_base = (void *)append;
vec[i].iov_len = append_len;
i++;
}
if (i)
return apr_pstrcatv(p, vec, i, new_len);
if (new_len)
*new_len = 0;
return "";
}
AP_DECLARE(apr_status_t) ap_varbuf_regsub(struct ap_varbuf *vb,
const char *input,
const char *source,
apr_size_t nmatch,
ap_regmatch_t pmatch[],
apr_size_t maxlen)
{
return regsub_core(NULL, NULL, vb, input, source, nmatch, pmatch, maxlen);
}
static const char * const oom_message = "[crit] Memory allocation failed, "
"aborting process." APR_EOL_STR;
AP_DECLARE(void) ap_abort_on_oom()
{
int written, count = strlen(oom_message);
const char *buf = oom_message;
do {
written = write(STDERR_FILENO, buf, count);
if (written == count)
break;
if (written > 0) {
buf += written;
count -= written;
}
} while (written >= 0 || errno == EINTR);
abort();
}
AP_DECLARE(void *) ap_malloc(size_t size)
{
void *p = malloc(size);
if (p == NULL && size != 0)
ap_abort_on_oom();
return p;
}
AP_DECLARE(void *) ap_calloc(size_t nelem, size_t size)
{
void *p = calloc(nelem, size);
if (p == NULL && nelem != 0 && size != 0)
ap_abort_on_oom();
return p;
}
AP_DECLARE(void *) ap_realloc(void *ptr, size_t size)
{
void *p = realloc(ptr, size);
if (p == NULL && size != 0)
ap_abort_on_oom();
return p;
}