Esempio n. 1
0
static int
compare_right(char const *a, char const *b)
{
     int bias = 0;

     /* The longest run of digits wins.  That aside, the greatest
	value wins, but we can't know that it will until we've scanned
	both numbers to know that they have the same magnitude, so we
	remember it in BIAS. */
     for (;; a++, b++) {
	  if (!apr_isdigit(*a)  &&  !apr_isdigit(*b))
	       break;
	  else if (!apr_isdigit(*a))
	       return -1;
	  else if (!apr_isdigit(*b))
	       return +1;
	  else if (*a < *b) {
	       if (!bias)
		    bias = -1;
	  } else if (*a > *b) {
	       if (!bias)
		    bias = +1;
	  } else if (!*a  &&  !*b)
	       break;
     }

     return bias;
}
Esempio n. 2
0
apr_int32_t util_timestring_to_seconds(char *string)
{
	
	char *character;
	apr_int32_t number = 0;

	if (string == NULL)		
		return 0;

	character = string;
	
	/* calculate number */
	while (apr_isdigit(*character) || apr_isspace(*character)) {
		if (apr_isdigit(*character)) {
			/* translate to number */
			unsigned digit = (unsigned) *character - (unsigned) '0';
			ap_assert(digit < 10);
			number = (number * (apr_int32_t) 10) + (apr_int32_t) digit; 
		}
		character += 1;
	}
	
	if (*character != '\0') {
		switch(*character) {
			case 'w':
			case 'W':
				number = number * SECONDS_IN_WEEK;
				break;
			case 'd':
			case 'D':
				number = number * SECONDS_IN_DAY;
				break;
			case 'h':
			case 'H':
				number = number * SECONDS_IN_HOUR;
				break;
			case 'm':
			case 'M':
				number = number * SECONDS_IN_MINUTE;
				break;
			case 's':
			case 'S':
			default:
				/* this is only here for clarity */
				number = number;
				break;
		}
	}
	
	if (number > MAX_CACHE_TIMEOUT)
		number = MAX_CACHE_TIMEOUT;
	return number;
}
Esempio n. 3
0
static apr_status_t parse_network(apr_ipsubnet_t *ipsub, const char *network)
{
    /* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */
    int shift;
    char *s, *t;
    int octet;
    char buf[sizeof "255.255.255.255"];

    if (strlen(network) < sizeof buf) {
        strcpy(buf, network);
    }
    else {
        return APR_EBADIP;
    }

    /* parse components */
    s = buf;
    ipsub->sub[0] = 0;
    ipsub->mask[0] = 0;
    shift = 24;
    while (*s) {
        t = s;
        if (!apr_isdigit(*t)) {
            return APR_EBADIP;
        }
        while (apr_isdigit(*t)) {
            ++t;
        }
        if (*t == '.') {
            *t++ = 0;
        }
        else if (*t) {
            return APR_EBADIP;
        }
        if (shift < 0) {
            return APR_EBADIP;
        }
        octet = atoi(s);
        if (octet < 0 || octet > 255) {
            return APR_EBADIP;
        }
        ipsub->sub[0] |= octet << shift;
        ipsub->mask[0] |= 0xFFUL << shift;
        s = t;
        shift -= 8;
    }
    ipsub->sub[0] = ntohl(ipsub->sub[0]);
    ipsub->mask[0] = ntohl(ipsub->mask[0]);
    ipsub->family = AF_INET;
    return APR_SUCCESS;
}
Esempio n. 4
0
static int strnatcmp0(char const *a, char const *b, int fold_case)
{
     int ai, bi;
     char ca, cb;
     int fractional, result;
     ai = bi = 0;
     while (1) {
	  ca = a[ai]; cb = b[bi];

	  /* skip over leading spaces or zeros */
	  while (apr_isspace(ca))
	       ca = a[++ai];

	  while (apr_isspace(cb))
	       cb = b[++bi];

	  /* process run of digits */
	  if (apr_isdigit(ca)  &&  apr_isdigit(cb)) {
	       fractional = (ca == '0' || cb == '0');

	       if (fractional) {
		    if ((result = compare_left(a+ai, b+bi)) != 0)
			 return result;
	       } else {
		    if ((result = compare_right(a+ai, b+bi)) != 0)
			 return result;
	       }
	  }

	  if (!ca && !cb) {
	       /* The strings compare the same.  Perhaps the caller
                  will want to call strcmp to break the tie. */
	       return 0;
	  }

	  if (fold_case) {
	       ca = apr_toupper(ca);
	       cb = apr_toupper(cb);
	  }

	  if (ca < cb)
	       return -1;
	  else if (ca > cb)
	       return +1;

	  ++ai; ++bi;
     }
}
Esempio n. 5
0
/*
 * Strips all of the RE: junk from the subject line.
 */
static char *strip_subject(apr_pool_t *p, Message *m)
{
    char *newVal, *match = m->subject, *tmp = NULL;

    /* Match the following cases: Re:, RE:, RE[1]:, Re: Re[2]: Re: */
    while (match && *match) {
        /* When we don't have a match, tmp contains the "real" subject. */
        tmp = newVal = match;
        match = NULL;
        if (*newVal == 'R' && (*++newVal == 'e' || *newVal == 'E')) {
            /* Note to self.  In pure compressed syntax, the famous dangling
             * else occurs.  Oh, well. */
            if (*++newVal == '[') {
                while (apr_isdigit(*++newVal)) {
                }
                if (*++newVal == ']' && *++newVal == ':')
                    match = ++newVal;
            }
            else if (*newVal == ':')
                match = ++newVal;
        }

        if (match)
            while (apr_isspace(*match))
                match++;
    }

    return apr_pstrdup(p, tmp);
}
Esempio n. 6
0
int util_string_is_number(const char *the_string)
{
	while (*the_string != '\0')
		if (!apr_isdigit(*(the_string++)))
			return 0;
	return 1;
}
Esempio n. 7
0
static const char *configure_redirect(cmd_parms *cmd, void *d_, const char *arg1)
{
    dir_config_rec *d = d_;
    int status;

    if (!strcasecmp(arg1, "ON"))
        status = HTTP_MOVED_TEMPORARILY;
    else if (!strcasecmp(arg1, "OFF"))
        status = REDIRECT_OFF;
    else if (!strcasecmp(arg1, "permanent"))
        status = HTTP_MOVED_PERMANENTLY;
    else if (!strcasecmp(arg1, "temp"))
        status = HTTP_MOVED_TEMPORARILY;
    else if (!strcasecmp(arg1, "seeother"))
        status = HTTP_SEE_OTHER;
    else if (apr_isdigit(*arg1)) {
        status = atoi(arg1);
        if (!ap_is_HTTP_REDIRECT(status)) {
            return "DirectoryIndexRedirect only accepts values between 300 and 399";
        }
    }
    else {
        return "DirectoryIndexRedirect ON|OFF|permanent|temp|seeother|3xx";
    }

    d->redirect_index = status;
    return NULL;
}
Esempio n. 8
0
/*
 * Set the ports CONNECT can use
 */
static const char *
    set_allowed_ports(cmd_parms *parms, void *dummy, const char *arg)
{
    server_rec *s = parms->server;
    int first, last;
    connect_conf *conf =
        ap_get_module_config(s->module_config, &proxy_connect_module);
    port_range *New;
    char *endptr;
    const char *p = arg;

    if (!apr_isdigit(arg[0]))
        return "AllowCONNECT: port numbers must be numeric";

    first = strtol(p, &endptr, 10);
    if (*endptr == '-') {
        p = endptr + 1;
        last = strtol(p, &endptr, 10);
    }
    else {
        last = first;
    }

    if (endptr == p || *endptr != '\0')  {
        return apr_psprintf(parms->temp_pool,
                            "Cannot parse '%s' as port number", p);
    }

    New = apr_array_push(conf->allowed_connect_ports);
    New->first = first;
    New->last  = last;
    return NULL;
}
Esempio n. 9
0
static int
compare_left(char const *a, char const *b)
{
     /* Compare two left-aligned numbers: the first to have a
        different value wins. */
     for (;; a++, b++) {
	  if (!apr_isdigit(*a)  &&  !apr_isdigit(*b))
	       break;
	  else if (!apr_isdigit(*a))
	       return -1;
	  else if (!apr_isdigit(*b))
	       return +1;
	  else if (*a < *b)
	       return -1;
	  else if (*a > *b)
	       return +1;
     }

     return 0;
}
Esempio n. 10
0
static int looks_like_ip(const char *ipstr)
{
    if (strchr(ipstr, ':')) {
        /* definitely not a hostname; assume it is intended to be an IPv6 address */
        return 1;
    }

    /* simple IPv4 address string check */
    while ((*ipstr == '.') || apr_isdigit(*ipstr))
        ipstr++;
    return (*ipstr == '\0');
}
Esempio n. 11
0
/*
 * Converts apr_time_t expressed as hex digits to
 * a true apr_time_t.
 */
CACHE_DECLARE(apr_time_t) ap_cache_hex2usec(const char *x)
{
    int i, ch;
    apr_time_t j;
    for (i = 0, j = 0; i < sizeof(j) * 2; i++) {
        ch = x[i];
        j <<= 4;
        if (apr_isdigit(ch))
            j |= ch - '0';
        else if (apr_isupper(ch))
            j |= ch - ('A' - 10);
        else
            j |= ch - ('a' - 10);
    }
    return j;
}
Esempio n. 12
0
AP_DECLARE(apr_status_t) ap_read_pid(apr_pool_t *p, const char *filename,
                                     pid_t *mypid)
{
    const apr_size_t BUFFER_SIZE = sizeof(long) * 3 + 2; /* see apr_ltoa */
    apr_file_t *pid_file = NULL;
    apr_status_t rv;
    const char *fname;
    char *buf, *endptr;
    apr_size_t bytes_read;

    if (!filename) {
        return APR_EGENERAL;
    }

    fname = ap_server_root_relative(p, filename);
    if (!fname) {
        ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, APR_EBADPATH,
                     NULL, "Invalid PID file path %s, ignoring.", filename);
        return APR_EGENERAL;
    }

    rv = apr_file_open(&pid_file, fname, APR_READ, APR_OS_DEFAULT, p);
    if (rv != APR_SUCCESS) {
        return rv;
    }

    buf = apr_palloc(p, BUFFER_SIZE);

    rv = apr_file_read_full(pid_file, buf, BUFFER_SIZE - 1, &bytes_read);
    if (rv != APR_SUCCESS && rv != APR_EOF) {
        return rv;
    }

    /* If we fill the buffer, we're probably reading a corrupt pid file.
     * To be nice, let's also ensure the first char is a digit. */
    if (bytes_read == 0 || bytes_read == BUFFER_SIZE - 1 || !apr_isdigit(*buf)) {
        return APR_EGENERAL;
    }

    buf[bytes_read] = '\0';
    *mypid = strtol(buf, &endptr, 10);

    apr_file_close(pid_file);
    return APR_SUCCESS;
}
Esempio n. 13
0
/*
 * Converts 8 hex digits to a timestamp
 */
static unsigned int auth_token_hex2sec(const char *x)
{
	int i, ch;
	unsigned int j;

	for (i = 0, j = 0; i < 8; i++) {
		ch = x[i];
		j <<= 4;

		if (apr_isdigit(ch))
			j |= ch - '0';
		else if (apr_isupper(ch))
			j |= ch - ('A' - 10);
		else
			j |= ch - ('a' - 10);
	}

	return j;
}
Esempio n. 14
0
/*
 * Determines if a string is a reply
 */
static int is_reply_string(char *c)
{
    /* Match the following cases: Re:, RE:, RE[1]:, Re: Re[2]: Re: */
    if (c) {
        if ((c[0] == 'R') && (c[1] == 'E' || c[1] == 'e')) {
            if (c[2] == ':')
                return 1;
            else if (c[2] == '[') {
                c = c + 3;

                while (apr_isdigit(*c))
                    c++;

                if (*c == ']')
                    return 1;
            }
        }
    }
    return 0;
}
Esempio n. 15
0
File: at.c Progetto: LuaDist/apreq
static int* at_list(apr_pool_t *pool, const char *spec, int *list)
{
    apr_array_header_t arr;
    int prev, current = 0;

    arr.pool = pool;
    arr.elt_size = sizeof *list;
    arr.nelts = 0;
    arr.nalloc = AT_NELTS;
    arr.elts = (char *)list;

    do {
        while (*spec && !apr_isdigit(*spec))
            ++spec;

        prev = current;
        current = (int)apr_strtoi64(spec, (char **)(void *)&spec, 10);
        *(int *)apr_array_push(&arr) = current;

    } while (prev >= current);

    return (int *)arr.elts;
}
Esempio n. 16
0
AP_DECLARE(char **) ap_create_environment(apr_pool_t *p, apr_table_t *t)
{
    const apr_array_header_t *env_arr = apr_table_elts(t);
    const apr_table_entry_t *elts = (const apr_table_entry_t *) env_arr->elts;
    char **env = (char **) apr_palloc(p, (env_arr->nelts + 2) * sizeof(char *));
    int i, j;
    char *tz;
    char *whack;

    j = 0;
    if (!apr_table_get(t, "TZ")) {
        tz = getenv("TZ");
        if (tz != NULL) {
            env[j++] = apr_pstrcat(p, "TZ=", tz, NULL);
        }
    }
    for (i = 0; i < env_arr->nelts; ++i) {
        if (!elts[i].key) {
            continue;
        }
        env[j] = apr_pstrcat(p, elts[i].key, "=", elts[i].val, NULL);
        whack = env[j];
        if (apr_isdigit(*whack)) {
            *whack++ = '_';
        }
        while (*whack != '=') {
            if (!apr_isalnum(*whack) && *whack != '_') {
                *whack = '_';
            }
            ++whack;
        }
        ++j;
    }

    env[j] = NULL;
    return env;
}
Esempio n. 17
0
static const char *parse_syslog_priority(const char *string,
					 nx_logdata_t *logdata,
					 boolean *retval)
{
    const char *ptr = string;
    int priority = -1;
    nx_syslog_facility_t fac = NX_SYSLOG_FACILITY_USER;
    nx_syslog_severity_t sev = NX_SYSLOG_SEVERITY_NOTICE;

    nx_value_t *facility = NULL;
    nx_value_t *severity = NULL;
    nx_loglevel_t loglevel = NX_LOGLEVEL_INFO;

    ASSERT(string != NULL);

    // parse priority
    if ( *ptr == '<' )
    {
	ptr++;
	priority = 0;
	while ( apr_isdigit(*ptr) )
	{
	    if ( ptr - string > 6 )
	    {
		*retval = FALSE;
		ptr = string;
		goto badpri;
	    }
	    priority = priority * 10 + (*ptr - '0');
	    ptr++;
	}
	if ( *ptr != '>' )
	{
	    priority = -1;
	}
	else
	{
	    ptr++;
	    if ( *ptr == ' ' )
	    {
		ptr++;
	    }
	}
    }
    else
    {
	*retval = FALSE;
	goto badpri;
    }

    if ( priority != -1 )
    {
	fac = (priority >> 3);
	if ( fac > NX_SYSLOG_FACILITY_LOCAL7 )
	{
	    fac = NX_SYSLOG_FACILITY_USER;
	    goto badpri;
	}
	sev = priority & 0x07;
	if ( sev > NX_SYSLOG_SEVERITY_NOPRI )
	{
	    sev = NX_SYSLOG_SEVERITY_NOTICE;
	    goto badpri;
	}
    }
Esempio n. 18
0
static const char *set_cookie_exp(cmd_parms *parms, void *dummy,
                                  const char *arg)
{
    cookie_log_state *cls;
    time_t factor, modifier = 0;
    time_t num = 0;
    char *word;

    cls  = ap_get_module_config(parms->server->module_config,
                                &usertrack_module);
    /* The simple case first - all numbers (we assume) */
    if (apr_isdigit(arg[0]) && apr_isdigit(arg[strlen(arg) - 1])) {
        cls->expires = atol(arg);
        return NULL;
    }

    /*
     * The harder case - stolen from mod_expires
     *
     * CookieExpires "[plus] {<num> <type>}*"
     */

    word = ap_getword_conf(parms->temp_pool, &arg);
    if (!strncasecmp(word, "plus", 1)) {
        word = ap_getword_conf(parms->temp_pool, &arg);
    };

    /* {<num> <type>}* */
    while (word[0]) {
        /* <num> */
        if (apr_isdigit(word[0]))
            num = atoi(word);
        else
            return "bad expires code, numeric value expected.";

        /* <type> */
        word = ap_getword_conf(parms->temp_pool, &arg);
        if (!word[0])
            return "bad expires code, missing <type>";

        if (!strncasecmp(word, "years", 1))
            factor = 60 * 60 * 24 * 365;
        else if (!strncasecmp(word, "months", 2))
            factor = 60 * 60 * 24 * 30;
        else if (!strncasecmp(word, "weeks", 1))
            factor = 60 * 60 * 24 * 7;
        else if (!strncasecmp(word, "days", 1))
            factor = 60 * 60 * 24;
        else if (!strncasecmp(word, "hours", 1))
            factor = 60 * 60;
        else if (!strncasecmp(word, "minutes", 2))
            factor = 60;
        else if (!strncasecmp(word, "seconds", 1))
            factor = 1;
        else
            return "bad expires code, unrecognized type";

        modifier = modifier + factor * num;

        /* next <num> */
        word = ap_getword_conf(parms->temp_pool, &arg);
    }

    cls->expires = modifier;

    return NULL;
}
Esempio n. 19
0
/*
 * Do format conversion placing the output in buffer
 * 本函数没有调用任何外部函数,所以它是自包含的
 */
APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *),
    apr_vformatter_buff_t *vbuff, const char *fmt, va_list ap)
{
    register char *sp;
    register char *bep;
    register int cc = 0;
    register apr_size_t i;

    register char *s = NULL;
    char *q;
    apr_size_t s_len = 0;

    register apr_size_t min_width = 0;
    apr_size_t precision = 0;
    enum {
        LEFT, RIGHT
    } adjust;
    char pad_char;
    char prefix_char;

    double fp_num;
    apr_int64_t i_quad = 0;
    apr_uint64_t ui_quad;
    apr_int32_t i_num = 0;
    apr_uint32_t ui_num = 0;

    char num_buf[NUM_BUF_SIZE];
    char char_buf[2];                /* for printing %% and %<unknown> */

    enum var_type_enum {
            IS_QUAD, IS_LONG, IS_SHORT, IS_INT
    };
    enum var_type_enum var_type = IS_INT;

    /*
     * Flag variables
     */
    boolean_e alternate_form;
    boolean_e print_sign;
    boolean_e print_blank;
    boolean_e adjust_precision;
    boolean_e adjust_width;
    int is_negative;

    sp = vbuff->curpos;
    bep = vbuff->endpos;

    while (*fmt) {
        if (*fmt != '%') {
            INS_CHAR(*fmt, sp, bep, cc);
        }
        else {
            /*
             * Default variable settings
             */
            boolean_e print_something = YES;
            adjust = RIGHT;
            alternate_form = print_sign = print_blank = NO;
            pad_char = ' ';
            prefix_char = NUL;

            fmt++;

            /*
             * Try to avoid checking for flags, width or precision
             */
            if (!apr_islower(*fmt)) {
                /*
                 * Recognize flags: -, #, BLANK, +
                 */
                for (;; fmt++) {
                    if (*fmt == '-')
                        adjust = LEFT;
                    else if (*fmt == '+')
                        print_sign = YES;
                    else if (*fmt == '#')
                        alternate_form = YES;
                    else if (*fmt == ' ')
                        print_blank = YES;
                    else if (*fmt == '0')
                        pad_char = '0';
                    else
                        break;
                }

                /*
                 * Check if a width was specified
                 */
                if (apr_isdigit(*fmt)) {
                    STR_TO_DEC(fmt, min_width);
                    adjust_width = YES;
                }
                else if (*fmt == '*') {
                    int v = va_arg(ap, int);
                    fmt++;
                    adjust_width = YES;
                    if (v < 0) {
                        adjust = LEFT;
                        min_width = (apr_size_t)(-v);
                    }
                    else
                        min_width = (apr_size_t)v;
                }
                else
                    adjust_width = NO;

                /*
                 * Check if a precision was specified
                 */
                if (*fmt == '.') {
                    adjust_precision = YES;
                    fmt++;
                    if (apr_isdigit(*fmt)) {
                        STR_TO_DEC(fmt, precision);
                    }
                    else if (*fmt == '*') {
                        int v = va_arg(ap, int);
                        fmt++;
                        precision = (v < 0) ? 0 : (apr_size_t)v;
                    }
                    else
/* Set the value of a config variabe, strings only */
static const char *set_config_value(cmd_parms *cmd, void *mconfig,
                                    const char *value)
{
    settings_rec *cfg;

    cfg = (settings_rec *) mconfig;

    char name[50];
    sprintf( name, "%s", cmd->cmd->name );

    /*
     * Apply restrictions on attributes.
     */
    if( strlen(value) == 0 ) {
        return apr_psprintf(cmd->pool, "%s not allowed to be NULL", name);
    }

    /* Domain to set the cookie in */
    if( strcasecmp(name, "QS2CookieDomain") == 0 ) {

        if( value[0] != '.' ) {
            return "QS2CookieDomain values must begin with a dot";
        }

        if( ap_strchr_c( &value[1], '.' ) == NULL ) {
            return "QS2CookieDomain values must contain at least one embedded dot";
        }

        // immediately format it for the cookie value, as that's the only
        // place we'll be using it.
        cfg->cookie_domain =
            apr_pstrcat( cmd->pool, "domain=", value, "; ", NULL );

    /* Prefix for all keys set in the cookie */
    } else if( strcasecmp(name, "QS2CookiePrefix") == 0 ) {
        cfg->cookie_prefix     = apr_pstrdup(cmd->pool, value);

    /* Use this query string argument for the cookie name */
    } else if( strcasecmp(name, "QS2CookieName") == 0 ) {
        cfg->cookie_name       = apr_pstrdup(cmd->pool, value);

    /* Use this query string argument for the cookie name */
    } else if( strcasecmp(name, "QS2CookieNameFrom") == 0 ) {
        cfg->cookie_name_from  = apr_pstrdup(cmd->pool, value);

    /* Use this delimiter for pairs of key/values */
    } else if( strcasecmp(name, "QS2CookiePairDelimiter") == 0 ) {

        if( strcspn( value, "=" ) == 0 ) {
            return apr_psprintf(cmd->pool,
                "Variable %s may not be '=' -- illegal in cookie values", name);
        }

        cfg->cookie_pair_delimiter  = apr_pstrdup(cmd->pool, value);

    /* Use this delimiter between a key and a value */
    } else if( strcasecmp(name, "QS2CookieKeyValueDelimiter") == 0 ) {

        if( strcspn( value, "=" ) == 0 ) {
            return apr_psprintf(cmd->pool,
                "Variable %s may not be '=' -- illegal in cookie values", name);
        }

        cfg->cookie_key_value_delimiter  = apr_pstrdup(cmd->pool, value);

    /* Maximum size of all the key/value pairs */
    } else if( strcasecmp(name, "QS2CookieMaxSize") == 0 ) {

        // this has to be a number
        if( apr_isdigit(*value) && apr_isdigit(value[strlen(value) - 1]) ) {
            cfg->cookie_max_size   = atol(apr_pstrdup(cmd->pool, value));
        } else {
            return apr_psprintf(cmd->pool,
                "Variable %s must be a number, not %s", name, value);
        }

    /* Expiry time, in seconds after the request */
    } else if( strcasecmp(name, "QS2CookieExpires") == 0 ) {

        // this has to be a number
        if( apr_isdigit(*value) && apr_isdigit(value[strlen(value) - 1]) ) {
            cfg->cookie_expires = atol(apr_pstrdup(cmd->pool, value));
        } else {
            return apr_psprintf(cmd->pool,
                "Variable %s must be a number, not %s", name, value);
        }

    /* all the keys that will not be put into the cookie */
    } else if( strcasecmp(name, "QS2CookieIgnore") == 0 ) {

        // following tutorial here:
        // http://dev.ariel-networks.com/apr/apr-tutorial/html/apr-tutorial-19.html
        const char *str                                = apr_pstrdup(cmd->pool, value);
        *(const char**)apr_array_push(cfg->qs_ignore) = str;

        _DEBUG && fprintf( stderr, "qs ignore = %s\n", str );

        char *ary = apr_array_pstrcat( cmd->pool, cfg->qs_ignore, '-' );
        _DEBUG && fprintf( stderr, "qs ignore as str = %s\n", ary );

    } else {
        return apr_psprintf(cmd->pool, "No such variable %s", name);
    }

    return NULL;
}
Esempio n. 21
0
File: misc.c Progetto: ATCP/mtcp
apr_status_t apr_get_oslevel(apr_oslevel_e *level)
{
    if (apr_os_level == APR_WIN_UNK) 
    {
        static OSVERSIONINFO oslev;
        oslev.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
        GetVersionEx(&oslev);

        if (oslev.dwPlatformId == VER_PLATFORM_WIN32_NT) 
        {
            static unsigned int servpack = 0;
            TCHAR *pservpack;
            if ((pservpack = oslev.szCSDVersion)) {
                while (*pservpack && !apr_isdigit(*pservpack)) {
                    pservpack++;
                }
                if (*pservpack)
#ifdef _UNICODE
                    servpack = _wtoi(pservpack);
#else
                    servpack = atoi(pservpack);
#endif
            }

            if (oslev.dwMajorVersion < 3) {
                apr_os_level = APR_WIN_UNSUP;
            }
            else if (oslev.dwMajorVersion == 3) {
                if (oslev.dwMajorVersion < 50) {
                    apr_os_level = APR_WIN_UNSUP;
                }
                else if (oslev.dwMajorVersion == 50) {
                    apr_os_level = APR_WIN_NT_3_5;
                }
                else {
                    apr_os_level = APR_WIN_NT_3_51;
                }
            }
            else if (oslev.dwMajorVersion == 4) {
                if (servpack < 2)
                    apr_os_level = APR_WIN_NT_4;
                else if (servpack <= 2)
                    apr_os_level = APR_WIN_NT_4_SP2;
                else if (servpack <= 3)
                    apr_os_level = APR_WIN_NT_4_SP3;
                else if (servpack <= 4)
                    apr_os_level = APR_WIN_NT_4_SP4;
                else if (servpack <= 5)
                    apr_os_level = APR_WIN_NT_4_SP5;
                else 
                    apr_os_level = APR_WIN_NT_4_SP6;
            }
            else if (oslev.dwMajorVersion == 5) {
                if (oslev.dwMinorVersion == 0) {
                    if (servpack == 0)
                        apr_os_level = APR_WIN_2000;
                    else if (servpack == 1)
                        apr_os_level = APR_WIN_2000_SP1;
                    else
                        apr_os_level = APR_WIN_2000_SP2;
                }
                else if (oslev.dwMinorVersion == 2) {
                    apr_os_level = APR_WIN_2003;
                }
                else {
                    if (servpack < 1)
                        apr_os_level = APR_WIN_XP;
                    else if (servpack == 1)
                        apr_os_level = APR_WIN_XP_SP1;
                    else
                        apr_os_level = APR_WIN_XP_SP2;
                }
            }
            else if (oslev.dwMajorVersion == 6) {
                apr_os_level = APR_WIN_VISTA;
            }
            else {
                apr_os_level = APR_WIN_XP;
            }
        }
#ifndef WINNT
        else if (oslev.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
            TCHAR *prevision;
            if (prevision = oslev.szCSDVersion) {
                while (*prevision && !apr_isupper(*prevision)) {
                     prevision++;
                }
            }
            else prevision = _T("");

            if (oslev.dwMinorVersion < 10) {
                if (*prevision < _T('C'))
                    apr_os_level = APR_WIN_95;
                else
                    apr_os_level = APR_WIN_95_OSR2;
            }
            else if (oslev.dwMinorVersion < 90) {
                if (*prevision < _T('A'))
                    apr_os_level = APR_WIN_98;
                else
                    apr_os_level = APR_WIN_98_SE;
            }
            else {
                apr_os_level = APR_WIN_ME;
            }
        }
#endif
#ifdef _WIN32_WCE
        else if (oslev.dwPlatformId == VER_PLATFORM_WIN32_CE) 
        {
            if (oslev.dwMajorVersion < 3) {
                apr_os_level = APR_WIN_UNSUP;
            }
            else {
                apr_os_level = APR_WIN_CE_3;
            }
        }
#endif
        else {
            apr_os_level = APR_WIN_UNSUP;
        }
    }

    *level = apr_os_level;

    if (apr_os_level < APR_WIN_UNSUP) {
        return APR_EGENERAL;
    }

    return APR_SUCCESS;
}
Esempio n. 22
0
static const char *vhost_alias_set(cmd_parms *cmd, void *dummy, const char *map)
{
    mva_sconf_t *conf;
    mva_mode_e mode, *pmode;
    const char **pmap;
    const char *p;
  
    conf = (mva_sconf_t *) ap_get_module_config(cmd->server->module_config,
						&vhost_alias_module);
    /* there ought to be a better way of doing this */
    if (&vhost_alias_set_doc_root_ip == cmd->info) {
	mode = VHOST_ALIAS_IP;
	pmap = &conf->doc_root;
	pmode = &conf->doc_root_mode;
    }
    else if (&vhost_alias_set_cgi_root_ip == cmd->info) {
	mode = VHOST_ALIAS_IP;
	pmap = &conf->cgi_root;
	pmode = &conf->cgi_root_mode;
    }
    else if (&vhost_alias_set_doc_root_name == cmd->info) {
	mode = VHOST_ALIAS_NAME;
	pmap = &conf->doc_root;
	pmode = &conf->doc_root_mode;
    }
    else if (&vhost_alias_set_cgi_root_name == cmd->info) {
	mode = VHOST_ALIAS_NAME;
	pmap = &conf->cgi_root;
	pmode = &conf->cgi_root_mode;
    }
    else {
	return "INTERNAL ERROR: unknown command info";
    }

    if (!ap_os_is_path_absolute(cmd->pool, map)) {
	if (strcasecmp(map, "none")) {
	    return "format string must be an absolute path, or 'none'";
	}
	*pmap = NULL;
	*pmode = VHOST_ALIAS_NONE;
	return NULL;
    }

    /* sanity check */
    p = map;
    while (*p != '\0') {
	if (*p++ != '%') {
	    continue;
	}
	/* we just found a '%' */
	if (*p == 'p' || *p == '%') {
	    ++p;
	    continue;
	}
	/* optional dash */
	if (*p == '-') {
	    ++p;
	}
	/* digit N */
	if (apr_isdigit(*p)) {
	    ++p;
	}
	else {
	    return "syntax error in format string";
	}
	/* optional plus */
	if (*p == '+') {
	    ++p;
	}
	/* do we end here? */
	if (*p != '.') {
	    continue;
	}
	++p;
	/* optional dash */
	if (*p == '-') {
	    ++p;
	}
	/* digit M */
	if (apr_isdigit(*p)) {
	    ++p;
	}
	else {
	    return "syntax error in format string";
	}
	/* optional plus */
	if (*p == '+') {
	    ++p;
	}
    }
    *pmap = map;
    *pmode = mode;
    return NULL;
}
static int check_unix_group(request_rec *r, const char *grouplist)
{
    char **p;
    struct group *grp;
    char *user= r->user;
    char *w, *at;

    /* Strip @ sign and anything following it from the username.  Some
     * authentication modules, like mod_auth_kerb like appending such
     * stuff to user names, but an @ sign is never legal in a unix login
     * name, so it should be safe to always discard such stuff.
     */
    if ((at= strchr(user, '@')) != NULL) *at= '\0';

    /* Get info about login */
    struct passwd *pwd= getpwnam(user);
    if (pwd == NULL)
    {
        /* No such user - forget it */
        if (at != NULL) *at= '@';
        return 0;
    }

    /* Loop through list of groups passed in */
    while (*grouplist != '\0')
    {
        w= ap_getword_conf(r->pool, &grouplist);
        if (apr_isdigit(w[0]))
        {
            /* Numeric group id */
            int gid= atoi(w);

            /* Check if it matches the user's primary group */
            if (gid == pwd->pw_gid)
            {
                if (at != NULL) *at= '@';
                return 1;
            }

            /* Get list of group members for numeric group id */
            grp= getgrgid(gid);
        }
        else
        {
            /* Get gid and list of group members for group name */
            grp= getgrnam(w);
            /* Check if gid of this group matches user's primary gid */
            if (grp != NULL && grp->gr_gid == pwd->pw_gid)
            {
                if (at != NULL) *at= '@';
                return 1;
            }
        }

        /* Walk through list of members, seeing if any match user login */
        if (grp != NULL)
            for (p= grp->gr_mem; *p != NULL; p++)
            {
                if (!strcmp(user, *p))
                {
                    if (at != NULL) *at= '@';
                    return 1;
                }
            }
    }

    /* Didn't find any matches, flunk him */
    if (at != NULL) *at= '@';
    return 0;
}
Esempio n. 24
0
/*
 * compare the supplied version with the core one
 */
static int compare_version(char *version_string, const char **error)
{
    char *p = version_string, *ep;
    int version[3] = {0, 0, 0};
    int c = 0;

    *error = "Version appears to be invalid. It must have the format "
             "major[.minor[.patch]] where major, minor and patch are "
             "numbers.";

    if (!apr_isdigit(*p)) {
        return 0;
    }

    /* parse supplied version */
    ep = version_string + strlen(version_string);
    while (p <= ep && c < 3) {
        if (*p == '.') {
            *p = '\0';
        }

        if (!*p) {
            version[c++] = atoi(version_string);
            version_string = ++p;
            continue;
        }

        if (!apr_isdigit(*p)) {
            break;
        }

        ++p;
    }

    if (p < ep) { /* syntax error */
        return 0;
    }

    *error = NULL;

    if      (httpd_version.major > version[0]) {
        return 1;
    }
    else if (httpd_version.major < version[0]) {
        return -1;
    }
    else if (httpd_version.minor > version[1]) {
        return 1;
    }
    else if (httpd_version.minor < version[1]) {
        return -1;
    }
    else if (httpd_version.patch > version[2]) {
        return 1;
    }
    else if (httpd_version.patch < version[2]) {
        return -1;
    }

    /* seems to be the same */
    return 0;
}
Esempio n. 25
0
APR_DECLARE(apr_status_t) apr_parse_addr_port(char **addr,
                                              char **scope_id,
                                              apr_port_t *port,
                                              const char *str,
                                              apr_pool_t *p)
{
    const char *ch, *lastchar;
    int big_port;
    apr_size_t addrlen;

    *addr = NULL;         /* assume not specified */
    *scope_id = NULL;     /* assume not specified */
    *port = 0;            /* assume not specified */

    /* First handle the optional port number.  That may be all that
     * is specified in the string.
     */
    ch = lastchar = str + strlen(str) - 1;
    while (ch >= str && apr_isdigit(*ch)) {
        --ch;
    }

    if (ch < str) {       /* Entire string is the port. */
        big_port = atoi(str);
        if (big_port < 1 || big_port > 65535) {
            return APR_EINVAL;
        }
        *port = big_port;
        return APR_SUCCESS;
    }

    if (*ch == ':' && ch < lastchar) { /* host and port number specified */
        if (ch == str) {               /* string starts with ':' -- bad */
            return APR_EINVAL;
        }
        big_port = atoi(ch + 1);
        if (big_port < 1 || big_port > 65535) {
            return APR_EINVAL;
        }
        *port = big_port;
        lastchar = ch - 1;
    }

    /* now handle the hostname */
    addrlen = lastchar - str + 1;

/* XXX we don't really have to require APR_HAVE_IPV6 for this; 
 * just pass char[] for ipaddr (so we don't depend on struct in6_addr)
 * and always define APR_INET6 
 */
#if APR_HAVE_IPV6
    if (*str == '[') {
        const char *end_bracket = memchr(str, ']', addrlen);
        struct in6_addr ipaddr;
        const char *scope_delim;

        if (!end_bracket || end_bracket != lastchar) {
            *port = 0;
            return APR_EINVAL;
        }

        /* handle scope id; this is the only context where it is allowed */
        scope_delim = memchr(str, '%', addrlen);
        if (scope_delim) {
            if (scope_delim == end_bracket - 1) { /* '%' without scope id */
                *port = 0;
                return APR_EINVAL;
            }
            addrlen = scope_delim - str - 1;
            *scope_id = apr_palloc(p, end_bracket - scope_delim);
            memcpy(*scope_id, scope_delim + 1, end_bracket - scope_delim - 1);
            (*scope_id)[end_bracket - scope_delim - 1] = '\0';
        }
        else {
            addrlen = addrlen - 2; /* minus 2 for '[' and ']' */
        }

        *addr = apr_palloc(p, addrlen + 1);
        memcpy(*addr,
               str + 1,
               addrlen);
        (*addr)[addrlen] = '\0';
        if (apr_inet_pton(AF_INET6, *addr, &ipaddr) != 1) {
            *addr = NULL;
            *scope_id = NULL;
            *port = 0;
            return APR_EINVAL;
        }
    }
    else 
#endif
    {
        /* XXX If '%' is not a valid char in a DNS name, we *could* check 
         *     for bogus scope ids first.
         */
        *addr = apr_palloc(p, addrlen + 1);
        memcpy(*addr, str, addrlen);
        (*addr)[addrlen] = '\0';
    }
    return APR_SUCCESS;
}
Esempio n. 26
0
static char *parse_log_item(apr_pool_t *p, log_format_item *it, const char **sa)
{
    const char *s = *sa;
    ap_log_handler *handler;

    if (*s != '%') {
        return parse_log_misc_string(p, it, sa);
    }

    ++s;
    it->condition_sense = 0;
    it->conditions = NULL;

    if (*s == '%') {
        it->arg = "%";
        it->func = constant_item;
        *sa = ++s;

        return NULL;
    }

    it->want_orig = -1;
    it->arg = "";               /* For safety's sake... */

    while (*s) {
        int i;

        switch (*s) {
        case '!':
            ++s;
            it->condition_sense = !it->condition_sense;
            break;

        case '<':
            ++s;
            it->want_orig = 1;
            break;

        case '>':
            ++s;
            it->want_orig = 0;
            break;

        case ',':
            ++s;
            break;

        case '{':
            ++s;
            it->arg = ap_getword(p, &s, '}');
            break;

        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
            i = *s - '0';
            while (apr_isdigit(*++s)) {
                i = i * 10 + (*s) - '0';
            }
            if (!it->conditions) {
                it->conditions = apr_array_make(p, 4, sizeof(int));
            }
            *(int *) apr_array_push(it->conditions) = i;
            break;

        default:
            handler = (ap_log_handler *)apr_hash_get(log_hash, s++, 1);
            if (!handler) {
                char dummy[2];

                dummy[0] = s[-1];
                dummy[1] = '\0';
                return apr_pstrcat(p, "Unrecognized LogFormat directive %",
                               dummy, NULL);
            }
            it->func = handler->func;
            if (it->want_orig == -1) {
                it->want_orig = handler->want_orig_default;
            }
            *sa = s;
            return NULL;
        }
    }

    return "Ran off end of LogFormat parsing args to some directive";
}
static const char *set_cookie_exp(cmd_parms *parms, void *mconfig,
                                  const char *arg)
{
    //cookie_log_state *cls;
    time_t factor, modifier = 0;
    time_t num = 0;
    char *word;

    cookietrack_settings_rec *dcfg = mconfig;

    /* The simple case first - all numbers (we assume) */
    if (apr_isdigit(arg[0]) && apr_isdigit(arg[strlen(arg) - 1])) {
        dcfg->expires = atol(arg);
        return NULL;
    }

    /*
     * The harder case - stolen from mod_expires
     *
     * CookieExpires "[plus] {<num> <type>}*"
     */

    word = ap_getword_conf(parms->pool, &arg);
    if (!strncasecmp(word, "plus", 1)) {
        word = ap_getword_conf(parms->pool, &arg);
    };

    /* {<num> <type>}* */
    while (word[0]) {
        /* <num> */
        if (apr_isdigit(word[0])) {
            num = atoi(word);
        } else {
            return "bad expires code, numeric value expected.";
        }

        /* <type> */
        word = ap_getword_conf(parms->pool, &arg);
        if (!word[0]) { return "bad expires code, missing <type>"; }

        factor = 0;
        if (!strncasecmp(word, "years", 1)) {
            factor = 60 * 60 * 24 * 365;
        } else if (!strncasecmp(word, "months", 2)) {
            factor = 60 * 60 * 24 * 30;
        } else if (!strncasecmp(word, "weeks", 1)) {
            factor = 60 * 60 * 24 * 7;
        } else if (!strncasecmp(word, "days", 1)) {
            factor = 60 * 60 * 24;
        } else if (!strncasecmp(word, "hours", 1)) {
            factor = 60 * 60;
        } else if (!strncasecmp(word, "minutes", 2)) {
            factor = 60;
        } else if (!strncasecmp(word, "seconds", 1)) {
            factor = 1;
        } else {
            return "bad expires code, unrecognized type";
        }

        modifier = modifier + factor * num;

        /* next <num> */
        word = ap_getword_conf(parms->pool, &arg);
    }

    dcfg->expires = modifier;

    return NULL;
}
Esempio n. 28
0
static apr_status_t apreq_cookie_attr(apr_pool_t *p,
                                      apreq_cookie_t *c,
                                      const char *attr,
                                      apr_size_t alen,
                                      const char *val,
                                      apr_size_t vlen)
{
    if (alen < 2)
        return APR_EBADARG;

    if ( attr[0] ==  '-' || attr[0] == '$' ) {
        ++attr;
        --alen;
    }

    switch (apr_tolower(*attr)) {

    case 'n': /* name is not an attr */
        return APR_ENOTIMPL;

    case 'v': /* version; value is not an attr */
        if (alen == 5 && strncasecmp(attr,"value", 5) == 0)
            return APR_ENOTIMPL;

        while (!apr_isdigit(*val)) {
            if (vlen == 0)
                return APREQ_ERROR_BADSEQ;
            ++val;
            --vlen;
        }
        apreq_cookie_version_set(c, *val - '0');
        return APR_SUCCESS;

    case 'e': case 'm': /* expires, max-age */
        apreq_cookie_expires(c, val);
        return APR_SUCCESS;

    case 'd':
        c->domain = apr_pstrmemdup(p,val,vlen);
        return APR_SUCCESS;

    case 'p':
        if (alen != 4)
            break;
        if (!strncasecmp("port", attr, 4)) {
            c->port = apr_pstrmemdup(p,val,vlen);
            return APR_SUCCESS;
        }
        else if (!strncasecmp("path", attr, 4)) {
            c->path = apr_pstrmemdup(p,val,vlen);
            return APR_SUCCESS;
        }
        break;

    case 'c':
        if (!strncasecmp("commentURL", attr, 10)) {
            c->commentURL = apr_pstrmemdup(p,val,vlen);
            return APR_SUCCESS;
        }
        else if (!strncasecmp("comment", attr, 7)) {
            c->comment = apr_pstrmemdup(p,val,vlen);
            return APR_SUCCESS;
        }
        break;

    case 's':
        if (vlen > 0 && *val != '0' && strncasecmp("off",val,vlen))
            apreq_cookie_secure_on(c);
        else
            apreq_cookie_secure_off(c);
        return APR_SUCCESS;

    case 'h': /* httponly */
        if (vlen > 0 && *val != '0' && strncasecmp("off",val,vlen))
            apreq_cookie_httponly_on(c);
        else
            apreq_cookie_httponly_off(c);
        return APR_SUCCESS;

    };

    return APR_ENOTIMPL;
}
static int check_unix_group(request_rec *r, const char *grouplist)
{
    char *user= r->user;
    char *at;

    /* Strip @ sign and anything following it from the username.  Some
     * authentication modules, like mod_auth_kerb like appending such
     * stuff to user names, but an @ sign is never legal in a unix login
     * name, so it should be safe to always discard such stuff.
     */
    if ((at= strchr(user, '@')) != NULL) *at= '\0';

    /* Get info about login */
    struct passwd *pwd= getpwnam(user);
    if (pwd == NULL)
    {
        /* No such user - forget it */
        if (at != NULL) *at= '@';
        return 0;
    }

#ifdef HAVE_GETGROUPLIST
    int num_groups = 0;
    int grouplistresult = getgrouplist(user, pwd->pw_gid, NULL, &num_groups);
    if (grouplistresult != -1)
    {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
            "expected -1 from first getgrouplist, got %d", grouplistresult);
    }
    gid_t* user_groups = (gid_t*)apr_palloc(r->pool, num_groups*sizeof(gid_t));
    grouplistresult = getgrouplist(user, pwd->pw_gid, user_groups, &num_groups);
    /* Loop through list of groups passed in */
    while (*grouplist != '\0')
    {
        const char* const word = ap_getword_white(r->pool, &grouplist);
        gid_t match_group;
        if (apr_isdigit(word[0]))
        {
            // numeric group id 
            match_group = atoi(word);
        }
        else
        {
            struct group* const group = getgrnam(word);
            match_group = group == NULL ? -1 : group->gr_gid;
        }
        for (int i = 0; i < num_groups; i++)
        {
            gid_t const user_group = user_groups[i];
            if (user_group == match_group)
            {
                if (at != NULL) *at= '@';
                return 1;
            }
        }
    }
#else
    /* Loop through list of groups passed in */
    while (*grouplist != '\0')
    {
        struct group *grp;
        char* w= ap_getword_white(r->pool, &grouplist);
        if (apr_isdigit(w[0]))
        {
            /* Numeric group id */
            int gid= atoi(w);

            /* Check if it matches the user's primary group */
            if (gid == pwd->pw_gid)
            {
                if (at != NULL) *at= '@';
                return 1;
            }

            /* Get list of group members for numeric group id */
            grp= getgrgid(gid);
        }
        else
        {
            /* Get gid and list of group members for group name */
            grp= getgrnam(w);
            /* Check if gid of this group matches user's primary gid */
            if (grp != NULL && grp->gr_gid == pwd->pw_gid)
            {
                if (at != NULL) *at= '@';
                return 1;
            }
        }

        /* Walk through list of members, seeing if any match user login */
        if (grp != NULL)
        {
            char **p;
            for (p= grp->gr_mem; *p != NULL; p++)
            {
                if (!strcmp(user, *p))
                {
                    if (at != NULL) *at= '@';
                    return 1;
                }
            }
        }
    }
#endif

    /* Didn't find any matches, flunk him */
    if (at != NULL) *at= '@';
    return 0;
}
Esempio n. 30
0
/*
 * Scanner for variable constructs $xxx and ${xxx}
 */
static int DefineIndex(apr_pool_t *p, const char *pScope, char *cpLine, int *pos, int *len, char **cpVar)
{
    int rc;
    char *cp;
    char *cp2;
    CharClass cc;
    char cEscape;
    char cDefine;
    char cBraceOpen;
    char cBraceClose;
    char *cpError;
    ScanState s;

    cEscape = DEFAULT_MC_ESCAPE[0];
    if ((cp = DefineFetch(p, "mod_define", "escape")) != NULL)
        cEscape = cp[0];
    cDefine = DEFAULT_MC_DOLLAR[0];
    if ((cp = DefineFetch(p, "mod_define", "dollar")) != NULL)
        cDefine = cp[0];
    cBraceOpen = DEFAULT_MC_BRACEOPEN[0];
    if ((cp = DefineFetch(p, "mod_define", "braceopen")) != NULL)
        cBraceOpen = cp[0];
    cBraceClose = DEFAULT_MC_BRACECLOSE[0];
    if ((cp = DefineFetch(p, "mod_define", "braceclose")) != NULL)
        cBraceClose = cp[0];

    rc = 0;
    *len = 0;
    cc = CC_OTHER;
    s = SS_NONE;
    for (cp = cpLine+(*pos); cc != CC_EOS; cp++) {
        if (*cp == cEscape)
            cc = CC_ESCAPE;
        else if (*cp == cDefine)
            cc = CC_DOLLAR;
        else if (*cp == cBraceOpen)
            cc = CC_BRACEOPEN;
        else if (*cp == cBraceClose)
            cc = CC_BRACECLOSE;
        else if (apr_isalpha(*cp))
            cc = CC_IDCHAR1;
        else if (apr_isdigit(*cp) || *cp == '_' || *cp == ':' || *cp == '-')
            cc = CC_IDCHAR;
        else if (*cp == '\0')
            cc = CC_EOS;
        else
            cc = CC_OTHER;
        switch (s) {
            case SS_NONE:
                switch (cc) {
                    case CC_ESCAPE:
                        s = SS_SKIP;
                        break;
                    case CC_DOLLAR:
                        s = SS_DOLLAR;
                        break;
                    default:
                        break;
                }
                break;
            case SS_SKIP:
                s = SS_NONE;
                continue;
                break;
            case SS_DOLLAR:
                switch (cc) {
                    case CC_BRACEOPEN:
                        s = SS_TOKEN_BRACED;
                        *pos = cp-cpLine-1;
                        (*len) = 2;
                        *cpVar = cp+1;
                        break;
                    case CC_IDCHAR1:
                        s = SS_TOKEN_UNBRACED;
                        *pos = cp-cpLine-1;
                        (*len) = 2;
                        *cpVar = cp;
                        break;
                    case CC_ESCAPE:
                        s = SS_SKIP;
                        break;
                    default:
                        s = SS_NONE;
                        break;
                }
                break;
            case SS_TOKEN_BRACED:
                switch (cc) {
                    case CC_IDCHAR1:
                    case CC_IDCHAR:
                        (*len)++;
                        break;
                    case CC_BRACECLOSE:
                        (*len)++;
                        cp2 = apr_palloc(p, cp-*cpVar+1);
                        apr_cpystrn(cp2, *cpVar, cp-*cpVar+1);
                        *cpVar = cp2;
                        s = SS_FOUND;
                        break;
                    default:
                        cpError = apr_psprintf(p, "Illegal character '%c' in identifier", *cp);
                        s = SS_ERROR;
                        break;
                }
                break;
            case SS_TOKEN_UNBRACED:
                switch (cc) {
                    case CC_IDCHAR1:
                    case CC_IDCHAR:
                        (*len)++;
                        break;
                    default:
                        cp2 = apr_palloc(p, cp-*cpVar+1);
                        apr_cpystrn(cp2, *cpVar, cp-*cpVar+1);
                        *cpVar = cp2;
                        s = SS_FOUND;
                        break;
                }
                break;
            case SS_FOUND:
            case SS_ERROR:
                break;
        }
        if (s == SS_ERROR) {
            fprintf(stderr, "Error: %s\n", cpError);
            break;
        }
        else if (s == SS_FOUND) {
            rc = 1;
            break;
        }
    }
    return rc;
}