diff options
author | Stefan Fritsch <sf@apache.org> | 2010-11-06 15:31:16 +0100 |
---|---|---|
committer | Stefan Fritsch <sf@apache.org> | 2010-11-06 15:31:16 +0100 |
commit | 35cdba6976ca6f8a9bde73267340c40d7ae6d496 (patch) | |
tree | cc1609882f476369e5edea4aef79a868fef4f7fd | |
parent | Put the expression parser back into mod_include (diff) | |
download | apache2-35cdba6976ca6f8a9bde73267340c40d7ae6d496.tar.xz apache2-35cdba6976ca6f8a9bde73267340c40d7ae6d496.zip |
Replace ap_expr with a parser derived from mod_ssl's parser. Make mod_ssl use
the new parser. Rework ap_expr's public interface and provide hooks for modules
to add variables and functions.
The Netware and Windows build files still need to be adjusted
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1032073 13f79535-47bb-0310-9956-ffa450edef68
32 files changed, 3133 insertions, 3069 deletions
@@ -6,6 +6,12 @@ Changes with Apache 2.3.9 Fix a denial of service attack against mod_reqtimeout. [Stefan Fritsch] + *) core, mod_include, mod_ssl: Move the expression parser derived from + mod_include back into mod_include. Replace ap_expr with a parser + derived from mod_ssl's parser. Make mod_ssl use the new parser. Rework + ap_expr's public interface and provide hooks for modules to add variables + and functions. [Stefan Fritsch] + *) core: Do the hook sorting earlier so that the hooks are properly sorted for the pre_config hook and during parsing the config. [Stefan Fritsch] @@ -226,15 +226,15 @@ if [ -f `which cut` ]; then > httpd.spec ) fi -# ensure that the mod_ssl expression parser sources are never regenerated +# ensure that the ap_expr expression parser sources are never regenerated # when running make -echo fixing timestamps for mod_ssl sources -cd modules/ssl -touch ssl_expr_parse.y +echo fixing timestamps for ap_expr sources +cd server +touch util_expr_parse.y sleep 1 -touch ssl_expr_parse.c ssl_expr_parse.h ssl_expr_scan.l +touch util_expr_parse.c util_expr_parse.h util_expr_scan.l sleep 1 -touch ssl_expr_scan.c -cd ../.. +touch util_expr_scan.c +cd .. exit 0 diff --git a/include/ap_expr.h b/include/ap_expr.h index 99f2d1d883..b71c40aee2 100644 --- a/include/ap_expr.h +++ b/include/ap_expr.h @@ -23,128 +23,193 @@ #define AP_EXPR_H #include "httpd.h" +#include "http_config.h" #include "ap_regex.h" #ifdef __cplusplus extern "C" { #endif -/* conditional expression parser stuff */ -typedef enum { - TOKEN_STRING, - TOKEN_RE, - TOKEN_AND, - TOKEN_OR, - TOKEN_NOT, - TOKEN_EQ, - TOKEN_NE, - TOKEN_RBRACE, - TOKEN_LBRACE, - TOKEN_GROUP, - TOKEN_GE, - TOKEN_LE, - TOKEN_GT, - TOKEN_LT, - TOKEN_ACCESS, - TOKEN_IN -} token_type_t; +/** A node in the expression parse tree */ +typedef struct ap_expr_node ap_expr; +/** Struct describing a parsed expression */ typedef struct { - token_type_t type; - const char *value; -#ifdef DEBUG_INCLUDE - const char *s; -#endif -} token_t; - -typedef struct parse_node { - struct parse_node *parent; - struct parse_node *left; - struct parse_node *right; - token_t token; - int value; - int done; -#ifdef DEBUG_INCLUDE - int dump_done; -#endif -} ap_parse_node_t; + /** The root of the actual expression parse tree */ + ap_expr *root_node; + /** The filename where the expression has been defined (for logging). + * May be NULL + */ + const char *filename; + /** The line number where the expression has been defined (for logging). */ + unsigned int line_number; +#define AP_EXPR_FLAGS_SSL_EXPR_COMPAT 1 + /** Flags relevant for the expression */ + unsigned int flags; + /** The module that is used for loglevel configuration (XXX put into eval_ctx?) */ + int module_index; +} ap_expr_info_t; -typedef struct { - const char *source; - const char *rexp; - apr_size_t nsub; - ap_regmatch_t match[AP_MAX_REG_MATCH]; - int have_match; -} backref_t; -typedef const char *(*string_func_t)(request_rec*, const char*); -typedef int (*opt_func_t)(request_rec*, ap_parse_node_t*, string_func_t); - -/** - * Parse an expression into a parse tree - * @param pool Pool - * @param expr The expression to parse - * @param was_error On return, set to zero if parse successful, nonzero on error - * @return The parse tree - */ -AP_DECLARE(ap_parse_node_t*) ap_expr_parse(apr_pool_t *pool, const char *expr, - int *was_error); /** * Evaluate a parse tree * @param r The current request - * @param root The root node of the parse tree - * @param was_error On return, set to zero if parse successful, nonzero on error - * @param reptr Regular expression memory for backreferencing if a regexp was parsed - * @param string_func String parser function - perform variable substitutions - * Use ap_expr_string where applicable - * @param eval_func Option evaluation function (e.g. -A filename) - * @return the value the expression parsed to + * @param expr The expression to be evaluated + * @param err A more detailed error string + * @return > 0 if expression evaluates to true, == 0 if false, < 0 on error */ -AP_DECLARE(int) ap_expr_eval(request_rec *r, const ap_parse_node_t *root, - int *was_error, backref_t **reptr, - string_func_t string_func, opt_func_t eval_func); +AP_DECLARE(int) ap_expr_exec(request_rec *r, const ap_expr_info_t *expr, + const char **err); + +/** Context used during evaluation of a parse tree, created by ap_expr_exec */ +typedef struct { + /** the current request */ + request_rec *r; + /** the current connection */ + conn_rec *c; + /** the current connection */ + server_rec *s; + /** the pool to use */ + apr_pool_t *p; + /** where to store the error string */ + const char **err; + /** ap_expr_info_t for the expression */ + const ap_expr_info_t *info; +} ap_expr_eval_ctx; + + /** - * Evaluate an expression. This is functionally equivalent to - * ap_expr_parse followed by ap_expr_eval, but faster and more efficient - * when an expression only needs to be parsed once and discarded. - * @param r The current request - * @param expr The expression to parse - * @param was_error On return, set to zero if parse successful, nonzero on error - * @param reptr Regular expression memory for backreferencing if a regexp was parsed - * @param string_func String parser function - perform variable substitutions - * Use ap_expr_string where applicable - * @param eval_func Option evaluation function (e.g. -A filename) - * @return the value the expression parsed to + * The parse can be extended with variable lookup, functions, and + * and operators. + * + * During parsing, the parser calls the lookup function to resolve a + * name into a function pointer and an opaque context for the function. + * + * The default lookup function is the hook 'ap_run_expr_lookup'. + * Modules can use it to make functions and variables generally available. + * + * An ap_expr consumer can also provide its own custom lookup function to + * modify the set of variables and functions that are available. The custom + * lookup function can in turn call 'ap_run_expr_lookup'. + */ + +/** Unary operator, takes one string argument and returns a bool value. + * The name must have the form '-z' (one letter only). + * @param ctx The evaluation context + * @param data An opaque context provided by the lookup hook function + * @param arg The (right) operand + * @return 0 or 1 + */ +typedef int ap_expr_op_unary_t(ap_expr_eval_ctx *ctx, const void *data, + const char *arg); + +/** Binary operator, takes two string arguments and returns a bool value. + * The name must have the form '-cmp' (at least two letters). + * @param ctx The evaluation context + * @param data An opaque context provided by the lookup hook function + * @param arg1 The left operand + * @param arg2 The right operand + * @return 0 or 1 + */ +typedef int ap_expr_op_binary_t(ap_expr_eval_ctx *ctx, const void *data, + const char *arg1, const char *arg2); + +/** String valued function, takes a string argument and returns a string + * @param ctx The evaluation context + * @param data An opaque context provided by the lookup hook function + * @param arg The argument + * @return The functions result string, may be NULL for 'empty string' + */ +typedef const char *(ap_expr_string_func_t)(ap_expr_eval_ctx *ctx, const void *data, + const char *arg); + +/** List valued function, takes a string argument and returns a list of strings + * Can currently only be called following the builtin '-in' operator. + * @param ctx The evaluation context + * @param data An opaque context provided by the lookup hook function + * @param arg The argument + * @return The functions result list of strings, may be NULL for 'empty array' */ -AP_DECLARE(int) ap_expr_evalstring(request_rec *r, const char *expr, - int *was_error, backref_t **reptr, - string_func_t string_func, - opt_func_t eval_func); +typedef apr_array_header_t *(ap_expr_list_func_t)(ap_expr_eval_ctx *ctx, const void *data, + const char *arg); + +/** Variable lookup function, takes no argument and returns a string + * @param ctx The evaluation context + * @param data An opaque context provided by the lookup hook function + * @return The expanded variable + */ +typedef const char *(ap_expr_var_func_t)(ap_expr_eval_ctx *ctx, const void *data); + +/** parameter struct passed to the lookup hook functions */ +typedef struct { + /** type of the looked up object */ + int type; +#define AP_EXPR_FUNC_VAR 0 +#define AP_EXPR_FUNC_STRING 1 +#define AP_EXPR_FUNC_LIST 2 +#define AP_EXPR_FUNC_OP_UNARY 3 +#define AP_EXPR_FUNC_OP_BINARY 4 + /** name of the looked up object */ + const char *name; + + int flags; + + apr_pool_t *pool; + apr_pool_t *ptemp; + + /** where to store the function pointer */ + const void **func; + /** where to store the function's context */ + const void **data; + /** Where to store the error message (if any) */ + const char **err; +} ap_expr_lookup_parms; + +/** Function for looking up the provider function for a variable, operator + * or function in an expression. + * @param parms The parameter struct, also determins where the result is + * stored. + * @return OK on success, + * !OK on failure, + * DECLINED if the requested name is not handled by this function + */ +typedef int (ap_expr_lookup_fn)(ap_expr_lookup_parms *parms); + +AP_DECLARE_HOOK(int, expr_lookup, (ap_expr_lookup_parms *parms)) /** - * Internal initialisation of ap_expr (for httpd) + * Parse an expression into a parse tree * @param pool Pool - * @return APR_SUCCESS or error + * @param ptemp temp pool + * @param info The ap_expr_info_t struct (with values filled in) + * @param expr The expression string to parse + * @param lookup_fn The lookup function to use, NULL for default + * @return NULL on success, error message on error. + * A pointer to the resulting parse tree will be stored in + * info->root_node. */ -AP_DECLARE(apr_status_t) ap_expr_init(apr_pool_t *pool); +AP_DECLARE(const char *) ap_expr_parse(apr_pool_t *pool, apr_pool_t *ptemp, + ap_expr_info_t *info, const char *expr, + ap_expr_lookup_fn *lookup_fn); /** - * Default string evaluation function for passing to ap_expr_eval and - * ap_expr_evalstring. Use this (and update as necessary) to offer - * a consistent expression syntax across different modules. - * Supports the following: - * $req{foo} - request header "foo" - * $resp{foo} - response header "foo" - * $env{foo} - environment variable "foo" - * $handler - r->handler - * $content-type - r->content_type - * Other strings are returned unmodified. - * @param r The current request - * @param str The string to evaluate - * @return The evaluated string + * High level interface to ap_expr_parse that also creates ap_expr_info_t and + * uses info from cmd_parms to fill in most of it. + * @param cmd The cmd_parms struct + * @param expr The expression string to parse + * @param err Set to NULL on success, error message on error + * @return The parsed expression */ -AP_DECLARE_NONSTD(const char*) ap_expr_string(request_rec *r, - const char *str); +AP_DECLARE(ap_expr_info_t *) ap_expr_parse_cmd(const cmd_parms *cmd, + const char *expr, + const char **err, + ap_expr_lookup_fn *lookup_fn); + + + /** + * Internal initialisation of ap_expr (for httpd internal use) + */ +void ap_expr_init(apr_pool_t *pool); #ifdef __cplusplus } diff --git a/include/ap_mmn.h b/include/ap_mmn.h index 2eec68b3e7..f5de1ccc63 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -277,12 +277,16 @@ * 20101016.0 (2.3.9-dev) Remove ap_cache_check_allowed(). * 20101017.0 (2.3.9-dev) Make ap_cache_control() public, add cache_control_t * to mod_disk_cache format. + * 20101106.0 (2.3.9-dev) Replace the ap_expr parser derived from + * mod_include's parser with one derived from + * mod_ssl's parser. Clean up ap_expr's public + * interface. */ #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */ #ifndef MODULE_MAGIC_NUMBER_MAJOR -#define MODULE_MAGIC_NUMBER_MAJOR 20101017 +#define MODULE_MAGIC_NUMBER_MAJOR 20101106 #endif #define MODULE_MAGIC_NUMBER_MINOR 0 /* 0...n */ diff --git a/include/http_core.h b/include/http_core.h index 858d8b5741..f3b7f5b910 100644 --- a/include/http_core.h +++ b/include/http_core.h @@ -534,7 +534,7 @@ typedef struct { #define USE_CANONICAL_PHYS_PORT_UNSET (2) unsigned use_canonical_phys_port : 2; - ap_parse_node_t *condition; /* Conditionally merge <If> sections */ + ap_expr_info_t *condition; /* Conditionally merge <If> sections */ /** per-dir log config */ struct ap_logconf *log; diff --git a/modules/aaa/mod_authz_core.c b/modules/aaa/mod_authz_core.c index 7ca38e7a29..73b13ab530 100644 --- a/modules/aaa/mod_authz_core.c +++ b/modules/aaa/mod_authz_core.c @@ -988,20 +988,22 @@ static authz_status expr_check_authorization(request_rec *r, const char *require_line, const void *parsed_require_line) { - int err = 0; - const ap_parse_node_t *expr = parsed_require_line; + const char *err = NULL; + const ap_expr_info_t *expr = parsed_require_line; + int rc = ap_expr_exec(r, expr, &err); - if (ap_expr_eval(r, expr, &err, NULL, ap_expr_string, NULL)) - return AUTHZ_GRANTED; - else + if (err || !rc) + /* XXX: real error handling? */ return AUTHZ_DENIED; + else + return AUTHZ_GRANTED; } static const char *expr_parse_config(cmd_parms *cmd, const char *require_line, const void **parsed_require_line) { - int expr_err = 0; - ap_parse_node_t *expr = ap_expr_parse(cmd->pool, require_line, &expr_err); + const char *expr_err = NULL; + ap_expr_info_t *expr = ap_expr_parse_cmd(cmd, require_line, &expr_err, NULL); if (expr_err) return "Cannot parse expression in require line"; diff --git a/modules/filters/mod_filter.c b/modules/filters/mod_filter.c index 3970c836e7..250c02d147 100644 --- a/modules/filters/mod_filter.c +++ b/modules/filters/mod_filter.c @@ -36,7 +36,7 @@ module AP_MODULE_DECLARE_DATA filter_module; * (2.0-compatible) ap_filter_rec_t* frec. */ struct ap_filter_provider_t { - ap_parse_node_t *expr; + ap_expr_info_t *expr; /** The filter that implements this provider */ ap_filter_rec_t *frec; @@ -134,7 +134,7 @@ static int filter_lookup(ap_filter_t *f, ap_filter_rec_t *filter) { ap_filter_provider_t *provider; int match; - int err = 0; + const char *err = NULL; unsigned int proto_flags; request_rec *r = f->r; harness_ctx *ctx = f->ctx; @@ -146,11 +146,12 @@ static int filter_lookup(ap_filter_t *f, ap_filter_rec_t *filter) /* Check registered providers in order */ for (provider = filter->providers; provider; provider = provider->next) { - match = ap_expr_eval(r, provider->expr, &err, NULL, ap_expr_string, NULL); + match = ap_expr_exec(r, provider->expr, &err); if (err) { /* log error but accept match value ? */ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "Error evaluating filter dispatch condition"); + "Error evaluating filter dispatch condition: %s", + err); } if (match) { @@ -402,8 +403,8 @@ static const char *filter_provider(cmd_parms *cmd, void *CFG, const char *c; ap_filter_rec_t* frec; ap_filter_rec_t* provider_frec; - ap_parse_node_t *node; - int err = 0; + ap_expr_info_t *node; + const char *err = NULL; /* fname has been declared with DeclareFilter, so we can look it up */ frec = apr_hash_get(cfg->live_filters, fname, APR_HASH_KEY_STRING); @@ -426,9 +427,11 @@ static const char *filter_provider(cmd_parms *cmd, void *CFG, if (!provider_frec) { return apr_psprintf(cmd->pool, "Unknown filter provider %s", pname); } - node = ap_expr_parse(cmd->pool, expr, &err); + node = ap_expr_parse_cmd(cmd, expr, &err, NULL); if (err) { - return "Error parsing FilterProvider expression."; + return apr_pstrcat(cmd->pool, + "Error parsing FilterProvider expression:", err, + NULL); } provider = apr_palloc(cmd->pool, sizeof(ap_filter_provider_t)); @@ -545,7 +548,7 @@ static const char *filter_bytype1(cmd_parms *cmd, void *CFG, *p++ = *type++; } while (*type); *p = 0; - expr = apr_psprintf(cmd->temp_pool, "$content-type = /^%s/", etype); + expr = apr_psprintf(cmd->temp_pool, "%%{CONTENT_TYPE} =~ m!^%s!", etype); rv = filter_provider(cmd, CFG, fname, pname, expr); diff --git a/modules/metadata/mod_headers.c b/modules/metadata/mod_headers.c index b02ed715af..505cb06eae 100644 --- a/modules/metadata/mod_headers.c +++ b/modules/metadata/mod_headers.c @@ -130,7 +130,7 @@ typedef struct { ap_regex_t *regex; const char *condition_var; const char *subs; - ap_parse_node_t *expr; + ap_expr_info_t *expr; } header_entry; /* echo_do is used for Header echo to iterate through the request headers*/ @@ -398,7 +398,7 @@ static APR_INLINE const char *header_inout_cmd(cmd_parms *cmd, const char *condition_var = NULL; const char *colon; header_entry *new; - ap_parse_node_t *expr = NULL; + ap_expr_info_t *expr = NULL; apr_array_header_t *fixup = (cmd->info == &hdr_in) ? dirconf->fixup_in : (cmd->info == &hdr_out_always) @@ -491,10 +491,12 @@ static APR_INLINE const char *header_inout_cmd(cmd_parms *cmd, condition_var = envclause + 4; } else { - int err = 0; - expr = ap_expr_parse(cmd->pool, envclause, &err); + const char *err = NULL; + expr = ap_expr_parse_cmd(cmd, envclause, &err, NULL); if (err) { - return "Can't parse envclause/expression"; + return apr_pstrcat(cmd->pool, + "Can't parse envclause/expression: ", err, + NULL); } } } @@ -645,12 +647,12 @@ static void do_headers_fixup(request_rec *r, apr_table_t *headers, } /* Do we have an expression to evaluate? */ else if (hdr->expr != NULL) { - int err = 0; - int eval = ap_expr_eval(r, hdr->expr, &err, NULL, - ap_expr_string, NULL); + const char *err = NULL; + int eval = ap_expr_exec(r, hdr->expr, &err); if (err) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "Failed to evaluate expression - ignoring"); + "Failed to evaluate expression (%s) - ignoring", + err); } else if (!eval) { continue; diff --git a/modules/ssl/Makefile.in b/modules/ssl/Makefile.in index e8a88876d0..4395bc3ac7 100644 --- a/modules/ssl/Makefile.in +++ b/modules/ssl/Makefile.in @@ -18,20 +18,3 @@ # include $(top_srcdir)/build/special.mk - -# -# developer stuff -# (we really don't expect end users to use these targets!) -# - -ssl_expr_scan.c: $(top_srcdir)/modules/ssl/ssl_expr_scan.l ssl_expr_parse.h - flex -Pssl_expr_yy -o ssl_expr_scan.c $(top_srcdir)/ssl_expr_scan.l - mv ssl_expr_scan.c ssl_expr_scan.c.tmp - sed -e "s|\"`pwd`/|\"|g" <ssl_expr_scan.c.tmp >ssl_expr_scan.c - rm -f ssl_expr_scan.c.tmp - -ssl_expr_parse.c ssl_expr_parse.h: $(top_srcdir)/modules/ssl/ssl_expr_parse.y - bison -pssl_expr_yy --defines=ssl_expr_parse.h -o ssl_expr_parse.c $(top_srcdir)/modules/ssl/ssl_expr_parse.y - mv ssl_expr_parse.c ssl_expr_parse.c.tmp - sed -e "s|\"`pwd`/|\"|g" < ssl_expr_parse.c.tmp > ssl_expr_parse.c - rm -f ssl_expr_parse.c.tmp diff --git a/modules/ssl/config.m4 b/modules/ssl/config.m4 index 2ef06cdcfb..b020acafcb 100644 --- a/modules/ssl/config.m4 +++ b/modules/ssl/config.m4 @@ -35,10 +35,6 @@ ssl_engine_mutex.lo dnl ssl_engine_pphrase.lo dnl ssl_engine_rand.lo dnl ssl_engine_vars.lo dnl -ssl_expr.lo dnl -ssl_expr_eval.lo dnl -ssl_expr_parse.lo dnl -ssl_expr_scan.lo dnl ssl_scache.lo dnl ssl_util_stapling.lo dnl ssl_util.lo dnl diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c index aa2dec8401..3d090cb15b 100644 --- a/modules/ssl/mod_ssl.c +++ b/modules/ssl/mod_ssl.c @@ -565,11 +565,6 @@ static void ssl_register_hooks(apr_pool_t *p) &ssl_authz_provider_verify_client, AP_AUTH_INTERNAL_PER_CONF); - ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ssl-require", - AUTHZ_PROVIDER_VERSION, - &ssl_authz_provider_sslrequire, - AP_AUTH_INTERNAL_PER_CONF); - } module AP_MODULE_DECLARE_DATA ssl_module = { diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c index b3dbfef63e..0ed504422e 100644 --- a/modules/ssl/ssl_engine_config.c +++ b/modules/ssl/ssl_engine_config.c @@ -1147,17 +1147,21 @@ const char *ssl_cmd_SSLRequire(cmd_parms *cmd, const char *arg) { SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg; - ssl_expr *expr; + ap_expr_info_t *info = apr_pcalloc(cmd->pool, sizeof(ap_expr_info_t)); ssl_require_t *require; const char *errstring; - if (!(expr = ssl_expr_comp(cmd->pool, arg, &errstring))) { + info->flags = AP_EXPR_FLAGS_SSL_EXPR_COMPAT; + info->filename = cmd->directive->filename; + info->line_number = cmd->directive->line_num; + errstring = ap_expr_parse(cmd->pool, cmd->temp_pool, info, arg, NULL); + if (errstring) { return apr_pstrcat(cmd->pool, "SSLRequire: ", errstring, NULL); } require = apr_array_push(dc->aRequirement); require->cpExpr = apr_pstrdup(cmd->pool, arg); - require->mpExpr = expr; + require->mpExpr = info; return NULL; } diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c index c374ce0fae..2f736c26d8 100644 --- a/modules/ssl/ssl_engine_kernel.c +++ b/modules/ssl/ssl_engine_kernel.c @@ -302,7 +302,6 @@ int ssl_hook_Access(request_rec *r) SSL_CTX *ctx = NULL; apr_array_header_t *requires; ssl_require_t *ssl_requires; - char *cp; int ok, i; BOOL renegotiate = FALSE, renegotiate_quick = FALSE; X509 *cert; @@ -900,17 +899,13 @@ int ssl_hook_Access(request_rec *r) for (i = 0; i < requires->nelts; i++) { ssl_require_t *req = &ssl_requires[i]; const char *errstring; - ok = ssl_expr_exec(r, req->mpExpr, &errstring); + ok = ap_expr_exec(r, req->mpExpr, &errstring); if (ok < 0) { - cp = apr_psprintf(r->pool, - "Failed to execute " - "SSL requirement expression: %s", - errstring); - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "access to %s failed, reason: %s", - r->filename, cp); + "access to %s failed, reason: Failed to execute " + "SSL requirement expression: %s", + r->filename, errstring); /* remember forbidden access for strict require option */ apr_table_setn(r->notes, "ssl-access-forbidden", "1"); @@ -1282,54 +1277,6 @@ const authz_provider ssl_authz_provider_verify_client = }; -static authz_status ssl_authz_sslrequire_check(request_rec *r, - const char *require_line, - const void *parsed) -{ - const ssl_expr *expr = parsed; - const char *errstring; - int ok = ssl_expr_exec(r, expr, &errstring); - - if (ok < 0) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "Failed to execute SSL requirement expression in " - "'Require ssl-require': %s", - errstring); - return AUTHZ_DENIED; - } - - if (ok != 1) { - ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, - "SSL requirement expression in 'Require ssl-require' " - "not fulfilled"); - return AUTHZ_DENIED; - } - - return AUTHZ_GRANTED; -} - -static const char *ssl_authz_sslrequire_parse(cmd_parms *cmd, - const char *require_line, - const void **parsed) -{ - const char *errstring; - ssl_expr *expr = ssl_expr_comp(cmd->pool, require_line, &errstring); - - if (!expr) - return apr_psprintf(cmd->pool, "Error in 'Require require-ssl': %s", - errstring); - - *parsed = expr; - - return NULL; -} - -const authz_provider ssl_authz_provider_sslrequire = -{ - &ssl_authz_sslrequire_check, - &ssl_authz_sslrequire_parse, -}; - /* _________________________________________________________________ ** diff --git a/modules/ssl/ssl_engine_vars.c b/modules/ssl/ssl_engine_vars.c index 62127fff2d..f88eebfd4d 100644 --- a/modules/ssl/ssl_engine_vars.c +++ b/modules/ssl/ssl_engine_vars.c @@ -29,6 +29,7 @@ -- Unknown */ #include "ssl_private.h" #include "mod_ssl.h" +#include "ap_expr.h" #include "apr_time.h" @@ -62,6 +63,45 @@ static const char var_interface[] = "mod_ssl/" MOD_SSL_VERSION; static char var_library_interface[] = SSL_LIBRARY_TEXT; static char *var_library = NULL; +static apr_array_header_t *expr_peer_ext_list_fn(ap_expr_eval_ctx *ctx, + const void *dummy, + const char *arg) +{ + return ssl_ext_list(ctx->p, ctx->c, 1, arg); +} + +static const char *expr_var_fn(ap_expr_eval_ctx *ctx, const void *data) +{ + char *var = (char *)data; + return ssl_var_lookup_ssl(ctx->p, ctx->c, var); +} + +static int ssl_expr_lookup(ap_expr_lookup_parms *parms) +{ + switch (parms->type) { + case AP_EXPR_FUNC_VAR: + /* for now, we just handle everything that starts with SSL_, but + * register our hook as APR_HOOK_LAST + * XXX: This can be optimized + */ + if (strcEQn(parms->name, "SSL_", 4)) { + *parms->func = expr_var_fn; + *parms->data = parms->name + 4; + return OK; + } + break; + case AP_EXPR_FUNC_LIST: + if (strcEQ(parms->name, "PeerExtList")) { + *parms->func = expr_peer_ext_list_fn; + *parms->data = "PeerExtList"; + return OK; + } + break; + } + return DECLINED; +} + + void ssl_var_register(apr_pool_t *p) { char *cp, *cp2; @@ -84,6 +124,8 @@ void ssl_var_register(apr_pool_t *p) if ((cp2 = strchr(cp, ' ')) != NULL) *cp2 = NUL; } + + ap_hook_expr_lookup(ssl_expr_lookup, NULL, NULL, APR_HOOK_MIDDLE); } /* This function must remain safe to use for a non-SSL connection. */ @@ -984,3 +1026,4 @@ static const char *ssl_var_log_handler_x(request_rec *r, char *a) return result; } + diff --git a/modules/ssl/ssl_expr.c b/modules/ssl/ssl_expr.c deleted file mode 100644 index 04262af1ab..0000000000 --- a/modules/ssl/ssl_expr.c +++ /dev/null @@ -1,85 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* _ _ - * _ __ ___ ___ __| | ___ ___| | mod_ssl - * | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL - * | | | | | | (_) | (_| | \__ \__ \ | - * |_| |_| |_|\___/ \__,_|___|___/___/_| - * |_____| - * ssl_expr.c - * Expression Handling - */ - /* ``It is hard to fly with - the eagles when you work - with the turkeys.'' - -- Unknown */ -#include "ssl_private.h" - -/* _________________________________________________________________ -** -** Expression Handling -** _________________________________________________________________ -*/ - - -ssl_expr *ssl_expr_comp(apr_pool_t *p, const char *expr, const char **err) -{ - ssl_expr_info_type context; - int rc; - - context.pool = p; - context.inputbuf = expr; - context.inputlen = strlen(expr); - context.inputptr = context.inputbuf; - context.expr = FALSE; - context.error = NULL; - - ssl_expr_yylex_init(&context.scanner); - ssl_expr_yyset_extra(&context, context.scanner); - rc = ssl_expr_yyparse(&context); - ssl_expr_yylex_destroy(context.scanner); - *err = context.error; - - if (rc) - return NULL; - - return context.expr; -} - -ssl_expr *ssl_expr_make(ssl_expr_node_op op, void *a1, void *a2, - ssl_expr_info_type *context) -{ - ssl_expr *node; - - node = (ssl_expr *)apr_palloc(context->pool, sizeof(ssl_expr)); - node->node_op = op; - node->node_arg1 = (char *)a1; - node->node_arg2 = (char *)a2; - return node; -} - -int ssl_expr_exec(request_rec *r, const ssl_expr *expr, const char **err) -{ - BOOL rc; - - *err = NULL; - rc = ssl_expr_eval(r, expr, err); - if (*err != NULL) - return (-1); - else - return (rc ? 1 : 0); -} diff --git a/modules/ssl/ssl_expr.h b/modules/ssl/ssl_expr.h deleted file mode 100644 index a8be52c836..0000000000 --- a/modules/ssl/ssl_expr.h +++ /dev/null @@ -1,109 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @verbatim - _ _ - _ __ ___ ___ __| | ___ ___| | mod_ssl - | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL - | | | | | | (_) | (_| | \__ \__ \ | - |_| |_| |_|\___/ \__,_|___|___/___/_| - |_____| - @endverbatim - * @file ssl_expr.h - * @brief Expression Handling (Header). - * ``May all your PUSHes be POPed.'' - * - * @defgroup MOD_SSL_EXPR Expression Handling - * @ingroup MOD_SSL - * @{ - */ - -#ifndef __SSL_EXPR_H__ -#define __SSL_EXPR_H__ - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE !FALSE -#endif - -#ifndef YY_NULL -#define YY_NULL 0 -#endif - -#ifndef MIN -#define MIN(a,b) (((a)<(b))?(a):(b)) -#endif - -#ifndef BOOL -#define BOOL unsigned int -#endif - -#ifndef NULL -#define NULL (void *)0 -#endif - -#ifndef NUL -#define NUL '\0' -#endif - -#ifndef YYDEBUG -#define YYDEBUG 0 -#endif - -typedef enum { - op_NOP, op_ListElement, op_PeerExtElement, - op_True, op_False, op_Not, op_Or, op_And, op_Comp, - op_EQ, op_NE, op_LT, op_LE, op_GT, op_GE, op_IN, op_REG, op_NRE, - op_Digit, op_String, op_Regex, op_Var, op_Func -} ssl_expr_node_op; - -typedef struct { - ssl_expr_node_op node_op; - void *node_arg1; - void *node_arg2; -} ssl_expr_node; - -typedef ssl_expr_node ssl_expr; - -typedef struct { - apr_pool_t *pool; - const char *inputbuf; - int inputlen; - const char *inputptr; - ssl_expr *expr; - void *scanner; - char *error; -} ssl_expr_info_type; - -int ssl_expr_yyparse(ssl_expr_info_type *context); -int ssl_expr_yyerror(ssl_expr_info_type *context, char *errstring); -int ssl_expr_yylex_init(void **scanner); -int ssl_expr_yylex_destroy(void *scanner); -void ssl_expr_yyset_extra(ssl_expr_info_type *context, void *scanner); - -ssl_expr *ssl_expr_comp(apr_pool_t *p, const char *exprstr, const char **err); -int ssl_expr_exec(request_rec *r, const ssl_expr *expr, const char **err); -ssl_expr *ssl_expr_make(ssl_expr_node_op op, void *arg1, void *arg2, - ssl_expr_info_type *context); -BOOL ssl_expr_eval(request_rec *r, const ssl_expr *expr, const char **err); - -#endif /* __SSL_EXPR_H__ */ -/** @} */ - diff --git a/modules/ssl/ssl_expr_eval.c b/modules/ssl/ssl_expr_eval.c deleted file mode 100644 index 9480048d89..0000000000 --- a/modules/ssl/ssl_expr_eval.c +++ /dev/null @@ -1,290 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* _ _ - * _ __ ___ ___ __| | ___ ___| | mod_ssl - * | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL - * | | | | | | (_) | (_| | \__ \__ \ | - * |_| |_| |_|\___/ \__,_|___|___/___/_| - * |_____| - * ssl_expr_eval.c - * Expression Evaluation - */ - /* ``Make love, - not software!'' - -- Unknown */ -#include "ssl_private.h" - -/* _________________________________________________________________ -** -** Expression Evaluation -** _________________________________________________________________ -*/ - -static BOOL ssl_expr_eval_comp(request_rec *, ssl_expr *, const char **err); -static char *ssl_expr_eval_word(request_rec *, ssl_expr *, const char **err); -static BOOL ssl_expr_eval_oid(request_rec *r, const char *word, - const char *oidstr, const char **err); -static char *ssl_expr_eval_func_file(request_rec *, char *, const char **err); -static int ssl_expr_eval_strcmplex(char *, char *, const char **err); - -BOOL ssl_expr_eval(request_rec *r, const ssl_expr *node, const char **err) -{ - switch (node->node_op) { - case op_True: { - return TRUE; - } - case op_False: { - return FALSE; - } - case op_Not: { - ssl_expr *e = (ssl_expr *)node->node_arg1; - return (!ssl_expr_eval(r, e, err)); - } - case op_Or: { - ssl_expr *e1 = (ssl_expr *)node->node_arg1; - ssl_expr *e2 = (ssl_expr *)node->node_arg2; - return (ssl_expr_eval(r, e1, err) || ssl_expr_eval(r, e2, err)); - } - case op_And: { - ssl_expr *e1 = (ssl_expr *)node->node_arg1; - ssl_expr *e2 = (ssl_expr *)node->node_arg2; - return (ssl_expr_eval(r, e1, err) && ssl_expr_eval(r, e2, err)); - } - case op_Comp: { - ssl_expr *e = (ssl_expr *)node->node_arg1; - return ssl_expr_eval_comp(r, e, err); - } - default: { - *err = "Internal evaluation error: Unknown expression node"; - return FALSE; - } - } -} - -static BOOL ssl_expr_eval_comp(request_rec *r, ssl_expr *node, const char **err) -{ - switch (node->node_op) { - case op_EQ: { - ssl_expr *e1 = (ssl_expr *)node->node_arg1; - ssl_expr *e2 = (ssl_expr *)node->node_arg2; - return (strcmp(ssl_expr_eval_word(r, e1, err), ssl_expr_eval_word(r, e2, err)) == 0); - } - case op_NE: { - ssl_expr *e1 = (ssl_expr *)node->node_arg1; - ssl_expr *e2 = (ssl_expr *)node->node_arg2; - return (strcmp(ssl_expr_eval_word(r, e1, err), ssl_expr_eval_word(r, e2, err)) != 0); - } - case op_LT: { - ssl_expr *e1 = (ssl_expr *)node->node_arg1; - ssl_expr *e2 = (ssl_expr *)node->node_arg2; - return (ssl_expr_eval_strcmplex(ssl_expr_eval_word(r, e1, err), ssl_expr_eval_word(r, e2, err), err) < 0); - } - case op_LE: { - ssl_expr *e1 = (ssl_expr *)node->node_arg1; - ssl_expr *e2 = (ssl_expr *)node->node_arg2; - return (ssl_expr_eval_strcmplex(ssl_expr_eval_word(r, e1, err), ssl_expr_eval_word(r, e2, err), err) <= 0); - } - case op_GT: { - ssl_expr *e1 = (ssl_expr *)node->node_arg1; - ssl_expr *e2 = (ssl_expr *)node->node_arg2; - return (ssl_expr_eval_strcmplex(ssl_expr_eval_word(r, e1, err), ssl_expr_eval_word(r, e2, err), err) > 0); - } - case op_GE: { - ssl_expr *e1 = (ssl_expr *)node->node_arg1; - ssl_expr *e2 = (ssl_expr *)node->node_arg2; - return (ssl_expr_eval_strcmplex(ssl_expr_eval_word(r, e1, err), ssl_expr_eval_word(r, e2, err), err) >= 0); - } - case op_IN: { - ssl_expr *e1 = (ssl_expr *)node->node_arg1; - ssl_expr *e2 = (ssl_expr *)node->node_arg2; - ssl_expr *e3; - char *w1 = ssl_expr_eval_word(r, e1, err); - BOOL found = FALSE; - do { - ssl_expr_node_op op = e2->node_op; - e3 = (ssl_expr *)e2->node_arg1; - e2 = (ssl_expr *)e2->node_arg2; - - if (op == op_PeerExtElement) { - char *w3 = ssl_expr_eval_word(r, e3, err); - - found = ssl_expr_eval_oid(r, w1, w3, err); - - /* There will be no more nodes on the list, so the result is authoritative */ - break; - } - - if (strcmp(w1, ssl_expr_eval_word(r, e3, err)) == 0) { - found = TRUE; - break; - } - } while (e2 != NULL); - return found; - } - case op_REG: { - ssl_expr *e1; - ssl_expr *e2; - char *word; - ap_regex_t *regex; - - e1 = (ssl_expr *)node->node_arg1; - e2 = (ssl_expr *)node->node_arg2; - word = ssl_expr_eval_word(r, e1, err); - regex = (ap_regex_t *)(e2->node_arg1); - return (ap_regexec(regex, word, 0, NULL, 0) == 0); - } - case op_NRE: { - ssl_expr *e1; - ssl_expr *e2; - char *word; - ap_regex_t *regex; - - e1 = (ssl_expr *)node->node_arg1; - e2 = (ssl_expr *)node->node_arg2; - word = ssl_expr_eval_word(r, e1, err); - regex = (ap_regex_t *)(e2->node_arg1); - return !(ap_regexec(regex, word, 0, NULL, 0) == 0); - } - default: { - *err = "Internal evaluation error: Unknown expression node"; - return FALSE; - } - } -} - -static char *ssl_expr_eval_word(request_rec *r, ssl_expr *node, const char **err) -{ - switch (node->node_op) { - case op_Digit: { - char *string = (char *)node->node_arg1; - return string; - } - case op_String: { - char *string = (char *)node->node_arg1; - return string; - } - case op_Var: { - char *var = (char *)node->node_arg1; - char *val = ssl_var_lookup(r->pool, r->server, r->connection, r, var); - return (val == NULL ? "" : val); - } - case op_Func: { - char *name = (char *)node->node_arg1; - ssl_expr *args = (ssl_expr *)node->node_arg2; - if (strEQ(name, "file")) - return ssl_expr_eval_func_file(r, (char *)(args->node_arg1), err); - else { - *err = "Internal evaluation error: Unknown function name"; - return ""; - } - } - default: { - *err = "Internal evaluation error: Unknown expression node"; - return FALSE; - } - } -} - -static BOOL ssl_expr_eval_oid(request_rec *r, const char *word, - const char *oidstr, const char **err) -{ - int j; - BOOL result = FALSE; - apr_array_header_t *oid_array; - char **oid_value; - - if (NULL == (oid_array = ssl_ext_list(r->pool, r->connection, 1, oidstr))) { - return FALSE; - } - - oid_value = (char **) oid_array->elts; - for (j = 0; j < oid_array->nelts; j++) { - if (strcmp(word, oid_value[j]) == 0) { - result = TRUE; - break; - } - } - return result; -} - - -static char *ssl_expr_eval_func_file(request_rec *r, char *filename, const char **err) -{ - apr_file_t *fp; - char *buf; - apr_off_t offset; - apr_size_t len; - apr_finfo_t finfo; - - if (apr_file_open(&fp, filename, APR_READ|APR_BUFFERED, - APR_OS_DEFAULT, r->pool) != APR_SUCCESS) { - *err = "Cannot open file"; - return ""; - } - apr_file_info_get(&finfo, APR_FINFO_SIZE, fp); - if ((finfo.size + 1) != ((apr_size_t)finfo.size + 1)) { - *err = "Huge file cannot be read"; - apr_file_close(fp); - return ""; - } - len = (apr_size_t)finfo.size; - if (len == 0) { - buf = (char *)apr_palloc(r->pool, sizeof(char) * 1); - *buf = NUL; - } - else { - if ((buf = (char *)apr_palloc(r->pool, sizeof(char)*(len+1))) == NULL) { - *err = "Cannot allocate memory"; - apr_file_close(fp); - return ""; - } - offset = 0; - apr_file_seek(fp, APR_SET, &offset); - if (apr_file_read(fp, buf, &len) != APR_SUCCESS) { - *err = "Cannot read from file"; - apr_file_close(fp); - return ""; - } - buf[len] = NUL; - } - apr_file_close(fp); - return buf; -} - -/* a variant of strcmp(3) which works correctly also for number strings */ -static int ssl_expr_eval_strcmplex(char *cpNum1, char *cpNum2, const char **err) -{ - int i, n1, n2; - - if (cpNum1 == NULL) - return -1; - if (cpNum2 == NULL) - return +1; - n1 = strlen(cpNum1); - n2 = strlen(cpNum2); - if (n1 > n2) - return 1; - if (n1 < n2) - return -1; - for (i = 0; i < n1; i++) { - if (cpNum1[i] > cpNum2[i]) - return 1; - if (cpNum1[i] < cpNum2[i]) - return -1; - } - return 0; -} diff --git a/modules/ssl/ssl_expr_parse.y b/modules/ssl/ssl_expr_parse.y deleted file mode 100644 index ce270b6948..0000000000 --- a/modules/ssl/ssl_expr_parse.y +++ /dev/null @@ -1,169 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* _ _ - * _ __ ___ ___ __| | ___ ___| | - * | '_ ` _ \ / _ \ / _` | / __/ __| | - * | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to OpenSSL - * |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.modssl.org/ - * |_____| - * ssl_expr_parse.y - * Expression LR(1) Parser - */ - /* ``What you see is all you get.'' - -- Brian Kernighan */ - -/* _________________________________________________________________ -** -** Expression Parser -** _________________________________________________________________ -*/ - -%pure-parser -%defines -%error-verbose -%lex-param { void *yyscanner } -%parse-param { ssl_expr_info_type *context } - -%{ -#include "ssl_private.h" -%} - -%union { - char *cpVal; - ssl_expr *exVal; -} - -%token T_TRUE -%token T_FALSE - -%token <cpVal> T_DIGIT -%token <cpVal> T_ID -%token <cpVal> T_STRING -%token <cpVal> T_REGEX -%token <cpVal> T_REGEX_I - -%token T_FUNC_FILE - -%token T_OP_EQ -%token T_OP_NE -%token T_OP_LT -%token T_OP_LE -%token T_OP_GT -%token T_OP_GE -%token T_OP_REG -%token T_OP_NRE -%token T_OP_IN -%token T_OP_PEEREXTLIST - -%token T_OP_OR -%token T_OP_AND -%token T_OP_NOT - -%left T_OP_OR -%left T_OP_AND -%left T_OP_NOT - -%type <exVal> expr -%type <exVal> comparison -%type <exVal> funccall -%type <exVal> regex -%type <exVal> words -%type <exVal> wordlist -%type <exVal> word - -%{ -#include "ssl_expr.h" -#define yyscanner context->scanner - -int ssl_expr_yyerror(ssl_expr_info_type *context, char *err); -int ssl_expr_yylex(YYSTYPE *lvalp, void *scanner); -%} - - -%% - -root : expr { context->expr = $1; } - ; - -expr : T_TRUE { $$ = ssl_expr_make(op_True, NULL, NULL, context); } - | T_FALSE { $$ = ssl_expr_make(op_False, NULL, NULL, context); } - | T_OP_NOT expr { $$ = ssl_expr_make(op_Not, $2, NULL, context); } - | expr T_OP_OR expr { $$ = ssl_expr_make(op_Or, $1, $3, context); } - | expr T_OP_AND expr { $$ = ssl_expr_make(op_And, $1, $3, context); } - | comparison { $$ = ssl_expr_make(op_Comp, $1, NULL, context); } - | '(' expr ')' { $$ = $2; } - ; - -comparison: word T_OP_EQ word { $$ = ssl_expr_make(op_EQ, $1, $3, context); } - | word T_OP_NE word { $$ = ssl_expr_make(op_NE, $1, $3, context); } - | word T_OP_LT word { $$ = ssl_expr_make(op_LT, $1, $3, context); } - | word T_OP_LE word { $$ = ssl_expr_make(op_LE, $1, $3, context); } - | word T_OP_GT word { $$ = ssl_expr_make(op_GT, $1, $3, context); } - | word T_OP_GE word { $$ = ssl_expr_make(op_GE, $1, $3, context); } - | word T_OP_IN wordlist { $$ = ssl_expr_make(op_IN, $1, $3, context); } - | word T_OP_REG regex { $$ = ssl_expr_make(op_REG, $1, $3, context); } - | word T_OP_NRE regex { $$ = ssl_expr_make(op_NRE, $1, $3, context); } - ; - -wordlist : T_OP_PEEREXTLIST '(' word ')' { $$ = ssl_expr_make(op_PeerExtElement, $3, NULL, context); } - | '{' words '}' { $$ = $2 ; } - ; - -words : word { $$ = ssl_expr_make(op_ListElement, $1, NULL, context); } - | words ',' word { $$ = ssl_expr_make(op_ListElement, $3, $1, context); } - ; - -word : T_DIGIT { $$ = ssl_expr_make(op_Digit, $1, NULL, context); } - | T_STRING { $$ = ssl_expr_make(op_String, $1, NULL, context); } - | '%' '{' T_ID '}' { $$ = ssl_expr_make(op_Var, $3, NULL, context); } - | funccall { $$ = $1; } - ; - -regex : T_REGEX { - ap_regex_t *regex; - if ((regex = ap_pregcomp(context->pool, $1, - AP_REG_EXTENDED|AP_REG_NOSUB)) == NULL) { - context->error = "Failed to compile regular expression"; - YYERROR; - } - $$ = ssl_expr_make(op_Regex, regex, NULL, context); - } - | T_REGEX_I { - ap_regex_t *regex; - if ((regex = ap_pregcomp(context->pool, $1, - AP_REG_EXTENDED|AP_REG_NOSUB|AP_REG_ICASE)) == NULL) { - context->error = "Failed to compile regular expression"; - YYERROR; - } - $$ = ssl_expr_make(op_Regex, regex, NULL, context); - } - ; - -funccall : T_FUNC_FILE '(' T_STRING ')' { - ssl_expr *args = ssl_expr_make(op_ListElement, $3, NULL, context); - $$ = ssl_expr_make(op_Func, "file", args, context); - } - ; - -%% - -int yyerror(ssl_expr_info_type *context, char *s) -{ - context->error = s; - return 2; -} - diff --git a/modules/ssl/ssl_expr_scan.l b/modules/ssl/ssl_expr_scan.l deleted file mode 100644 index be57934f64..0000000000 --- a/modules/ssl/ssl_expr_scan.l +++ /dev/null @@ -1,230 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* _ _ - * _ __ ___ ___ __| | ___ ___| | - * | '_ ` _ \ / _ \ / _` | / __/ __| | - * | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to OpenSSL - * |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.modssl.org/ - * |_____| - * ssl_expr_scan.l - * Expression Scanner - */ - /* ``Killing for peace is - like fucking for virginity.'' - -- Unknown */ - -/* _________________________________________________________________ -** -** Expression Scanner -** _________________________________________________________________ -*/ - -%pointer -%option batch -%option never-interactive -%option nodefault -%option noyywrap -%option reentrant -%option bison-bridge -%option warn -%option noinput nounput -%x str -%x regex regex_flags - -%{ -#include "ssl_private.h" - -#include "ssl_expr_parse.h" -#include "ssl_expr.h" - -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ -{ \ - if ((result = MIN(max_size, yyextra->inputbuf \ - + yyextra->inputlen \ - - yyextra->inputptr)) <= 0) \ - { \ - result = YY_NULL; \ - } \ - else { \ - memcpy(buf, yyextra->inputptr, result); \ - yyextra->inputptr += result; \ - } \ -} - -#define MAX_STR_LEN 2048 -#define YY_EXTRA_TYPE ssl_expr_info_type* -%} - - -%% - - char caStr[MAX_STR_LEN]; - char *cpStr = NULL; - char caRegex[MAX_STR_LEN]; - char *cpRegex = NULL; - char cRegexDel = NUL; - - /* - * Whitespaces - */ -[ \t\n]+ { - /* NOP */ -} - - /* - * C-style strings ("...") - */ -\" { - cpStr = caStr; - BEGIN(str); -} -<str>\" { - BEGIN(INITIAL); - *cpStr = NUL; - yylval->cpVal = apr_pstrdup(yyextra->pool, caStr); - return T_STRING; -} -<str>\n { - ssl_expr_yyerror(yyextra, "Unterminated string"); -} -<str>\\[0-7]{1,3} { - int result; - - (void)sscanf(yytext+1, "%o", &result); - if (result > 0xff) - ssl_expr_yyerror(yyextra, "Escape sequence out of bound"); - else - *cpStr++ = result; -} -<str>\\[0-9]+ { - ssl_expr_yyerror(yyextra, "Bad escape sequence"); -} -<str>\\n { *cpStr++ = '\n'; } -<str>\\r { *cpStr++ = '\r'; } -<str>\\t { *cpStr++ = '\t'; } -<str>\\b { *cpStr++ = '\b'; } -<str>\\f { *cpStr++ = '\f'; } -<str>\\(.|\n) { - *cpStr++ = yytext[1]; -} -<str>[^\\\n\"]+ { - char *cp = yytext; - while (*cp != NUL) - *cpStr++ = *cp++; -} -<str>. { - *cpStr++ = yytext[1]; -} - - /* - * Regular Expression - */ -"m". { - cRegexDel = yytext[1]; - cpRegex = caRegex; - BEGIN(regex); -} -<regex>.|\n { - if (yytext[0] == cRegexDel) { - *cpRegex = NUL; - BEGIN(regex_flags); - } - else { - *cpRegex++ = yytext[0]; - } -} -<regex_flags>i { - yylval->cpVal = apr_pstrdup(yyextra->pool, caRegex); - BEGIN(INITIAL); - return T_REGEX_I; -} -<regex_flags>.|\n { - yylval->cpVal = apr_pstrdup(yyextra->pool, caRegex); - yyless(0); - BEGIN(INITIAL); - return T_REGEX; -} -<regex_flags><<EOF>> { - yylval->cpVal = apr_pstrdup(yyextra->pool, caRegex); - BEGIN(INITIAL); - return T_REGEX; -} - - /* - * Operators - */ -"eq" { return T_OP_EQ; } -"==" { return T_OP_EQ; } -"ne" { return T_OP_NE; } -"!=" { return T_OP_NE; } -"lt" { return T_OP_LT; } -"<" { return T_OP_LT; } -"le" { return T_OP_LE; } -"<=" { return T_OP_LE; } -"gt" { return T_OP_GT; } -">" { return T_OP_GT; } -"ge" { return T_OP_GE; } -">=" { return T_OP_GE; } -"=~" { return T_OP_REG; } -"!~" { return T_OP_NRE; } -"and" { return T_OP_AND; } -"&&" { return T_OP_AND; } -"or" { return T_OP_OR; } -"||" { return T_OP_OR; } -"not" { return T_OP_NOT; } -"!" { return T_OP_NOT; } -"in" { return T_OP_IN; } -[Pp][Ee][Ee][Rr][Ee][Xx][Tt][Ll][Ii][Ss][Tt] { return T_OP_PEEREXTLIST; } - - /* - * Functions - */ -"file" { return T_FUNC_FILE; } - - /* - * Specials - */ -"true" { return T_TRUE; } -"false" { return T_FALSE; } - - /* - * Digits - */ -[0-9]+ { - yylval->cpVal = apr_pstrdup(yyextra->pool, yytext); - return T_DIGIT; -} - - /* - * Identifiers - */ -[a-zA-Z][a-zA-Z0-9_:-]* { - yylval->cpVal = apr_pstrdup(yyextra->pool, yytext); - return T_ID; -} - - /* - * Anything else is returned as is... - */ -.|\n { - return yytext[0]; -} - -%% - - diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h index 4e8714c732..ae344a141d 100644 --- a/modules/ssl/ssl_private.h +++ b/modules/ssl/ssl_private.h @@ -55,9 +55,38 @@ #define MOD_SSL_VERSION AP_SERVER_BASEREVISION +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE !FALSE +#endif + +#ifndef YY_NULL +#define YY_NULL 0 +#endif + +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + +#ifndef BOOL +#define BOOL unsigned int +#endif + +#ifndef NULL +#define NULL (void *)0 +#endif + +#ifndef NUL +#define NUL '\0' +#endif + + /* mod_ssl headers */ #include "ssl_toolkit_compat.h" -#include "ssl_expr.h" +#include "ap_expr.h" #include "ssl_util_ssl.h" /* The #ifdef macros are only defined AFTER including the above @@ -272,8 +301,8 @@ typedef enum { * Define the SSL requirement structure */ typedef struct { - char *cpExpr; - ssl_expr *mpExpr; + char *cpExpr; + ap_expr_info_t *mpExpr; } ssl_require_t; /** @@ -617,7 +646,6 @@ void ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s); /** Apache authz provisders */ extern const authz_provider ssl_authz_provider_require_ssl; extern const authz_provider ssl_authz_provider_verify_client; -extern const authz_provider ssl_authz_provider_sslrequire; /** OpenSSL callbacks */ RSA *ssl_callback_TmpRSA(SSL *, int, int); diff --git a/server/Makefile.in b/server/Makefile.in index 10b41446a5..98d8ee9be3 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -12,9 +12,10 @@ LTLIBRARY_SOURCES = \ util_script.c util_md5.c util_cfgtree.c util_ebcdic.c util_time.c \ connection.c listen.c util_mutex.c mpm_common.c mpm_unix.c \ util_charset.c util_cookies.c util_debug.c util_xml.c \ - util_expr.c util_filter.c util_pcre.c util_regex.c exports.c \ + util_filter.c util_pcre.c util_regex.c exports.c \ scoreboard.c error_bucket.c protocol.c core.c request.c provider.c \ - eoc_bucket.c eor_bucket.c core_filters.c + eoc_bucket.c eor_bucket.c core_filters.c \ + util_expr_parse.c util_expr_scan.c util_expr_eval.c TARGETS = delete-exports $(LTLIBRARY_NAME) $(CORE_IMPLIB_FILE) export_vars.h httpd.exp @@ -83,3 +84,19 @@ httpd.exp: exports.c export_vars.h @echo "* Please do not edit by hand." >> $@ $(CPP) $(ALL_CPPFLAGS) $(ALL_INCLUDES) exports.c | grep "ap_hack_" | grep -v apr_ | sed -e 's/^.*[)]\(.*\);$$/\1/' >> $@ $(CPP) $(ALL_CPPFLAGS) $(ALL_INCLUDES) export_vars.h | grep -v apr_ | sed -e 's/^\#[^!]*//' | sed -e '/^$$/d' >> $@ + + +# developer stuff +# (we really don't expect end users to use these targets!) +# +util_expr_scan.c util_expr_parse.c util_expr_parse.h: util_expr_scan.l util_expr_parse.y + bison -pap_expr_yy --defines=$(builddir)/util_expr_parse.h \ + -o $(builddir)/util_expr_parse.c $(srcdir)/util_expr_parse.y + flex -Pap_expr_yy -o $(builddir)/util_expr_scan.c $(srcdir)/util_expr_scan.l + set -e ; \ + for f in util_expr_scan.c util_expr_parse.c util_expr_parse.h ; do \ + sed -e "s|\"$(builddir)/|\"|g" < $(builddir)/$$f > \ + $(builddir)/$$f.$$$$ && \ + mv $(builddir)/$$f.$$$$ $(builddir)/$$f ; \ + done + diff --git a/server/core.c b/server/core.c index e01b4b40ec..d41ff648f5 100644 --- a/server/core.c +++ b/server/core.c @@ -1986,7 +1986,7 @@ static const char *ifsection(cmd_parms *cmd, void *mconfig, const char *arg) const char *err = ap_check_cmd_context(cmd, NOT_IN_LOCATION | NOT_IN_LIMIT); const char *condition; - int expr_err = 0; + const char *expr_err; if (err != NULL) { return err; @@ -2012,9 +2012,9 @@ static const char *ifsection(cmd_parms *cmd, void *mconfig, const char *arg) conf = ap_set_config_vectors(cmd->server, new_file_conf, cmd->path, &core_module, cmd->pool); - conf->condition = ap_expr_parse(cmd->pool, condition, &expr_err); + conf->condition = ap_expr_parse_cmd(cmd, condition, &expr_err, NULL); if (expr_err) { - return "Cannot parse condition clause"; + return apr_psprintf(cmd->pool, "Cannot parse condition clause: %s", expr_err); } errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_file_conf); @@ -4133,6 +4133,7 @@ static void register_hooks(apr_pool_t *p) { errorlog_hash = apr_hash_make(p); ap_register_log_hooks(p); + ap_expr_init(p); /* create_connection and pre_connection should always be hooked * APR_HOOK_REALLY_LAST by core to give other modules the opportunity diff --git a/server/main.c b/server/main.c index 1943371693..3ea53d4bb4 100644 --- a/server/main.c +++ b/server/main.c @@ -39,7 +39,6 @@ #include "apr_uri.h" #include "util_ebcdic.h" #include "ap_mpm.h" -#include "ap_expr.h" #if APR_HAVE_UNISTD_H #include <unistd.h> @@ -472,9 +471,6 @@ int main(int argc, const char * const argv[]) destroy_and_exit_process(process, 1); } #endif - if (ap_expr_init(ap_pglobal) != APR_SUCCESS) { - destroy_and_exit_process(process, 1); - } apr_pool_create(&pcommands, ap_pglobal); apr_pool_tag(pcommands, "pcommands"); diff --git a/server/request.c b/server/request.c index 2779c8de47..f516617b8a 100644 --- a/server/request.c +++ b/server/request.c @@ -1529,13 +1529,13 @@ AP_DECLARE(int) ap_file_walk(request_rec *r) * really try them with the most general first. */ for (sec_idx = 0; sec_idx < num_sec; ++sec_idx) { - int err = 0; + const char *err = NULL; core_dir_config *entry_core; entry_core = ap_get_module_config(sec_ent[sec_idx], &core_module); if (entry_core->condition) { - if (!ap_expr_eval(r, entry_core->condition, &err, NULL, - ap_expr_string, NULL)) { + /* XXX: error handling */ + if (!ap_expr_exec(r, entry_core->condition, &err)) { continue; } } diff --git a/server/util_expr.c b/server/util_expr.c deleted file mode 100644 index d6f81944d4..0000000000 --- a/server/util_expr.c +++ /dev/null @@ -1,1282 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "apr.h" -#include "apr_strings.h" -#include "apr_lib.h" - -#define APR_WANT_STRFUNC -#define APR_WANT_MEMFUNC -#include "apr_want.h" - -#include "httpd.h" -#include "http_log.h" -#include "http_core.h" - -#include "ap_expr.h" - -APLOG_USE_MODULE(core); - -#if 1 -/* - * +-------------------------------------------------------+ - * | | - * | Debugging Utilities - * | | - * +-------------------------------------------------------+ - */ - -#ifdef DEBUG_INCLUDE - -#define TYPE_TOKEN(token, ttype) do { \ - (token)->type = ttype; \ - (token)->s = #ttype; \ -} while(0) - -#define CREATE_NODE(pool,name) do { \ - (name) = apr_pcalloc(pool, sizeof(*(name))); \ -} while(0) - -static void debug_printf(request_rec *r, const char *fmt, ...) -{ - va_list ap; - char *debug__str; - - va_start(ap, fmt); - debug__str = apr_pvsprintf(r->pool, fmt, ap); - va_end(ap); -/* - APR_BRIGADE_INSERT_TAIL(ctx->intern->debug.bb, apr_bucket_pool_create( - debug__str, strlen(debug__str), ctx->pool, - ctx->intern->debug.f->c->bucket_alloc)); - */ -} - -#define DUMP__CHILD(ctx, is, node, child) if (1) { \ - ap_parse_node_t *d__c = node->child; \ - if (d__c) { \ - if (!d__c->dump_done) { \ - if (d__c->parent != node) { \ - debug_printf(ctx, "!!! Parse tree is not consistent !!!\n"); \ - if (!d__c->parent) { \ - debug_printf(ctx, "Parent of " #child " child node is " \ - "NULL.\n"); \ - } \ - else { \ - debug_printf(ctx, "Parent of " #child " child node " \ - "points to another node (of type %s)!\n", \ - d__c->parent->token.s); \ - } \ - return; \ - } \ - node = d__c; \ - continue; \ - } \ - } \ - else { \ - debug_printf(ctx, "%s(missing)\n", is); \ - } \ -} - -static void debug_dump_tree(include_ctx_t *ctx, ap_parse_node_t *root) -{ - ap_parse_node_t *current; - char *is; - - if (!root) { - debug_printf(ctx, " -- Parse Tree empty --\n\n"); - return; - } - - debug_printf(ctx, " ----- Parse Tree -----\n"); - current = root; - is = " "; - - while (current) { - switch (current->token.type) { - case TOKEN_STRING: - case TOKEN_RE: - debug_printf(ctx, "%s%s (%s)\n", is, current->token.s, - current->token.value); - current->dump_done = 1; - current = current->parent; - continue; - - case TOKEN_NOT: - case TOKEN_GROUP: - case TOKEN_RBRACE: - case TOKEN_LBRACE: - if (!current->dump_done) { - debug_printf(ctx, "%s%s\n", is, current->token.s); - is = apr_pstrcat(ctx->dpool, is, " ", NULL); - current->dump_done = 1; - } - - DUMP__CHILD(ctx, is, current, right) - - if (!current->right || current->right->dump_done) { - is = apr_pstrmemdup(ctx->dpool, is, strlen(is) - 4); - if (current->right) current->right->dump_done = 0; - current = current->parent; - } - continue; - - default: - if (!current->dump_done) { - debug_printf(ctx, "%s%s\n", is, current->token.s); - is = apr_pstrcat(ctx->dpool, is, " ", NULL); - current->dump_done = 1; - } - - DUMP__CHILD(ctx, is, current, left) - DUMP__CHILD(ctx, is, current, right) - - if ((!current->left || current->left->dump_done) && - (!current->right || current->right->dump_done)) { - - is = apr_pstrmemdup(ctx->dpool, is, strlen(is) - 4); - if (current->left) current->left->dump_done = 0; - if (current->right) current->right->dump_done = 0; - current = current->parent; - } - continue; - } - } - - /* it is possible to call this function within the parser loop, to see - * how the tree is built. That way, we must cleanup after us to dump - * always the whole tree - */ - root->dump_done = 0; - if (root->left) root->left->dump_done = 0; - if (root->right) root->right->dump_done = 0; - - debug_printf(ctx, " --- End Parse Tree ---\n\n"); - - return; -} - -#define DEBUG_INIT(ctx, filter, brigade) do { \ - (ctx)->intern->debug.f = filter; \ - (ctx)->intern->debug.bb = brigade; \ -} while(0) - -#define DEBUG_PRINTF(arg) debug_printf arg - -#define DEBUG_DUMP_TOKEN(ctx, token) do { \ - token_t *d__t = (token); \ - \ - if (d__t->type == TOKEN_STRING || d__t->type == TOKEN_RE) { \ - DEBUG_PRINTF(((ctx), " Found: %s (%s)\n", d__t->s, d__t->value)); \ - } \ - else { \ - DEBUG_PRINTF((ctx, " Found: %s\n", d__t->s)); \ - } \ -} while(0) - -#define DEBUG_DUMP_EVAL(r, node) do { \ - char c = '"'; \ - switch ((node)->token.type) { \ - case TOKEN_STRING: \ - debug_printf((r), " Evaluate: %s (%s) -> %c\n", (node)->token.s,\ - (node)->token.value, ((node)->value) ? '1':'0'); \ - break; \ - case TOKEN_AND: \ - case TOKEN_OR: \ - debug_printf((r), " Evaluate: %s (Left: %s; Right: %s) -> %c\n",\ - (node)->token.s, \ - (((node)->left->done) ? ((node)->left->value ?"1":"0") \ - : "short circuited"), \ - (((node)->right->done) ? ((node)->right->value?"1":"0") \ - : "short circuited"), \ - (node)->value ? '1' : '0'); \ - break; \ - case TOKEN_EQ: \ - case TOKEN_NE: \ - case TOKEN_GT: \ - case TOKEN_GE: \ - case TOKEN_LT: \ - case TOKEN_LE: \ - if ((node)->right->token.type == TOKEN_RE) c = '/'; \ - debug_printf((r), " Compare: %s (\"%s\" with %c%s%c) -> %c\n", \ - (node)->token.s, \ - (node)->left->token.value, \ - c, (node)->right->token.value, c, \ - (node)->value ? '1' : '0'); \ - break; \ - default: \ - debug_printf((r), " Evaluate: %s -> %c\n", (node)->token.s, \ - (node)->value ? '1' : '0'); \ - break; \ - } \ -} while(0) - -#define DEBUG_DUMP_UNMATCHED(r, unmatched) do { \ - if (unmatched) { \ - DEBUG_PRINTF(((r), " Unmatched %c\n", (char)(unmatched))); \ - } \ -} while(0) - -#define DEBUG_DUMP_COND(ctx, text) \ - DEBUG_PRINTF(((ctx), "**** %s cond status=\"%c\"\n", (text), \ - ((ctx)->flags & SSI_FLAG_COND_TRUE) ? '1' : '0')) - -#define DEBUG_DUMP_TREE(ctx, root) debug_dump_tree(ctx, root) - -#else /* DEBUG_INCLUDE */ - -#define TYPE_TOKEN(token, ttype) (token)->type = ttype - -#define CREATE_NODE(pool,name) do { \ - (name) = apr_pcalloc(pool, sizeof(*(name))); \ -} while(0) - -#define DEBUG_INIT(ctx, f, bb) -#define DEBUG_PRINTF(arg) -#define DEBUG_DUMP_TOKEN(ctx, token) -#define DEBUG_DUMP_EVAL(ctx, node) -#define DEBUG_DUMP_UNMATCHED(ctx, unmatched) -#define DEBUG_DUMP_COND(ctx, text) -#define DEBUG_DUMP_TREE(ctx, root) - -#endif /* !DEBUG_INCLUDE */ - -#endif /* 0 */ - - -/* - * +-------------------------------------------------------+ - * | | - * | Conditional Expression Parser - * | | - * +-------------------------------------------------------+ - */ -static APR_INLINE int re_check(request_rec *r, const char *string, - const char *rexp, backref_t **reptr) -{ - ap_regex_t *compiled; - backref_t *re = reptr ? *reptr : NULL; - - compiled = ap_pregcomp(r->pool, rexp, AP_REG_EXTENDED); - if (!compiled) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "unable to " - "compile pattern \"%s\"", rexp); - return -1; - } - - if (!re) { - re = apr_palloc(r->pool, sizeof(*re)); - if (reptr) { - *reptr = re; - } - } - - re->source = apr_pstrdup(r->pool, string); - re->rexp = apr_pstrdup(r->pool, rexp); - re->nsub = compiled->re_nsub; - re->have_match = !ap_regexec(compiled, string, AP_MAX_REG_MATCH, - re->match, 0); - - ap_pregfree(r->pool, compiled); - return re->have_match; -} - -static int get_ptoken(apr_pool_t *pool, const char **parse, token_t *token, - token_t *previous) -{ - const char *p; - apr_size_t shift; - int unmatched; - - token->value = NULL; - - if (!*parse) { - return 0; - } - - /* Skip leading white space */ - while (apr_isspace(**parse)) { - ++*parse; - } - - if (!**parse) { - *parse = NULL; - return 0; - } - - TYPE_TOKEN(token, TOKEN_STRING); /* the default type */ - p = *parse; - unmatched = 0; - - switch (*(*parse)++) { - case '(': - TYPE_TOKEN(token, TOKEN_LBRACE); - return 0; - case ')': - TYPE_TOKEN(token, TOKEN_RBRACE); - return 0; - case '=': - if (**parse == '=') ++*parse; - TYPE_TOKEN(token, TOKEN_EQ); - return 0; - case '!': - if (**parse == '=') { - TYPE_TOKEN(token, TOKEN_NE); - ++*parse; - return 0; - } - TYPE_TOKEN(token, TOKEN_NOT); - return 0; - case '\'': - unmatched = '\''; - break; - case '/': - /* if last token was ACCESS, this token is STRING */ - if (previous != NULL && TOKEN_ACCESS == previous->type) { - break; - } - TYPE_TOKEN(token, TOKEN_RE); - unmatched = '/'; - break; - case '|': - if (**parse == '|') { - TYPE_TOKEN(token, TOKEN_OR); - ++*parse; - return 0; - } - break; - case '&': - if (**parse == '&') { - TYPE_TOKEN(token, TOKEN_AND); - ++*parse; - return 0; - } - break; - case '>': - if (**parse == '=') { - TYPE_TOKEN(token, TOKEN_GE); - ++*parse; - return 0; - } - TYPE_TOKEN(token, TOKEN_GT); - return 0; - case '<': - if (**parse == '=') { - TYPE_TOKEN(token, TOKEN_LE); - ++*parse; - return 0; - } - TYPE_TOKEN(token, TOKEN_LT); - return 0; - case '-': - if (apr_isalnum(**parse) && apr_isspace((*parse)[1])) { - TYPE_TOKEN(token, TOKEN_ACCESS); - token->value = *parse; - ++*parse; - return 0; - } - break; - case 'I': - if (**parse == 'N') { - TYPE_TOKEN(token, TOKEN_IN); - ++*parse; - return 0; - } - break; - } - - /* It's a string or regex token - * Now search for the next token, which finishes this string - */ - shift = 0; - p = *parse = token->value = unmatched ? *parse : p; - - for (; **parse; p = ++*parse) { - if (**parse == '\\') { - if (!*(++*parse)) { - p = *parse; - break; - } - - ++shift; - } - else { - if (unmatched) { - if (**parse == unmatched) { - unmatched = 0; - ++*parse; - break; - } - } - else if (apr_isspace(**parse)) { - break; - } - else { - int found = 0; - - switch (**parse) { - case '(': - case ')': - case '=': - case '!': - case '<': - case '>': - ++found; - break; - - case '|': - case '&': - if ((*parse)[1] == **parse) { - ++found; - } - break; - } - - if (found) { - break; - } - } - } - } - - if (unmatched) { - token->value = apr_pstrdup(pool, ""); - } - else { - apr_size_t len = p - token->value - shift; - char *c = apr_palloc(pool, len + 1); - - p = token->value; - token->value = c; - - while (shift--) { - const char *e = ap_strchr_c(p, '\\'); - - memcpy(c, p, e-p); - c += e-p; - *c++ = *++e; - len -= e-p; - p = e+1; - } - - if (len) { - memcpy(c, p, len); - } - c[len] = '\0'; - } - - return unmatched; -} - -/* This is what we export. We can split it in two. */ -AP_DECLARE(ap_parse_node_t*) ap_expr_parse(apr_pool_t* pool, const char *expr, - int *was_error) -{ - ap_parse_node_t *new, *root = NULL, *current = NULL; - const char *error = "Invalid expression \"%s\" in file %s"; - const char *parse = expr; - int was_unmatched = 0; - unsigned regex = 0; - - *was_error = 0; - - if (!parse) { - return 0; - } - - /* Create Parse Tree */ - while (1) { - /* uncomment this to see how the tree a built: - * - * DEBUG_DUMP_TREE(ctx, root); - */ - CREATE_NODE(pool, new); - - was_unmatched = get_ptoken(pool, &parse, &new->token, - (current != NULL ? ¤t->token : NULL)); - if (!parse) { - break; - } - - DEBUG_DUMP_UNMATCHED(ctx, was_unmatched); - DEBUG_DUMP_TOKEN(ctx, &new->token); - - if (!current) { - switch (new->token.type) { - case TOKEN_STRING: - case TOKEN_NOT: - case TOKEN_ACCESS: - case TOKEN_LBRACE: - root = current = new; - continue; - - default: - *was_error = 1; - return 0; - } - } - - switch (new->token.type) { - case TOKEN_STRING: - switch (current->token.type) { - case TOKEN_STRING: - current->token.value = - apr_pstrcat(pool, current->token.value, - *current->token.value ? " " : "", - new->token.value, NULL); - continue; - - case TOKEN_RE: - case TOKEN_RBRACE: - case TOKEN_GROUP: - break; - - default: - new->parent = current; - current = current->right = new; - continue; - } - break; - - case TOKEN_RE: - switch (current->token.type) { - case TOKEN_EQ: - case TOKEN_NE: - new->parent = current; - current = current->right = new; - ++regex; - continue; - - default: - break; - } - break; - - case TOKEN_AND: - case TOKEN_OR: - switch (current->token.type) { - case TOKEN_STRING: - case TOKEN_RE: - case TOKEN_GROUP: - current = current->parent; - - while (current) { - switch (current->token.type) { - case TOKEN_AND: - case TOKEN_OR: - case TOKEN_LBRACE: - break; - - default: - current = current->parent; - continue; - } - break; - } - - if (!current) { - new->left = root; - root->parent = new; - current = root = new; - continue; - } - - new->left = current->right; - new->left->parent = new; - new->parent = current; - current = current->right = new; - continue; - - default: - break; - } - break; - - case TOKEN_EQ: - case TOKEN_NE: - case TOKEN_GE: - case TOKEN_GT: - case TOKEN_LE: - case TOKEN_LT: - case TOKEN_IN: - if (current->token.type == TOKEN_STRING) { - current = current->parent; - - if (!current) { - new->left = root; - root->parent = new; - current = root = new; - continue; - } - - switch (current->token.type) { - case TOKEN_LBRACE: - case TOKEN_AND: - case TOKEN_OR: - new->left = current->right; - new->left->parent = new; - new->parent = current; - current = current->right = new; - continue; - - default: - break; - } - } - break; - - case TOKEN_RBRACE: - while (current && current->token.type != TOKEN_LBRACE) { - current = current->parent; - } - - if (current) { - TYPE_TOKEN(¤t->token, TOKEN_GROUP); - continue; - } - - error = "Unmatched ')' in \"%s\" in file %s"; - break; - - case TOKEN_NOT: - case TOKEN_ACCESS: - case TOKEN_LBRACE: - switch (current->token.type) { - case TOKEN_STRING: - case TOKEN_RE: - case TOKEN_RBRACE: - case TOKEN_GROUP: - break; - - default: - current->right = new; - new->parent = current; - current = new; - continue; - } - break; - - default: - break; - } - - *was_error = 1; - return 0; - } - - DEBUG_DUMP_TREE(ctx, root); - return root; -} - -static ap_parse_node_t *ap_expr_clone_tree(apr_pool_t *pool, - const ap_parse_node_t *pnode, - ap_parse_node_t *parent) -{ - ap_parse_node_t *ret; - ret = apr_pmemdup(pool, pnode, sizeof(ap_parse_node_t)); - if (pnode->left) { - ret->left = ap_expr_clone_tree(pool, pnode->left, ret); - } - if (pnode->right) { - ret->right = ap_expr_clone_tree(pool, pnode->right, ret); - } - ret->parent = parent; - return ret; -} - -#define PARSE_STRING(r,s) (string_func ? string_func((r),(s)) : (s)) -static int expr_eval(request_rec *r, ap_parse_node_t *root, - int *was_error, backref_t **reptr, - string_func_t string_func, opt_func_t eval_func) -{ - ap_parse_node_t *current = root; - const char *error = NULL; - unsigned int regex = 0; - const char *val; - const char *lval; - const char *rval; - - /* Evaluate Parse Tree */ - while (current) { - switch (current->token.type) { - case TOKEN_STRING: - val = PARSE_STRING(r, current->token.value); - current->value = !!*val; - break; - - case TOKEN_AND: - case TOKEN_OR: - if (!current->left || !current->right) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "Invalid expression in file %s", r->filename); - *was_error = 1; - return 0; - } - - if (!current->left->done) { - switch (current->left->token.type) { - case TOKEN_STRING: - lval = PARSE_STRING(r, current->left->token.value); - current->left->value = !!*lval; - DEBUG_DUMP_EVAL(ctx, current->left); - current->left->done = 1; - break; - - default: - current = current->left; - continue; - } - } - - /* short circuit evaluation */ - if (!current->right->done && !regex && - ((current->token.type == TOKEN_AND && !current->left->value) || - (current->token.type == TOKEN_OR && current->left->value))) { - current->value = current->left->value; - } - else { - if (!current->right->done) { - switch (current->right->token.type) { - case TOKEN_STRING: - rval = PARSE_STRING(r,current->right->token.value); - current->right->value = !!*rval; - DEBUG_DUMP_EVAL(r, current->right); - current->right->done = 1; - break; - - default: - current = current->right; - continue; - } - } - - if (current->token.type == TOKEN_AND) { - current->value = current->left->value && - current->right->value; - } - else { - current->value = current->left->value || - current->right->value; - } - } - break; - - case TOKEN_EQ: - case TOKEN_NE: - if (!current->left || !current->right || - current->left->token.type != TOKEN_STRING || - (current->right->token.type != TOKEN_STRING && - current->right->token.type != TOKEN_RE)) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "Invalid expression in file %s", r->filename); - *was_error = 1; - return 0; - } - lval = PARSE_STRING(r, current->left->token.value); - rval = PARSE_STRING(r, current->right->token.value); - - if (current->right->token.type == TOKEN_RE) { - current->value = re_check(r, lval, rval, reptr); - --regex; - } - else { - current->value = !strcmp(lval, rval); - } - - if (current->token.type == TOKEN_NE) { - current->value = !current->value; - } - break; - - case TOKEN_GE: - case TOKEN_GT: - case TOKEN_LE: - case TOKEN_LT: - if (!current->left || !current->right || - current->left->token.type != TOKEN_STRING || - current->right->token.type != TOKEN_STRING) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "Invalid expression in file %s", r->filename); - *was_error = 1; - return 0; - } - - lval = PARSE_STRING(r, current->left->token.value); - rval = PARSE_STRING(r, current->right->token.value); - - current->value = strcmp(lval, rval); - - switch (current->token.type) { - case TOKEN_GE: current->value = current->value >= 0; break; - case TOKEN_GT: current->value = current->value > 0; break; - case TOKEN_LE: current->value = current->value <= 0; break; - case TOKEN_LT: current->value = current->value < 0; break; - default: current->value = 0; break; /* should not happen */ - } - break; - case TOKEN_IN: - if (!current->left || !current->right || - current->left->token.type != TOKEN_STRING || - current->right->token.type != TOKEN_STRING) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "Invalid expression in file %s", r->filename); - *was_error = 1; - return 0; - } - - lval = PARSE_STRING(r, current->left->token.value); - rval = PARSE_STRING(r, current->right->token.value); - val = ap_strstr_c(rval, lval); - /* should be included as a complete word, not a subword - * as in regexp /\bLVAL\b/ - */ - current->value = (val != NULL - && (val == rval || !isalnum(val[-1])) - && !isalnum(val[strlen(val)])) - ? 1 : 0; - break; - - case TOKEN_NOT: - case TOKEN_GROUP: - if (current->right) { - if (!current->right->done) { - current = current->right; - continue; - } - current->value = current->right->value; - } - else { - current->value = 1; - } - - if (current->token.type == TOKEN_NOT) { - current->value = !current->value; - } - break; - case TOKEN_ACCESS: - if (eval_func) { - *was_error = eval_func(r, current, string_func); - if (*was_error) { - return 0; - } - } - break; - - case TOKEN_RE: - if (!error) { - error = "No operator before regex in file %s"; - } - case TOKEN_LBRACE: - if (!error) { - error = "Unmatched '(' in file %s"; - } - default: - if (!error) { - error = "internal parser error in file %s"; - } - - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, error, r->filename); - *was_error = 1; - return 0; - } - - DEBUG_DUMP_EVAL(r, current); - current->done = 1; - current = current->parent; - } - - return (root ? root->value : 0); -} -AP_DECLARE(int) ap_expr_eval(request_rec *r, const ap_parse_node_t *root, - int *was_error, backref_t **reptr, - string_func_t string_func, opt_func_t eval_func) -{ - ap_parse_node_t *clone; - if (root == NULL) { /* no condition == unconditional */ - return 1; - } - clone = ap_expr_clone_tree(r->pool, root, NULL); - return expr_eval(r, clone, was_error, reptr, string_func, eval_func); -} -AP_DECLARE(int) ap_expr_evalstring(request_rec *r, const char *expr, - int *was_error, backref_t **reptr, - string_func_t string_func, - opt_func_t eval_func) -{ - ap_parse_node_t *root = ap_expr_parse(r->pool, expr, was_error); - if (*was_error || !root) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "Error parsing expression in %s", r->filename); - return 0; - } - return expr_eval(r, root, was_error, reptr, string_func, eval_func); -} - - -static ap_regex_t *isvar = NULL; -AP_DECLARE_NONSTD(const char*) ap_expr_string(request_rec *r, - const char *str) -{ - /* a default string evaluator: support headers and env */ - const char *ret = str; - ap_regmatch_t match[3]; - const char *p; - - ap_assert(isvar != NULL); - if (ap_regexec(isvar, str, 3, match, 0) == 0) { - apr_table_t *table = NULL; - int len = match[1].rm_eo-match[1].rm_so; - const char *name = str+match[1].rm_so; - if (!strncasecmp("req", name, len)) { - table = r->headers_in; - } - else if (!strncasecmp("resp", name, len)) { - table = r->headers_out; - } - else if (!strncasecmp("env", name, len)) { - table = r->subprocess_env; - } - if (table != NULL) { - char *key = apr_pstrndup(r->pool, str+match[2].rm_so, - match[2].rm_eo-match[2].rm_so); - ret = apr_table_get(table, key); - } - } - else if (str[0] == '$') { - if (!strcasecmp(str, "$handler")) { - ret = r->handler; - } - else if (!strcasecmp(str, "$content-type")) { - ret = r->content_type; - } - } - - /* copy wholesale from mod_rewrite to support its %{varname} vars */ - else if ((str[0] == '%') && (str[1] == '{') - && (p = ap_strchr_c(str, '}'), p != NULL)) { - char *ch, *var; - apr_time_exp_t tm; - - var = apr_pstrndup(r->pool, str+2, p-str-2); - for (ch = var; *ch; ++ch) { - *ch = apr_toupper(*ch); - } - - switch (strlen(var)) { - case 4: - if (!strcmp(var, "TIME")) { - apr_time_exp_lt(&tm, apr_time_now()); - ret = apr_psprintf(r->pool, "%04d%02d%02d%02d%02d%02d", - tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); - return (char *)ret; - } - else if (!strcmp(var, "IPV6")) { - int flag = FALSE; -#if APR_HAVE_IPV6 - apr_sockaddr_t *addr = r->connection->remote_addr; - flag = (addr->family == AF_INET6 && - !IN6_IS_ADDR_V4MAPPED((struct in6_addr *)addr->ipaddr_ptr)); -#endif - ret = (flag ? "on" : "off"); - } - break; - -#if FIXME - case 5: - if (!strcmp(var, "HTTPS")) { - int flag = rewrite_is_https && rewrite_is_https(r->connection); - return apr_pstrdup(r->pool, flag ? "on" : "off"); - } - break; -#endif - case 8: - switch (var[6]) { - case 'A': - if (!strcmp(var, "TIME_DAY")) { - apr_time_exp_lt(&tm, apr_time_now()); - return apr_psprintf(r->pool, "%02d", tm.tm_mday); - } - break; - - case 'E': - if (!strcmp(var, "TIME_SEC")) { - apr_time_exp_lt(&tm, apr_time_now()); - return apr_psprintf(r->pool, "%02d", tm.tm_sec); - } - break; - - case 'I': - if (!strcmp(var, "TIME_MIN")) { - apr_time_exp_lt(&tm, apr_time_now()); - return apr_psprintf(r->pool, "%02d", tm.tm_min); - } - break; - - case 'O': - if (!strcmp(var, "TIME_MON")) { - apr_time_exp_lt(&tm, apr_time_now()); - return apr_psprintf(r->pool, "%02d", tm.tm_mon+1); - } - break; - } - break; - - case 9: - switch (var[7]) { - case 'A': - if (var[8] == 'Y' && !strcmp(var, "TIME_WDAY")) { - apr_time_exp_lt(&tm, apr_time_now()); - return apr_psprintf(r->pool, "%d", tm.tm_wday); - } - else if (!strcmp(var, "TIME_YEAR")) { - apr_time_exp_lt(&tm, apr_time_now()); - return apr_psprintf(r->pool, "%04d", tm.tm_year+1900); - } - break; - - case 'E': - if (!strcmp(var, "IS_SUBREQ")) { - ret = (r->main ? "true" : "false"); - } - break; - - case 'F': - if (!strcmp(var, "PATH_INFO")) { - ret = r->path_info; - } - break; - - case 'P': - if (!strcmp(var, "AUTH_TYPE")) { - ret = r->ap_auth_type; - } - break; - - case 'S': - if (!strcmp(var, "HTTP_HOST")) { - ret = apr_table_get(r->headers_in, "Host"); - } - break; - - case 'U': - if (!strcmp(var, "TIME_HOUR")) { - apr_time_exp_lt(&tm, apr_time_now()); - return apr_psprintf(r->pool, "%02d", tm.tm_hour); - } - break; - } - break; - - case 11: - switch (var[8]) { - case 'A': - if (!strcmp(var, "SERVER_NAME")) { - ret = ap_get_server_name(r); - } - break; - - case 'D': - if (*var == 'R' && !strcmp(var, "REMOTE_ADDR")) { - ret = r->connection->remote_ip; - } - else if (!strcmp(var, "SERVER_ADDR")) { - ret = r->connection->local_ip; - } - break; - - case 'E': - if (*var == 'H' && !strcmp(var, "HTTP_ACCEPT")) { - ret = apr_table_get(r->headers_in, "Accept"); - } - else if (!strcmp(var, "THE_REQUEST")) { - ret = r->the_request; - } - break; - - case 'I': - if (!strcmp(var, "API_VERSION")) { - return apr_psprintf(r->pool, "%d:%d", - MODULE_MAGIC_NUMBER_MAJOR, - MODULE_MAGIC_NUMBER_MINOR); - } - break; - - case 'K': - if (!strcmp(var, "HTTP_COOKIE")) { - ret = apr_table_get(r->headers_in, "Cookie"); - } - break; - - case 'O': - if (*var == 'S' && !strcmp(var, "SERVER_PORT")) { - return apr_psprintf(r->pool, "%u", ap_get_server_port(r)); - } - else if (var[7] == 'H' && !strcmp(var, "REMOTE_HOST")) { - ret = ap_get_remote_host(r->connection,r->per_dir_config, - REMOTE_NAME, NULL); - } - else if (!strcmp(var, "REMOTE_PORT")) { - return apr_itoa(r->pool, r->connection->remote_addr->port); - } - break; - - case 'S': - if (*var == 'R' && !strcmp(var, "REMOTE_USER")) { - ret = r->user; - } - else if (!strcmp(var, "SCRIPT_USER")) { - ret = "<unknown>"; - if (r->finfo.valid & APR_FINFO_USER) { - apr_uid_name_get((char **)&ret, r->finfo.user, - r->pool); - } - } - break; - - case 'U': - if (!strcmp(var, "REQUEST_URI")) { - ret = r->uri; - } - break; - } - break; - - case 12: - switch (var[3]) { - case 'I': - if (!strcmp(var, "SCRIPT_GROUP")) { - ret = "<unknown>"; - if (r->finfo.valid & APR_FINFO_GROUP) { - apr_gid_name_get((char **)&ret, r->finfo.group, - r->pool); - } - } - break; - - case 'O': - if (!strcmp(var, "REMOTE_IDENT")) { - ret = ap_get_remote_logname(r); - } - break; - - case 'P': - if (!strcmp(var, "HTTP_REFERER")) { - ret = apr_table_get(r->headers_in, "Referer"); - } - break; - - case 'R': - if (!strcmp(var, "QUERY_STRING")) { - ret = r->args; - } - break; - - case 'V': - if (!strcmp(var, "SERVER_ADMIN")) { - ret = r->server->server_admin; - } - break; - } - break; - - case 13: - if (!strcmp(var, "DOCUMENT_ROOT")) { - ret = ap_document_root(r); - } - break; - - case 14: - if (*var == 'H' && !strcmp(var, "HTTP_FORWARDED")) { - ret = apr_table_get(r->headers_in, "Forwarded"); - } - else if (!strcmp(var, "REQUEST_METHOD")) { - ret = r->method; - } - break; - - case 15: - switch (var[7]) { - case 'E': - if (!strcmp(var, "HTTP_USER_AGENT")) { - ret = apr_table_get(r->headers_in, "User-Agent"); - } - break; - - case 'F': - if (!strcmp(var, "SCRIPT_FILENAME")) { - ret = r->filename; /* same as request_filename (16) */ - } - break; - - case 'P': - if (!strcmp(var, "SERVER_PROTOCOL")) { - ret = r->protocol; - } - break; - - case 'S': - if (!strcmp(var, "SERVER_SOFTWARE")) { - ret = ap_get_server_banner(); - } - break; - } - break; - - case 16: - if (!strcmp(var, "REQUEST_FILENAME")) { - ret = r->filename; /* same as script_filename (15) */ - } - break; - - case 21: - if (!strcmp(var, "HTTP_PROXY_CONNECTION")) { - ret = apr_table_get(r->headers_in, "Proxy-Connection"); - } - break; - } - } - - /* TODO: provide a hook so modules can interpret other patterns */ - /* OhBugger, where's the regexp for backreferences ? */ - if (!ret) { - ret = ""; - } - return ret; /* default - literal string as-is */ -} -static apr_status_t ap_expr_term(void *expr) -{ - if (isvar) { - ap_regfree(isvar); - isvar = NULL; - } - return APR_SUCCESS; -} -AP_DECLARE(apr_status_t) ap_expr_init(apr_pool_t *pool) -{ - static ap_regex_t var; - if (!isvar) { - isvar = &var; - if (ap_regcomp(isvar, "\\$([A-Za-z0-9]+)\\{([^\\}]+)\\}", 0)) { - isvar = NULL; - } - else { - apr_pool_cleanup_register(pool, isvar, ap_expr_term, - apr_pool_cleanup_null); - } - } - return isvar ? APR_SUCCESS : APR_EGENERAL; -} diff --git a/server/util_expr_eval.c b/server/util_expr_eval.c new file mode 100644 index 0000000000..8a74621f5c --- /dev/null +++ b/server/util_expr_eval.c @@ -0,0 +1,1024 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* _ _ + * ap_expr_eval.c, based on ssl_expr_eval.c from mod_ssl + */ + +#include "httpd.h" +#include "http_log.h" +#include "http_core.h" +#include "http_protocol.h" +#include "ap_provider.h" +#include "util_expr_private.h" + +#include "apr_lib.h" + +APLOG_USE_MODULE(core); + +APR_HOOK_STRUCT( + APR_HOOK_LINK(expr_lookup) +) + +AP_IMPLEMENT_HOOK_RUN_FIRST(int, expr_lookup, (ap_expr_lookup_parms *parms), + (parms), DECLINED) + +static const char *ap_expr_eval_string_func(ap_expr_eval_ctx *ctx, const ap_expr *info, + const ap_expr *args); +static const char *ap_expr_eval_var(ap_expr_eval_ctx *ctx, + const ap_expr_var_func_t *func, + const void *data); +static void expr_dump_tree(const ap_expr *e, const server_rec *s, int loglevel, int indent); + +static const char *ap_expr_eval_word(ap_expr_eval_ctx *ctx, const ap_expr *node) +{ + const char *result = ""; + switch (node->node_op) { + case op_Digit: + result = node->node_arg1; + break; + case op_String: + result = node->node_arg1; + break; + case op_Var: + result = ap_expr_eval_var(ctx, node->node_arg1, node->node_arg2); + break; + case op_StringFuncCall: { + const ap_expr *info = node->node_arg1; + const ap_expr *args = node->node_arg2; + result = ap_expr_eval_string_func(ctx, info, args); + break; + } + default: + *ctx->err = "Internal evaluation error: Unknown expression node"; + break; + } + if (!result) + result = ""; + return result; +} + +static const char *ap_expr_eval_var(ap_expr_eval_ctx *ctx, + const ap_expr_var_func_t *func, + const void *data) +{ + AP_DEBUG_ASSERT(func != NULL); + AP_DEBUG_ASSERT(data != NULL); + return (*func)(ctx, data); +} + +static const char *ap_expr_eval_string_func(ap_expr_eval_ctx *ctx, const ap_expr *info, + const ap_expr *arg) +{ + ap_expr_string_func_t *func = info->node_arg1; + const void *data = info->node_arg2; + + AP_DEBUG_ASSERT(info->node_op == op_StringFuncInfo); + AP_DEBUG_ASSERT(func != NULL); + AP_DEBUG_ASSERT(data != NULL); + return (*func)(ctx, data, ap_expr_eval_word(ctx, arg)); +} + +static int intstrcmp(const char *s1, const char *s2) +{ + apr_int64_t i1 = apr_atoi64(s1); + apr_int64_t i2 = apr_atoi64(s2); + + if (i1 < i2) + return -1; + else if (i1 == i2) + return 0; + else + return 1; +} + +static int ap_expr_eval_comp(ap_expr_eval_ctx *ctx, const ap_expr *node) +{ + switch (node->node_op) { + case op_EQ: { + const ap_expr *e1 = node->node_arg1; + const ap_expr *e2 = node->node_arg2; + return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) == 0); + } + case op_NE: { + const ap_expr *e1 = node->node_arg1; + const ap_expr *e2 = node->node_arg2; + return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) != 0); + } + case op_LT: { + const ap_expr *e1 = node->node_arg1; + const ap_expr *e2 = node->node_arg2; + return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) < 0); + } + case op_LE: { + const ap_expr *e1 = node->node_arg1; + const ap_expr *e2 = node->node_arg2; + return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <= 0); + } + case op_GT: { + const ap_expr *e1 = node->node_arg1; + const ap_expr *e2 = node->node_arg2; + return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) > 0); + } + case op_GE: { + const ap_expr *e1 = node->node_arg1; + const ap_expr *e2 = node->node_arg2; + return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >= 0); + } + case op_STR_EQ: { + const ap_expr *e1 = node->node_arg1; + const ap_expr *e2 = node->node_arg2; + return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) == 0); + } + case op_STR_NE: { + const ap_expr *e1 = node->node_arg1; + const ap_expr *e2 = node->node_arg2; + return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) != 0); + } + case op_STR_LT: { + const ap_expr *e1 = node->node_arg1; + const ap_expr *e2 = node->node_arg2; + return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) < 0); + } + case op_STR_LE: { + const ap_expr *e1 = node->node_arg1; + const ap_expr *e2 = node->node_arg2; + return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <= 0); + } + case op_STR_GT: { + const ap_expr *e1 = node->node_arg1; + const ap_expr *e2 = node->node_arg2; + return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) > 0); + } + case op_STR_GE: { + const ap_expr *e1 = node->node_arg1; + const ap_expr *e2 = node->node_arg2; + return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >= 0); + } + case op_IN: { + const ap_expr *e1 = node->node_arg1; + const ap_expr *e2 = node->node_arg2; + const char *needle = ap_expr_eval_word(ctx, e1); + if (e2->node_op == op_ListElement) { + do { + const ap_expr *val = e2->node_arg1; + AP_DEBUG_ASSERT(e2->node_op == op_ListElement); + if (strcmp(needle, ap_expr_eval_word(ctx, val)) == 0) { + return 1; + break; + } + e2 = e2->node_arg2; + } while (e2 != NULL); + } + else if (e2->node_op == op_ListFuncCall) { + const ap_expr *info = e2->node_arg1; + const ap_expr *arg = e2->node_arg2; + ap_expr_list_func_t *func = info->node_arg1; + apr_array_header_t *haystack; + int i = 0; + AP_DEBUG_ASSERT(func != NULL); + AP_DEBUG_ASSERT(info->node_op == op_ListFuncInfo); + haystack = (*func)(ctx, info->node_arg2, ap_expr_eval_word(ctx, arg)); + if (haystack == NULL) + return 0; + for (; i < haystack->nelts; i++) { + if (strcmp(needle, APR_ARRAY_IDX(haystack,i,char *)) == 0) + return 1; + } + } + return 0; + } + case op_REG: { + const ap_expr *e1; + const ap_expr *e2; + const char *word; + const ap_regex_t *regex; + + e1 = node->node_arg1; + e2 = node->node_arg2; + word = ap_expr_eval_word(ctx, e1); + regex = e2->node_arg1; + return (ap_regexec(regex, word, 0, NULL, 0) == 0); + } + case op_NRE: { + const ap_expr *e1; + const ap_expr *e2; + const char *word; + const ap_regex_t *regex; + + e1 = node->node_arg1; + e2 = node->node_arg2; + word = ap_expr_eval_word(ctx, e1); + regex = e2->node_arg1; + return !(ap_regexec(regex, word, 0, NULL, 0) == 0); + } + default: { + *ctx->err = "Internal evaluation error: Unknown expression node"; + return -1; + } + } +} + +/* combined string/int comparison for compatibility with ssl_expr */ +static int strcmplex(const char *str1, const char *str2) +{ + int i, n1, n2; + + if (str1 == NULL) + return -1; + if (str2 == NULL) + return +1; + n1 = strlen(str1); + n2 = strlen(str2); + if (n1 > n2) + return 1; + if (n1 < n2) + return -1; + for (i = 0; i < n1; i++) { + if (str1[i] > str2[i]) + return 1; + if (str1[i] < str2[i]) + return -1; + } + return 0; +} + +static int ssl_expr_eval_comp(ap_expr_eval_ctx *ctx, const ap_expr *node) +{ + const ap_expr *e1 = node->node_arg1; + const ap_expr *e2 = node->node_arg2; + switch (node->node_op) { + case op_EQ: + case op_STR_EQ: + return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) == 0); + case op_NE: + case op_STR_NE: + return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) != 0); + case op_LT: + case op_STR_LT: + return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) < 0); + case op_LE: + case op_STR_LE: + return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <= 0); + case op_GT: + case op_STR_GT: + return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) > 0); + case op_GE: + case op_STR_GE: + return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >= 0); + default: + return ap_expr_eval_comp(ctx, node); + } +} + + +AP_DECLARE(const char *) ap_expr_parse(apr_pool_t *pool, apr_pool_t *ptemp, + ap_expr_info_t *info, const char *expr, + ap_expr_lookup_fn *lookup_fn) +{ + ap_expr_parse_ctx ctx; + int rc; + + ctx.pool = pool; + ctx.ptemp = ptemp; + ctx.inputbuf = expr; + ctx.inputlen = strlen(expr); + ctx.inputptr = ctx.inputbuf; + ctx.expr = NULL; + ctx.error = NULL; /* generic bison error message (usually not very useful) */ + ctx.error2 = NULL; /* additional error message */ + ctx.flags = info->flags; + ctx.scan_del = '\0'; + ctx.scan_buf[0] = '\0'; + ctx.scan_ptr = ctx.scan_buf; + ctx.lookup_fn = lookup_fn ? lookup_fn : ap_run_expr_lookup; + + ap_expr_yylex_init(&ctx.scanner); + ap_expr_yyset_extra(&ctx, ctx.scanner); + rc = ap_expr_yyparse(&ctx); + ap_expr_yylex_destroy(ctx.scanner); + if (ctx.error) { + if (ctx.error2) + return apr_psprintf(pool, "%s: %s", ctx.error, ctx.error2); + else + return ctx.error; + } + else if (ctx.error2) { + return ctx.error2; + } + + if (rc) /* XXX can this happen? */ + return "syntax error"; + + /* XXX Make this properly depend on the loglevel, which requires + * XXX having a server_rec + */ + /* + if (ctx.expr) + expr_dump_tree(ctx.expr, NULL, APLOG_NOTICE, 2); + */ + + info->root_node = ctx.expr; + + return NULL; +} + +AP_DECLARE(ap_expr_info_t*) ap_expr_parse_cmd(const cmd_parms *cmd, + const char *expr, + const char **err, + ap_expr_lookup_fn *lookup_fn) +{ + ap_expr_info_t *info = apr_pcalloc(cmd->pool, sizeof(ap_expr_info_t)); + info->filename = cmd->directive->filename; + info->line_number = cmd->directive->line_num; + *err = ap_expr_parse(cmd->pool, cmd->temp_pool, info, expr, lookup_fn); + + if (*err) + return NULL; + + return info; +} + +ap_expr *ap_expr_make(ap_expr_node_op op, const void *a1, const void *a2, + ap_expr_parse_ctx *ctx) +{ + ap_expr *node = apr_palloc(ctx->pool, sizeof(ap_expr)); + node->node_op = op; + node->node_arg1 = a1; + node->node_arg2 = a2; + return node; +} + + +static ap_expr *ap_expr_info_make(int type, const char *name, ap_expr_parse_ctx *ctx) +{ + ap_expr *info = apr_palloc(ctx->pool, sizeof(ap_expr)); + ap_expr_lookup_parms parms; + parms.type = type; + parms.flags = 0; + parms.pool = ctx->pool; + parms.ptemp = ctx->ptemp; + parms.name = name; + parms.func = &info->node_arg1; + parms.data = &info->node_arg2; + parms.err = &ctx->error2; + if (ctx->lookup_fn(&parms) != OK) + return NULL; + return info; +} + +ap_expr *ap_expr_str_func_make(const char *name, const ap_expr *arg, + ap_expr_parse_ctx *ctx) +{ + ap_expr *info = ap_expr_info_make(AP_EXPR_FUNC_STRING, name, ctx); + if (!info) + return NULL; + + info->node_op = op_StringFuncInfo; + return ap_expr_make(op_StringFuncCall, info, arg, ctx); +} + +ap_expr *ap_expr_list_func_make(const char *name, const ap_expr *arg, + ap_expr_parse_ctx *ctx) +{ + ap_expr *info = ap_expr_info_make(AP_EXPR_FUNC_LIST, name, ctx); + if (!info) + return NULL; + + info->node_op = op_ListFuncInfo; + return ap_expr_make(op_ListFuncCall, info, arg, ctx); +} + +ap_expr *ap_expr_unary_op_make(const char *name, const ap_expr *arg, + ap_expr_parse_ctx *ctx) +{ + ap_expr *info = ap_expr_info_make(AP_EXPR_FUNC_OP_UNARY, name, ctx); + if (!info) + return NULL; + + info->node_op = op_UnaryOpInfo; + return ap_expr_make(op_UnaryOpCall, info, arg, ctx); +} + +ap_expr *ap_expr_binary_op_make(const char *name, const ap_expr *arg1, + const ap_expr *arg2, ap_expr_parse_ctx *ctx) +{ + ap_expr *args; + ap_expr *info = ap_expr_info_make(AP_EXPR_FUNC_OP_UNARY, name, ctx); + if (!info) + return NULL; + + info->node_op = op_BinaryOpInfo; + args = ap_expr_make(op_BinaryOpArgs, arg1, arg2, ctx); + return ap_expr_make(op_BinaryOpCall, info, args, ctx); +} + + +ap_expr *ap_expr_var_make(const char *name, ap_expr_parse_ctx *ctx) +{ + ap_expr *node = ap_expr_info_make(AP_EXPR_FUNC_VAR, name, ctx); + if (!node) + return NULL; + + node->node_op = op_Var; + return node; +} + + +#define MARK APLOG_MARK,loglevel,0,s +#define DUMP_E_E(op, e1, e2) \ + do { ap_log_error(MARK,"%*s%s: %pp %pp", indent, " ", op, e1, e2); \ + if (e1) expr_dump_tree(e1, s, loglevel, indent + 2); \ + if (e2) expr_dump_tree(e2, s, loglevel, indent + 2); \ + } while (0) +#define DUMP_S_E(op, s1, e1) \ + do { ap_log_error(MARK,"%*s%s: '%s' %pp", indent, " ", op, (char *)s1, e1); \ + if (e1) expr_dump_tree(e1, s, loglevel, indent + 2); \ + } while (0) +#define DUMP_S_P(op, s1, p1) \ + ap_log_error(MARK,"%*s%s: '%s' %pp", indent, " ", op, (char *)s1, p1); +#define DUMP_P_P(op, p1, p2) \ + ap_log_error(MARK,"%*s%s: %pp %pp", indent, " ", op, p1, p2); +#define DUMP_S_S(op, s1, s2) \ + ap_log_error(MARK,"%*s%s: '%s' '%s'", indent, " ", op, (char *)s1, (char *)s2) +#define DUMP_P(op, p1) \ + ap_log_error(MARK,"%*s%s: %pp", indent, " ", op, p1); +#define DUMP_S(op, s1) \ + ap_log_error(MARK,"%*s%s: '%s'", indent, " ", op, (char *)s1) + +#define CASE_OP(op) case op: name = #op ; break; + +static void expr_dump_tree(const ap_expr *e, const server_rec *s, int loglevel, int indent) +{ + switch (e->node_op) { + /* no arg */ + case op_NOP: + case op_True: + case op_False: + { + char *name; + switch (e->node_op) { + CASE_OP(op_NOP); + CASE_OP(op_True); + CASE_OP(op_False); + default: + ap_assert(0); + } + ap_log_error(MARK, "%*s%s", indent, " ", name); + } + break; + + /* arg1: string, arg2: expr */ + case op_UnaryOpCall: + case op_BinaryOpCall: + case op_BinaryOpArgs: + { + char *name; + switch (e->node_op) { + CASE_OP(op_BinaryOpCall); + CASE_OP(op_UnaryOpCall); + CASE_OP(op_BinaryOpArgs); + default: + ap_assert(0); + } + DUMP_S_E(name, e->node_arg1, e->node_arg2); + } + break; + + /* arg1: expr, arg2: expr */ + case op_Comp: + case op_Not: + case op_Or: + case op_And: + case op_EQ: + case op_NE: + case op_LT: + case op_LE: + case op_GT: + case op_GE: + case op_STR_EQ: + case op_STR_NE: + case op_STR_LT: + case op_STR_LE: + case op_STR_GT: + case op_STR_GE: + case op_IN: + case op_REG: + case op_NRE: + case op_Concat: + case op_StringFuncCall: + case op_ListFuncCall: + case op_ListElement: + { + char *name; + switch (e->node_op) { + CASE_OP(op_Comp); + CASE_OP(op_Not); + CASE_OP(op_Or); + CASE_OP(op_And); + CASE_OP(op_EQ); + CASE_OP(op_NE); + CASE_OP(op_LT); + CASE_OP(op_LE); + CASE_OP(op_GT); + CASE_OP(op_GE); + CASE_OP(op_STR_EQ); + CASE_OP(op_STR_NE); + CASE_OP(op_STR_LT); + CASE_OP(op_STR_LE); + CASE_OP(op_STR_GT); + CASE_OP(op_STR_GE); + CASE_OP(op_IN); + CASE_OP(op_REG); + CASE_OP(op_NRE); + CASE_OP(op_Concat); + CASE_OP(op_StringFuncCall); + CASE_OP(op_ListFuncCall); + CASE_OP(op_ListElement); + default: + ap_assert(0); + } + DUMP_E_E(name, e->node_arg1, e->node_arg2); + } + break; + /* arg1: string */ + case op_Digit: + case op_String: + { + char *name; + switch (e->node_op) { + CASE_OP(op_Digit); + CASE_OP(op_String); + default: + ap_assert(0); + } + DUMP_S(name, e->node_arg1); + } + break; + /* arg1: pointer, arg2: pointer */ + case op_Var: + case op_StringFuncInfo: + case op_UnaryOpInfo: + case op_BinaryOpInfo: + case op_ListFuncInfo: + { + char *name; + switch (e->node_op) { + CASE_OP(op_Var); + CASE_OP(op_StringFuncInfo); + CASE_OP(op_UnaryOpInfo); + CASE_OP(op_BinaryOpInfo); + CASE_OP(op_ListFuncInfo); + default: + ap_assert(0); + } + DUMP_P_P(name, e->node_arg1, e->node_arg2); + } + break; + /* arg1: pointer */ + case op_Regex: + DUMP_P("op_Regex", e->node_arg1); + break; + default: + ap_log_error(MARK, "%*sERROR: INVALID OP %d", indent, " ", e->node_op); + break; + } +} +static int ap_expr_eval_unary_op(ap_expr_eval_ctx *ctx, const ap_expr *info, + const ap_expr *arg) +{ + const ap_expr_op_unary_t *op_func = info->node_arg1; + const void *data = info->node_arg2; + + AP_DEBUG_ASSERT(info->node_op == op_UnaryOpInfo); + AP_DEBUG_ASSERT(op_func != NULL); + AP_DEBUG_ASSERT(data != NULL); + return (*op_func)(ctx, data, ap_expr_eval_word(ctx, arg)); +} + +static int ap_expr_eval_binary_op(ap_expr_eval_ctx *ctx, const ap_expr *info, + const ap_expr *args) +{ + const ap_expr_op_binary_t *op_func = info->node_arg1; + const void *data = info->node_arg2; + const ap_expr *a1 = args->node_arg1; + const ap_expr *a2 = args->node_arg2; + + AP_DEBUG_ASSERT(info->node_op == op_BinaryOpInfo); + AP_DEBUG_ASSERT(args->node_op == op_BinaryOpArgs); + AP_DEBUG_ASSERT(op_func != NULL); + AP_DEBUG_ASSERT(data != NULL); + return (*op_func)(ctx, data, ap_expr_eval_word(ctx, a1), + ap_expr_eval_word(ctx, a2)); +} + + +static int ap_expr_eval(ap_expr_eval_ctx *ctx, const ap_expr *node) +{ + switch (node->node_op) { + case op_True: { + return 1; + } + case op_False: { + return 0; + } + case op_Not: { + const ap_expr *e = node->node_arg1; + return (!ap_expr_eval(ctx, e)); + } + case op_Or: { + const ap_expr *e1 = node->node_arg1; + const ap_expr *e2 = node->node_arg2; + return (ap_expr_eval(ctx, e1) || ap_expr_eval(ctx, e2)); + } + case op_And: { + const ap_expr *e1 = node->node_arg1; + const ap_expr *e2 = node->node_arg2; + return (ap_expr_eval(ctx, e1) && ap_expr_eval(ctx, e2)); + } + case op_UnaryOpCall: { + const ap_expr *info = node->node_arg1; + const ap_expr *args = node->node_arg2; + return ap_expr_eval_unary_op(ctx, info, args); + } + case op_BinaryOpCall: { + const ap_expr *info = node->node_arg1; + const ap_expr *args = node->node_arg2; + return ap_expr_eval_binary_op(ctx, info, args); + } + case op_Comp: { + const ap_expr *e = node->node_arg1; + if (ctx->info->flags & AP_EXPR_FLAGS_SSL_EXPR_COMPAT) + return ssl_expr_eval_comp(ctx, e); + else + return ap_expr_eval_comp(ctx, e); + } + default: { + *ctx->err = "Internal evaluation error: Unknown expression node"; + return FALSE; + } + } +} + + +AP_DECLARE(int) ap_expr_exec(request_rec *r, const ap_expr_info_t *info, const char **err) +{ + ap_expr_eval_ctx ctx; + int rc; + ctx.r = r; + ctx.c = r->connection; + ctx.s = r->server; + ctx.p = r->pool; + ctx.err = err; + ctx.info = info; + + *err = NULL; + rc = ap_expr_eval(&ctx, info->root_node); + if (*err != NULL) + return (-1); + else + return (rc ? 1 : 0); +} + +static const char *req_func(ap_expr_eval_ctx *ctx, const char *name, + const char *arg) +{ + if (ctx->r) + return apr_table_get(ctx->r->headers_in, arg); + else + return ""; +} + +static const char *resp_func(ap_expr_eval_ctx *ctx, const char *name, + const char *arg) +{ + if (ctx->r) + return apr_table_get(ctx->r->headers_out, arg); + else + return ""; +} + +static const char *env_func(ap_expr_eval_ctx *ctx, const char *name, + const char *arg) +{ + if (ctx->r) + return apr_table_get(ctx->r->subprocess_env, arg); + else + return ""; +} + +static const char *osenv_func(ap_expr_eval_ctx *ctx, const char *name, const char *arg) +{ + return getenv(arg); +} + +static const char *tolower_func(ap_expr_eval_ctx *ctx, const char *name, const char *arg) +{ + char *result = apr_pstrdup(ctx->p, arg); + ap_str_tolower(result); + return result; +} + +static const char *toupper_func(ap_expr_eval_ctx *ctx, const char *name, const char *arg) +{ + char *p; + char *result = apr_pstrdup(ctx->p, arg); + + for (p = result; *p; ++p) { + *p = apr_toupper(*p); + } + + return result; +} + +static const char *escape_func(ap_expr_eval_ctx *ctx, const char *name, const char *arg) +{ + return ap_escape_uri(ctx->p, arg); +} + +static const char *unescape_func(ap_expr_eval_ctx *ctx, const char *name, const char *arg) +{ + char *result = apr_pstrdup(ctx->p, arg); + if (ap_unescape_url(result)) + return ""; + else + return result; + +} + +static const char *request_var_names[] = { + "REQUEST_METHOD", /* 0 */ + "REQUEST_SCHEME", /* 1 */ + "REQUEST_URI", /* 2 */ + "REQUEST_FILENAME", /* 3 */ + "REMOTE_HOST", /* 4 */ + "REMOTE_IDENT", /* 5 */ + "REMOTE_USER", /* 6 */ + "SERVER_ADMIN", /* 7 */ + "SERVER_NAME", /* 8 */ + "SERVER_PORT", /* 9 */ + "SERVER_PROTOCOL", /* 10 */ + "SCRIPT_FILENAME", /* 11 */ + "PATH_INFO", /* 12 */ + "QUERY_STRING", /* 13 */ + "IS_SUBREQ", /* 14 */ + "DOCUMENT_ROOT", /* 15 */ + "AUTH_TYPE", /* 16 */ + "THE_REQUEST", /* 17 */ + "REMOTE_ADDR", /* 18 */ + "CONTENT_TYPE", /* 19 */ + NULL +}; + +static const char *request_var_fn(ap_expr_eval_ctx *ctx, const void *data) +{ + int index = ((const char **)data - request_var_names); + request_rec *r = ctx->r; + if (!r) + return ""; + + switch (index) { + case 0: + return r->method; + case 1: + return ap_http_scheme(r); + case 2: + return r->uri; + case 3: + return r->filename; + case 4: + return ap_get_remote_host(r->connection, r->per_dir_config, + REMOTE_NAME, NULL); + case 5: + return ap_get_remote_logname(r); + case 6: + return r->user; + case 7: + return r->server->server_admin; + case 8: + return ap_get_server_name(r); + case 9: + return apr_psprintf(ctx->p, "%u", ap_get_server_port(r)); + case 10: + return r->protocol; + case 11: + return r->filename; + case 12: + return r->path_info; + case 13: + return r->args; + case 14: + return (r->main != NULL ? "true" : "false"); + case 15: + return ap_document_root(r); + case 16: + return r->ap_auth_type; + case 17: + return r->the_request; + case 18: + return ctx->c->remote_ip; + case 19: + return r->content_type; + default: + ap_assert(0); + return NULL; + } +} + +static const char *req_header_var_names[] = { + "HTTP_USER_AGENT", /* 0 */ + "HTTP_PROXY_CONNECTION", /* 1 */ + "HTTP_REFERER", + "HTTP_COOKIE", + "HTTP_FORWARDED", + "HTTP_HOST", + "HTTP_ACCEPT", + NULL +}; + +static const char *req_header_var_fn(ap_expr_eval_ctx *ctx, const void *data) +{ + const char **name = (const char **)data; + int index = (name - req_header_var_names); + if (!ctx->r) + return ""; + + switch (index) { + case 0: + return apr_table_get(ctx->r->headers_in, "User-Agent"); + case 1: + return apr_table_get(ctx->r->headers_in, "Proxy-Connection"); + default: + /* apr_table_get is case insensitive, just skip leading "HTTP_" */ + return apr_table_get(ctx->r->headers_in, *name + 5); + } +} + +static const char *misc_var_names[] = { + "TIME_YEAR", /* 0 */ + "TIME_MON", /* 1 */ + "TIME_DAY", /* 2 */ + "TIME_HOUR", /* 3 */ + "TIME_MIN", /* 4 */ + "TIME_SEC", /* 5 */ + "TIME_WDAY", /* 6 */ + "TIME", /* 7 */ + "SERVER_SOFTWARE", /* 8 */ + "API_VERSION", /* 9 */ + NULL +}; + +static const char *misc_var_fn(ap_expr_eval_ctx *ctx, const void *data) +{ + apr_time_exp_t tm; + apr_time_exp_lt(&tm, apr_time_now()); + int index = ((const char **)data - misc_var_names); + + switch (index) { + case 0: + return apr_psprintf(ctx->p, "%02d%02d", (tm.tm_year / 100) + 19, + tm.tm_year % 100); + case 1: + return apr_psprintf(ctx->p, "%02d", tm.tm_mon+1); + case 2: + return apr_psprintf(ctx->p, "%02d", tm.tm_mday); + case 3: + return apr_psprintf(ctx->p, "%02d", tm.tm_hour); + case 4: + return apr_psprintf(ctx->p, "%02d", tm.tm_min); + case 5: + return apr_psprintf(ctx->p, "%02d", tm.tm_sec); + case 6: + return apr_psprintf(ctx->p, "%d", tm.tm_wday); + case 7: + return apr_psprintf(ctx->p, "%02d%02d%02d%02d%02d%02d%02d", + (tm.tm_year / 100) + 19, (tm.tm_year % 100), + tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, + tm.tm_sec); + case 8: + return ap_get_server_banner(); + case 9: + return apr_itoa(ctx->p, MODULE_MAGIC_NUMBER); + default: + ap_assert(0); + } + + return NULL; +} + +struct expr_provider_single { + const void *func; + const char *name; +}; +struct expr_provider_multi { + const void *func; + const char **names; +}; + +static const struct expr_provider_multi var_providers[] = { + { misc_var_fn, misc_var_names }, + { req_header_var_fn, req_header_var_names }, + { request_var_fn, request_var_names }, + { NULL, NULL } +}; + +static const struct expr_provider_single string_func_providers[] = { + { osenv_func, "osenv" }, + { env_func, "env" }, + { resp_func, "resp" }, + { req_func, "req" }, + /* 'http' as alias for 'req' for compatibility with ssl_expr */ + { req_func, "http" }, + { tolower_func, "tolower" }, + { toupper_func, "toupper" }, + { escape_func, "escape" }, + { unescape_func, "unescape" }, + { NULL, NULL} +}; +/* XXX: base64 encode/decode ? */ + +static int core_expr_lookup(ap_expr_lookup_parms *parms) +{ + switch (parms->type) { + case AP_EXPR_FUNC_VAR: { + const struct expr_provider_multi *prov = var_providers; + while (prov->func) { + const char **name = prov->names; + while (*name) { + if (strcasecmp(*name, parms->name) == 0) { + *parms->func = prov->func; + *parms->data = name; + return OK; + } + name++; + } + prov++; + } + break; + } + case AP_EXPR_FUNC_STRING: { + const struct expr_provider_single *prov = string_func_providers; + while (prov->func) { + if (strcasecmp(prov->name, parms->name) == 0) { + *parms->func = prov->func; + *parms->data = prov->name; + return OK; + } + prov++; + } + break; + } + default: + break; + } + return DECLINED; +} + +static int expr_lookup_not_found(ap_expr_lookup_parms *parms) +{ + const char *type; + + switch (parms->type) { + case AP_EXPR_FUNC_VAR: + type = "Variable"; + break; + case AP_EXPR_FUNC_STRING: + type = "Function"; + break; + case AP_EXPR_FUNC_LIST: + type = "List-returning function"; + break; + case AP_EXPR_FUNC_OP_UNARY: + type = "Unary operator"; + break; + case AP_EXPR_FUNC_OP_BINARY: + type = "Binary operator"; + break; + default: + *parms->err = "Inavalid expression type in expr_lookup"; + return !OK; + } + *parms->err = apr_psprintf(parms->ptemp, "%s '%s' does not exist", type, + parms->name); + return !OK; +} + +void ap_expr_init(apr_pool_t *p) +{ + ap_hook_expr_lookup(core_expr_lookup, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_expr_lookup(expr_lookup_not_found, NULL, NULL, APR_HOOK_REALLY_LAST); +} + diff --git a/modules/ssl/ssl_expr_parse.c b/server/util_expr_parse.c index c05caba20f..5562e9e8f9 100644 --- a/modules/ssl/ssl_expr_parse.c +++ b/server/util_expr_parse.c @@ -64,25 +64,25 @@ #define YYLSP_NEEDED 0 /* Substitute the variable and function names. */ -#define yyparse ssl_expr_yyparse -#define yylex ssl_expr_yylex -#define yyerror ssl_expr_yyerror -#define yylval ssl_expr_yylval -#define yychar ssl_expr_yychar -#define yydebug ssl_expr_yydebug -#define yynerrs ssl_expr_yynerrs +#define yyparse ap_expr_yyparse +#define yylex ap_expr_yylex +#define yyerror ap_expr_yyerror +#define yylval ap_expr_yylval +#define yychar ap_expr_yychar +#define yydebug ap_expr_yydebug +#define yynerrs ap_expr_yynerrs /* Copy the first part of user declarations. */ /* Line 189 of yacc.c */ -#line 41 "ssl_expr_parse.y" +#line 31 "util_expr_parse.y" -#include "ssl_private.h" +#include "util_expr_private.h" /* Line 189 of yacc.c */ -#line 86 "ssl_expr_parse.c" +#line 86 "util_expr_parse.c" /* Enabling traces. */ #ifndef YYDEBUG @@ -111,25 +111,37 @@ enum yytokentype { T_TRUE = 258, T_FALSE = 259, - T_DIGIT = 260, - T_ID = 261, - T_STRING = 262, - T_REGEX = 263, - T_REGEX_I = 264, - T_FUNC_FILE = 265, - T_OP_EQ = 266, - T_OP_NE = 267, - T_OP_LT = 268, - T_OP_LE = 269, - T_OP_GT = 270, - T_OP_GE = 271, - T_OP_REG = 272, - T_OP_NRE = 273, - T_OP_IN = 274, - T_OP_PEEREXTLIST = 275, - T_OP_OR = 276, - T_OP_AND = 277, - T_OP_NOT = 278 + ERROR = 260, + T_DIGIT = 261, + T_ID = 262, + T_STRING = 263, + T_REGEX = 264, + T_REGEX_I = 265, + T_OP_UNARY = 266, + T_OP_BINARY = 267, + T_STR_BEGIN = 268, + T_STR_END = 269, + T_VAR_BEGIN = 270, + T_VAR_END = 271, + T_OP_EQ = 272, + T_OP_NE = 273, + T_OP_LT = 274, + T_OP_LE = 275, + T_OP_GT = 276, + T_OP_GE = 277, + T_OP_REG = 278, + T_OP_NRE = 279, + T_OP_IN = 280, + T_OP_STR_EQ = 281, + T_OP_STR_NE = 282, + T_OP_STR_LT = 283, + T_OP_STR_LE = 284, + T_OP_STR_GT = 285, + T_OP_STR_GE = 286, + T_OP_CONCAT = 287, + T_OP_OR = 288, + T_OP_AND = 289, + T_OP_NOT = 290 }; #endif @@ -140,15 +152,15 @@ typedef union YYSTYPE { /* Line 214 of yacc.c */ -#line 45 "ssl_expr_parse.y" +#line 35 "util_expr_parse.y" - char *cpVal; - ssl_expr *exVal; + char *cpVal; + ap_expr *exVal; /* Line 214 of yacc.c */ -#line 152 "ssl_expr_parse.c" +#line 164 "util_expr_parse.c" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ @@ -159,17 +171,16 @@ typedef union YYSTYPE /* Copy the second part of user declarations. */ /* Line 264 of yacc.c */ -#line 88 "ssl_expr_parse.y" +#line 96 "util_expr_parse.y" -#include "ssl_expr.h" -#define yyscanner context->scanner +#include "util_expr_private.h" +#define yyscanner ctx->scanner -int ssl_expr_yyerror(ssl_expr_info_type *context, char *err); -int ssl_expr_yylex(YYSTYPE *lvalp, void *scanner); +int ap_expr_yylex(YYSTYPE *lvalp, void *scanner); /* Line 264 of yacc.c */ -#line 173 "ssl_expr_parse.c" +#line 184 "util_expr_parse.c" #ifdef short # undef short @@ -382,22 +393,22 @@ union yyalloc #endif /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 18 +#define YYFINAL 27 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 56 +#define YYLAST 117 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 30 +#define YYNTOKENS 42 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 9 +#define YYNNTS 13 /* YYNRULES -- Number of rules. */ -#define YYNRULES 29 +#define YYNRULES 47 /* YYNRULES -- Number of states. */ -#define YYNSTATES 58 +#define YYNSTATES 88 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 278 +#define YYMAXUTOK 290 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -408,16 +419,16 @@ static const yytype_uint8 yytranslate[] = 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 29, 2, 2, - 24, 25, 2, 2, 28, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 36, 37, 2, 2, 40, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 41, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 26, 2, 27, 2, 2, 2, 2, + 2, 2, 2, 38, 2, 39, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -432,7 +443,9 @@ static const yytype_uint8 yytranslate[] = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23 + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35 }; #if YYDEBUG @@ -440,32 +453,42 @@ static const yytype_uint8 yytranslate[] = YYRHS. */ static const yytype_uint8 yyprhs[] = { - 0, 0, 3, 5, 7, 9, 12, 16, 20, 22, - 26, 30, 34, 38, 42, 46, 50, 54, 58, 62, - 67, 71, 73, 77, 79, 81, 86, 88, 90, 92 + 0, 0, 3, 5, 7, 9, 11, 14, 18, 22, + 24, 27, 31, 35, 39, 43, 47, 51, 55, 59, + 63, 67, 71, 75, 79, 83, 87, 91, 95, 97, + 101, 103, 107, 110, 112, 114, 116, 120, 126, 128, + 132, 134, 136, 140, 143, 145, 147, 152 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { - 31, 0, -1, 32, -1, 3, -1, 4, -1, 23, - 32, -1, 32, 21, 32, -1, 32, 22, 32, -1, - 33, -1, 24, 32, 25, -1, 36, 11, 36, -1, - 36, 12, 36, -1, 36, 13, 36, -1, 36, 14, - 36, -1, 36, 15, 36, -1, 36, 16, 36, -1, - 36, 19, 34, -1, 36, 17, 37, -1, 36, 18, - 37, -1, 20, 24, 36, 25, -1, 26, 35, 27, - -1, 36, -1, 35, 28, 36, -1, 5, -1, 7, - -1, 29, 26, 6, 27, -1, 38, -1, 8, -1, - 9, -1, 10, 24, 7, 25, -1 + 43, 0, -1, 44, -1, 5, -1, 3, -1, 4, + -1, 35, 44, -1, 44, 33, 44, -1, 44, 34, + 44, -1, 45, -1, 11, 51, -1, 36, 44, 37, + -1, 51, 17, 51, -1, 51, 18, 51, -1, 51, + 19, 51, -1, 51, 20, 51, -1, 51, 21, 51, + -1, 51, 22, 51, -1, 51, 26, 51, -1, 51, + 27, 51, -1, 51, 28, 51, -1, 51, 29, 51, + -1, 51, 30, 51, -1, 51, 31, 51, -1, 51, + 25, 46, -1, 51, 23, 52, -1, 51, 24, 52, + -1, 51, 12, 51, -1, 53, -1, 38, 47, 39, + -1, 51, -1, 47, 40, 51, -1, 48, 49, -1, + 49, -1, 8, -1, 50, -1, 15, 7, 16, -1, + 15, 7, 41, 48, 16, -1, 6, -1, 51, 32, + 51, -1, 50, -1, 54, -1, 13, 48, 14, -1, + 13, 14, -1, 9, -1, 10, -1, 7, 36, 51, + 37, -1, 7, 36, 51, 37, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 99, 99, 102, 103, 104, 105, 106, 107, 108, - 111, 112, 113, 114, 115, 116, 117, 118, 119, 122, - 123, 126, 127, 130, 131, 132, 133, 136, 145, 156 + 0, 106, 106, 107, 110, 111, 112, 113, 114, 115, + 116, 117, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 138, 139, + 142, 143, 146, 147, 151, 152, 155, 156, 159, 160, + 161, 162, 163, 164, 167, 176, 187, 190 }; #endif @@ -474,12 +497,15 @@ static const yytype_uint8 yyrline[] = First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { - "$end", "error", "$undefined", "T_TRUE", "T_FALSE", "T_DIGIT", "T_ID", - "T_STRING", "T_REGEX", "T_REGEX_I", "T_FUNC_FILE", "T_OP_EQ", "T_OP_NE", - "T_OP_LT", "T_OP_LE", "T_OP_GT", "T_OP_GE", "T_OP_REG", "T_OP_NRE", - "T_OP_IN", "T_OP_PEEREXTLIST", "T_OP_OR", "T_OP_AND", "T_OP_NOT", "'('", - "')'", "'{'", "'}'", "','", "'%'", "$accept", "root", "expr", - "comparison", "wordlist", "words", "word", "regex", "funccall", 0 + "$end", "error", "$undefined", "T_TRUE", "T_FALSE", "ERROR", "T_DIGIT", + "T_ID", "T_STRING", "T_REGEX", "T_REGEX_I", "T_OP_UNARY", "T_OP_BINARY", + "T_STR_BEGIN", "T_STR_END", "T_VAR_BEGIN", "T_VAR_END", "T_OP_EQ", + "T_OP_NE", "T_OP_LT", "T_OP_LE", "T_OP_GT", "T_OP_GE", "T_OP_REG", + "T_OP_NRE", "T_OP_IN", "T_OP_STR_EQ", "T_OP_STR_NE", "T_OP_STR_LT", + "T_OP_STR_LE", "T_OP_STR_GT", "T_OP_STR_GE", "T_OP_CONCAT", "T_OP_OR", + "T_OP_AND", "T_OP_NOT", "'('", "')'", "'{'", "'}'", "','", "':'", + "$accept", "root", "expr", "comparison", "wordlist", "words", "string", + "strpart", "var", "word", "regex", "lstfunccall", "strfunccall", 0 }; #endif @@ -490,24 +516,30 @@ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 40, 41, 123, 125, 44, 37 + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 40, 41, 123, 125, + 44, 58 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 30, 31, 32, 32, 32, 32, 32, 32, 32, - 33, 33, 33, 33, 33, 33, 33, 33, 33, 34, - 34, 35, 35, 36, 36, 36, 36, 37, 37, 38 + 0, 42, 43, 43, 44, 44, 44, 44, 44, 44, + 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 46, 46, + 47, 47, 48, 48, 49, 49, 50, 50, 51, 51, + 51, 51, 51, 51, 52, 52, 53, 54 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { - 0, 2, 1, 1, 1, 2, 3, 3, 1, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, - 3, 1, 3, 1, 1, 4, 1, 1, 1, 4 + 0, 2, 1, 1, 1, 1, 2, 3, 3, 1, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, + 1, 3, 2, 1, 1, 1, 3, 5, 1, 3, + 1, 1, 3, 2, 1, 1, 4, 4 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -515,37 +547,45 @@ static const yytype_uint8 yyr2[] = means the default is an error. */ static const yytype_uint8 yydefact[] = { - 0, 3, 4, 23, 24, 0, 0, 0, 0, 0, - 2, 8, 0, 26, 0, 5, 0, 0, 1, 0, + 0, 4, 5, 3, 38, 0, 0, 0, 0, 0, + 0, 0, 2, 9, 40, 0, 41, 0, 10, 34, + 43, 0, 33, 35, 0, 6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 9, 0, 6, 7, 10, 11, 12, 13, 14, - 15, 27, 28, 17, 18, 0, 0, 16, 29, 25, - 0, 0, 21, 0, 20, 0, 19, 22 + 0, 0, 0, 0, 0, 0, 0, 0, 42, 32, + 36, 0, 11, 7, 8, 27, 12, 13, 14, 15, + 16, 17, 44, 45, 25, 26, 0, 0, 24, 28, + 18, 19, 20, 21, 22, 23, 39, 47, 0, 0, + 0, 30, 37, 0, 29, 0, 46, 31 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - -1, 9, 10, 11, 47, 51, 12, 43, 13 + -1, 11, 12, 13, 68, 80, 21, 22, 14, 15, + 64, 69, 16 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -22 +#define YYPACT_NINF -29 static const yytype_int8 yypact[] = { - 3, -22, -22, -22, -22, -12, 3, 3, -10, 22, - 23, -22, 24, -22, 17, -22, -2, 44, -22, 3, - 3, 4, 4, 4, 4, 4, 4, 38, 38, -5, - 26, -22, 1, 30, -22, -22, -22, -22, -22, -22, - -22, -22, -22, -22, -22, 29, 4, -22, -22, -22, - 4, 21, -22, 31, -22, 4, -22, -22 + 49, -29, -29, -29, -29, 12, 1, 35, 25, 65, + 65, 57, -15, -29, -29, 85, -29, 1, 31, -29, + -29, 51, -29, -29, -10, -29, 53, -29, 65, 65, + 1, 1, 1, 1, 1, 1, 1, 11, 11, -5, + 1, 1, 1, 1, 1, 1, 1, -28, -29, -29, + -29, 36, -29, 33, -29, 31, 31, 31, 31, 31, + 31, 31, -29, -29, -29, -29, 34, 1, -29, -29, + 31, 31, 31, 31, 31, 31, -29, -29, -3, 1, + 6, 31, -29, -22, -29, 1, -29, 31 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { - -22, -22, 11, -22, -22, -22, -21, 27, -22 + -29, -29, 13, -29, -29, -29, 24, -20, -4, -6, + 39, -29, -29 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If @@ -555,34 +595,49 @@ static const yytype_int8 yypgoto[] = #define YYTABLE_NINF -1 static const yytype_uint8 yytable[] = { - 35, 36, 37, 38, 39, 40, 1, 2, 3, 3, - 4, 4, 14, 5, 5, 45, 17, 15, 16, 19, - 20, 46, 18, 31, 30, 52, 6, 7, 49, 53, - 33, 34, 8, 8, 57, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 19, 20, 41, 42, 54, 55, - 32, 48, 20, 50, 0, 44, 56 + 18, 49, 66, 23, 46, 19, 50, 4, 5, 77, + 46, 47, 8, 82, 7, 86, 8, 23, 28, 29, + 62, 63, 25, 26, 55, 56, 57, 58, 59, 60, + 61, 51, 24, 67, 70, 71, 72, 73, 74, 75, + 76, 53, 54, 19, 19, 84, 85, 23, 17, 20, + 8, 8, 1, 2, 3, 4, 5, 27, 49, 19, + 6, 81, 7, 46, 8, 48, 8, 29, 1, 2, + 79, 4, 5, 83, 23, 78, 6, 65, 7, 87, + 8, 0, 0, 0, 9, 10, 28, 29, 0, 0, + 52, 0, 0, 0, 0, 0, 0, 30, 0, 0, + 9, 10, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46 }; static const yytype_int8 yycheck[] = { - 21, 22, 23, 24, 25, 26, 3, 4, 5, 5, - 7, 7, 24, 10, 10, 20, 26, 6, 7, 21, - 22, 26, 0, 25, 7, 46, 23, 24, 27, 50, - 19, 20, 29, 29, 55, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 21, 22, 8, 9, 27, 28, - 6, 25, 22, 24, -1, 28, 25 + 6, 21, 7, 7, 32, 8, 16, 6, 7, 37, + 32, 17, 15, 16, 13, 37, 15, 21, 33, 34, + 9, 10, 9, 10, 30, 31, 32, 33, 34, 35, + 36, 41, 7, 38, 40, 41, 42, 43, 44, 45, + 46, 28, 29, 8, 8, 39, 40, 51, 36, 14, + 15, 15, 3, 4, 5, 6, 7, 0, 78, 8, + 11, 67, 13, 32, 15, 14, 15, 34, 3, 4, + 36, 6, 7, 79, 78, 51, 11, 38, 13, 85, + 15, -1, -1, -1, 35, 36, 33, 34, -1, -1, + 37, -1, -1, -1, -1, -1, -1, 12, -1, -1, + 35, 36, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { - 0, 3, 4, 5, 7, 10, 23, 24, 29, 31, - 32, 33, 36, 38, 24, 32, 32, 26, 0, 21, - 22, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 7, 25, 6, 32, 32, 36, 36, 36, 36, 36, - 36, 8, 9, 37, 37, 20, 26, 34, 25, 27, - 24, 35, 36, 36, 27, 28, 25, 36 + 0, 3, 4, 5, 6, 7, 11, 13, 15, 35, + 36, 43, 44, 45, 50, 51, 54, 36, 51, 8, + 14, 48, 49, 50, 7, 44, 44, 0, 33, 34, + 12, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 51, 14, 49, + 16, 41, 37, 44, 44, 51, 51, 51, 51, 51, + 51, 51, 9, 10, 52, 52, 7, 38, 46, 53, + 51, 51, 51, 51, 51, 51, 51, 37, 48, 36, + 47, 51, 16, 51, 39, 40, 37, 51 }; #define yyerrok (yyerrstatus = 0) @@ -615,7 +670,7 @@ do \ } \ else \ { \ - yyerror (context, YY_("syntax error: cannot back up")); \ + yyerror (ctx, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) @@ -695,7 +750,7 @@ do { \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ - Type, Value, context); \ + Type, Value, ctx); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) @@ -709,19 +764,19 @@ do { \ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, ssl_expr_info_type *context) +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, ap_expr_parse_ctx *ctx) #else static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep, context) +yy_symbol_value_print (yyoutput, yytype, yyvaluep, ctx) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; - ssl_expr_info_type *context; + ap_expr_parse_ctx *ctx; #endif { if (!yyvaluep) return; - YYUSE (context); + YYUSE (ctx); # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); @@ -743,14 +798,14 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, context) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, ssl_expr_info_type *context) +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, ap_expr_parse_ctx *ctx) #else static void -yy_symbol_print (yyoutput, yytype, yyvaluep, context) +yy_symbol_print (yyoutput, yytype, yyvaluep, ctx) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; - ssl_expr_info_type *context; + ap_expr_parse_ctx *ctx; #endif { if (yytype < YYNTOKENS) @@ -758,7 +813,7 @@ yy_symbol_print (yyoutput, yytype, yyvaluep, context) else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); - yy_symbol_value_print (yyoutput, yytype, yyvaluep, context); + yy_symbol_value_print (yyoutput, yytype, yyvaluep, ctx); YYFPRINTF (yyoutput, ")"); } @@ -801,13 +856,13 @@ do { \ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_reduce_print (YYSTYPE *yyvsp, int yyrule, ssl_expr_info_type *context) +yy_reduce_print (YYSTYPE *yyvsp, int yyrule, ap_expr_parse_ctx *ctx) #else static void -yy_reduce_print (yyvsp, yyrule, context) +yy_reduce_print (yyvsp, yyrule, ctx) YYSTYPE *yyvsp; int yyrule; - ssl_expr_info_type *context; + ap_expr_parse_ctx *ctx; #endif { int yynrhs = yyr2[yyrule]; @@ -821,7 +876,7 @@ yy_reduce_print (yyvsp, yyrule, context) YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) - , context); + , ctx); YYFPRINTF (stderr, "\n"); } } @@ -829,7 +884,7 @@ yy_reduce_print (yyvsp, yyrule, context) # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ - yy_reduce_print (yyvsp, Rule, context); \ + yy_reduce_print (yyvsp, Rule, ctx); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that @@ -1080,18 +1135,18 @@ yysyntax_error (char *yyresult, int yystate, int yychar) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, ssl_expr_info_type *context) +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, ap_expr_parse_ctx *ctx) #else static void -yydestruct (yymsg, yytype, yyvaluep, context) +yydestruct (yymsg, yytype, yyvaluep, ctx) const char *yymsg; int yytype; YYSTYPE *yyvaluep; - ssl_expr_info_type *context; + ap_expr_parse_ctx *ctx; #endif { YYUSE (yyvaluep); - YYUSE (context); + YYUSE (ctx); if (!yymsg) yymsg = "Deleting"; @@ -1114,7 +1169,7 @@ int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus -int yyparse (ssl_expr_info_type *context); +int yyparse (ap_expr_parse_ctx *ctx); #else int yyparse (); #endif @@ -1142,11 +1197,11 @@ yyparse (YYPARSE_PARAM) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int -yyparse (ssl_expr_info_type *context) +yyparse (ap_expr_parse_ctx *ctx) #else int -yyparse (context) - ssl_expr_info_type *context; +yyparse (ctx) + ap_expr_parse_ctx *ctx; #endif #endif { @@ -1401,222 +1456,345 @@ yyreduce: case 2: /* Line 1455 of yacc.c */ -#line 99 "ssl_expr_parse.y" - { context->expr = (yyvsp[(1) - (1)].exVal); ;} +#line 106 "util_expr_parse.y" + { ctx->expr = (yyvsp[(1) - (1)].exVal); ;} break; case 3: /* Line 1455 of yacc.c */ -#line 102 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_True, NULL, NULL, context); ;} +#line 107 "util_expr_parse.y" + { YYABORT; ;} break; case 4: /* Line 1455 of yacc.c */ -#line 103 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_False, NULL, NULL, context); ;} +#line 110 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_True, NULL, NULL, ctx); ;} break; case 5: /* Line 1455 of yacc.c */ -#line 104 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_Not, (yyvsp[(2) - (2)].exVal), NULL, context); ;} +#line 111 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_False, NULL, NULL, ctx); ;} break; case 6: /* Line 1455 of yacc.c */ -#line 105 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_Or, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), context); ;} +#line 112 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_Not, (yyvsp[(2) - (2)].exVal), NULL, ctx); ;} break; case 7: /* Line 1455 of yacc.c */ -#line 106 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_And, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), context); ;} +#line 113 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_Or, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;} break; case 8: /* Line 1455 of yacc.c */ -#line 107 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_Comp, (yyvsp[(1) - (1)].exVal), NULL, context); ;} +#line 114 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_And, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;} break; case 9: /* Line 1455 of yacc.c */ -#line 108 "ssl_expr_parse.y" - { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); ;} +#line 115 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_Comp, (yyvsp[(1) - (1)].exVal), NULL, ctx); ;} break; case 10: /* Line 1455 of yacc.c */ -#line 111 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_EQ, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), context); ;} +#line 116 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_unary_op_make( (yyvsp[(1) - (2)].cpVal), (yyvsp[(2) - (2)].exVal), ctx); ;} break; case 11: /* Line 1455 of yacc.c */ -#line 112 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_NE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), context); ;} +#line 117 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); ;} break; case 12: /* Line 1455 of yacc.c */ -#line 113 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_LT, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), context); ;} +#line 120 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_EQ, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;} break; case 13: /* Line 1455 of yacc.c */ -#line 114 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_LE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), context); ;} +#line 121 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_NE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;} break; case 14: /* Line 1455 of yacc.c */ -#line 115 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_GT, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), context); ;} +#line 122 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_LT, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;} break; case 15: /* Line 1455 of yacc.c */ -#line 116 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_GE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), context); ;} +#line 123 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_LE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;} break; case 16: /* Line 1455 of yacc.c */ -#line 117 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_IN, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), context); ;} +#line 124 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_GT, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;} break; case 17: /* Line 1455 of yacc.c */ -#line 118 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_REG, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), context); ;} +#line 125 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_GE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;} break; case 18: /* Line 1455 of yacc.c */ -#line 119 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_NRE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), context); ;} +#line 126 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_STR_EQ, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;} break; case 19: /* Line 1455 of yacc.c */ -#line 122 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_PeerExtElement, (yyvsp[(3) - (4)].exVal), NULL, context); ;} +#line 127 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_STR_NE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;} break; case 20: /* Line 1455 of yacc.c */ -#line 123 "ssl_expr_parse.y" - { (yyval.exVal) = (yyvsp[(2) - (3)].exVal) ; ;} +#line 128 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_STR_LT, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;} break; case 21: /* Line 1455 of yacc.c */ -#line 126 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_ListElement, (yyvsp[(1) - (1)].exVal), NULL, context); ;} +#line 129 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_STR_LE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;} break; case 22: /* Line 1455 of yacc.c */ -#line 127 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_ListElement, (yyvsp[(3) - (3)].exVal), (yyvsp[(1) - (3)].exVal), context); ;} +#line 130 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_STR_GT, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;} break; case 23: /* Line 1455 of yacc.c */ -#line 130 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_Digit, (yyvsp[(1) - (1)].cpVal), NULL, context); ;} +#line 131 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_STR_GE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;} break; case 24: /* Line 1455 of yacc.c */ -#line 131 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_String, (yyvsp[(1) - (1)].cpVal), NULL, context); ;} +#line 132 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_IN, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;} break; case 25: /* Line 1455 of yacc.c */ -#line 132 "ssl_expr_parse.y" - { (yyval.exVal) = ssl_expr_make(op_Var, (yyvsp[(3) - (4)].cpVal), NULL, context); ;} +#line 133 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_REG, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;} break; case 26: /* Line 1455 of yacc.c */ -#line 133 "ssl_expr_parse.y" - { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); ;} +#line 134 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_NRE, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;} break; case 27: /* Line 1455 of yacc.c */ -#line 136 "ssl_expr_parse.y" - { +#line 135 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_binary_op_make((yyvsp[(2) - (3)].cpVal), (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;} + break; + + case 28: + +/* Line 1455 of yacc.c */ +#line 138 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); ;} + break; + + case 29: + +/* Line 1455 of yacc.c */ +#line 139 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); ;} + break; + + case 30: + +/* Line 1455 of yacc.c */ +#line 142 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_ListElement, (yyvsp[(1) - (1)].exVal), NULL, ctx); ;} + break; + + case 31: + +/* Line 1455 of yacc.c */ +#line 143 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_ListElement, (yyvsp[(3) - (3)].exVal), (yyvsp[(1) - (3)].exVal), ctx); ;} + break; + + case 32: + +/* Line 1455 of yacc.c */ +#line 146 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_Concat, (yyvsp[(1) - (2)].exVal), (yyvsp[(2) - (2)].exVal), ctx); ;} + break; + + case 33: + +/* Line 1455 of yacc.c */ +#line 147 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); ;} + break; + + case 34: + +/* Line 1455 of yacc.c */ +#line 151 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_String, (yyvsp[(1) - (1)].cpVal), NULL, ctx); ;} + break; + + case 35: + +/* Line 1455 of yacc.c */ +#line 152 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); ;} + break; + + case 36: + +/* Line 1455 of yacc.c */ +#line 155 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_var_make((yyvsp[(2) - (3)].cpVal), ctx); ;} + break; + + case 37: + +/* Line 1455 of yacc.c */ +#line 156 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_str_func_make((yyvsp[(2) - (5)].cpVal), (yyvsp[(4) - (5)].exVal), ctx); ;} + break; + + case 38: + +/* Line 1455 of yacc.c */ +#line 159 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_Digit, (yyvsp[(1) - (1)].cpVal), NULL, ctx); ;} + break; + + case 39: + +/* Line 1455 of yacc.c */ +#line 160 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_Concat, (yyvsp[(1) - (3)].exVal), (yyvsp[(3) - (3)].exVal), ctx); ;} + break; + + case 40: + +/* Line 1455 of yacc.c */ +#line 161 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); ;} + break; + + case 41: + +/* Line 1455 of yacc.c */ +#line 162 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(1) - (1)].exVal); ;} + break; + + case 42: + +/* Line 1455 of yacc.c */ +#line 163 "util_expr_parse.y" + { (yyval.exVal) = (yyvsp[(2) - (3)].exVal); ;} + break; + + case 43: + +/* Line 1455 of yacc.c */ +#line 164 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_make(op_String, "", NULL, ctx); ;} + break; + + case 44: + +/* Line 1455 of yacc.c */ +#line 167 "util_expr_parse.y" + { ap_regex_t *regex; - if ((regex = ap_pregcomp(context->pool, (yyvsp[(1) - (1)].cpVal), + if ((regex = ap_pregcomp(ctx->pool, (yyvsp[(1) - (1)].cpVal), AP_REG_EXTENDED|AP_REG_NOSUB)) == NULL) { - context->error = "Failed to compile regular expression"; + ctx->error = "Failed to compile regular expression"; YYERROR; } - (yyval.exVal) = ssl_expr_make(op_Regex, regex, NULL, context); + (yyval.exVal) = ap_expr_make(op_Regex, regex, NULL, ctx); ;} break; - case 28: + case 45: /* Line 1455 of yacc.c */ -#line 145 "ssl_expr_parse.y" +#line 176 "util_expr_parse.y" { ap_regex_t *regex; - if ((regex = ap_pregcomp(context->pool, (yyvsp[(1) - (1)].cpVal), + if ((regex = ap_pregcomp(ctx->pool, (yyvsp[(1) - (1)].cpVal), AP_REG_EXTENDED|AP_REG_NOSUB|AP_REG_ICASE)) == NULL) { - context->error = "Failed to compile regular expression"; + ctx->error = "Failed to compile regular expression"; YYERROR; } - (yyval.exVal) = ssl_expr_make(op_Regex, regex, NULL, context); + (yyval.exVal) = ap_expr_make(op_Regex, regex, NULL, ctx); ;} break; - case 29: + case 46: /* Line 1455 of yacc.c */ -#line 156 "ssl_expr_parse.y" - { - ssl_expr *args = ssl_expr_make(op_ListElement, (yyvsp[(3) - (4)].cpVal), NULL, context); - (yyval.exVal) = ssl_expr_make(op_Func, "file", args, context); - ;} +#line 187 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_list_func_make((yyvsp[(1) - (4)].cpVal), (yyvsp[(3) - (4)].exVal), ctx); ;} + break; + + case 47: + +/* Line 1455 of yacc.c */ +#line 190 "util_expr_parse.y" + { (yyval.exVal) = ap_expr_str_func_make((yyvsp[(1) - (4)].cpVal), (yyvsp[(3) - (4)].exVal), ctx); ;} break; /* Line 1455 of yacc.c */ -#line 1620 "ssl_expr_parse.c" +#line 1798 "util_expr_parse.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -1651,7 +1829,7 @@ yyerrlab: { ++yynerrs; #if ! YYERROR_VERBOSE - yyerror (context, YY_("syntax error")); + yyerror (ctx, YY_("syntax error")); #else { YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); @@ -1675,11 +1853,11 @@ yyerrlab: if (0 < yysize && yysize <= yymsg_alloc) { (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (context, yymsg); + yyerror (ctx, yymsg); } else { - yyerror (context, YY_("syntax error")); + yyerror (ctx, YY_("syntax error")); if (yysize != 0) goto yyexhaustedlab; } @@ -1703,7 +1881,7 @@ yyerrlab: else { yydestruct ("Error: discarding", - yytoken, &yylval, context); + yytoken, &yylval, ctx); yychar = YYEMPTY; } } @@ -1759,7 +1937,7 @@ yyerrlab1: yydestruct ("Error: popping", - yystos[yystate], yyvsp, context); + yystos[yystate], yyvsp, ctx); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); @@ -1794,7 +1972,7 @@ yyabortlab: | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: - yyerror (context, YY_("memory exhausted")); + yyerror (ctx, YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif @@ -1802,7 +1980,7 @@ yyexhaustedlab: yyreturn: if (yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, context); + yytoken, &yylval, ctx); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); @@ -1810,7 +1988,7 @@ yyreturn: while (yyssp != yyss) { yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp, context); + yystos[*yyssp], yyvsp, ctx); YYPOPSTACK (1); } #ifndef yyoverflow @@ -1828,13 +2006,12 @@ yyreturn: /* Line 1675 of yacc.c */ -#line 162 "ssl_expr_parse.y" +#line 193 "util_expr_parse.y" -int yyerror(ssl_expr_info_type *context, char *s) +void yyerror(ap_expr_parse_ctx *ctx, char *s) { - context->error = s; - return 2; + ctx->error = s; } diff --git a/modules/ssl/ssl_expr_parse.h b/server/util_expr_parse.h index e847372ee7..f806e0121f 100644 --- a/modules/ssl/ssl_expr_parse.h +++ b/server/util_expr_parse.h @@ -41,25 +41,37 @@ enum yytokentype { T_TRUE = 258, T_FALSE = 259, - T_DIGIT = 260, - T_ID = 261, - T_STRING = 262, - T_REGEX = 263, - T_REGEX_I = 264, - T_FUNC_FILE = 265, - T_OP_EQ = 266, - T_OP_NE = 267, - T_OP_LT = 268, - T_OP_LE = 269, - T_OP_GT = 270, - T_OP_GE = 271, - T_OP_REG = 272, - T_OP_NRE = 273, - T_OP_IN = 274, - T_OP_PEEREXTLIST = 275, - T_OP_OR = 276, - T_OP_AND = 277, - T_OP_NOT = 278 + ERROR = 260, + T_DIGIT = 261, + T_ID = 262, + T_STRING = 263, + T_REGEX = 264, + T_REGEX_I = 265, + T_OP_UNARY = 266, + T_OP_BINARY = 267, + T_STR_BEGIN = 268, + T_STR_END = 269, + T_VAR_BEGIN = 270, + T_VAR_END = 271, + T_OP_EQ = 272, + T_OP_NE = 273, + T_OP_LT = 274, + T_OP_LE = 275, + T_OP_GT = 276, + T_OP_GE = 277, + T_OP_REG = 278, + T_OP_NRE = 279, + T_OP_IN = 280, + T_OP_STR_EQ = 281, + T_OP_STR_NE = 282, + T_OP_STR_LT = 283, + T_OP_STR_LE = 284, + T_OP_STR_GT = 285, + T_OP_STR_GE = 286, + T_OP_CONCAT = 287, + T_OP_OR = 288, + T_OP_AND = 289, + T_OP_NOT = 290 }; #endif @@ -70,15 +82,15 @@ typedef union YYSTYPE { /* Line 1676 of yacc.c */ -#line 45 "ssl_expr_parse.y" +#line 35 "util_expr_parse.y" - char *cpVal; - ssl_expr *exVal; + char *cpVal; + ap_expr *exVal; /* Line 1676 of yacc.c */ -#line 82 "ssl_expr_parse.h" +#line 94 "util_expr_parse.h" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ diff --git a/server/util_expr_parse.y b/server/util_expr_parse.y new file mode 100644 index 0000000000..c79eee5940 --- /dev/null +++ b/server/util_expr_parse.y @@ -0,0 +1,199 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* based on ap_expr_parse.y from mod_ssl */ + +/* _________________________________________________________________ +** +** Expression Parser +** _________________________________________________________________ +*/ + +%pure-parser +%error-verbose +%defines +%lex-param { void *yyscanner } +%parse-param { ap_expr_parse_ctx *ctx } + +%{ +#include "util_expr_private.h" +%} + +%union { + char *cpVal; + ap_expr *exVal; +} + +%token T_TRUE +%token T_FALSE + +%token <cpVal> ERROR + +%token <cpVal> T_DIGIT +%token <cpVal> T_ID +%token <cpVal> T_STRING +%token <cpVal> T_REGEX +%token <cpVal> T_REGEX_I +%token <cpVal> T_OP_UNARY +%token <cpVal> T_OP_BINARY + +%token T_STR_BEGIN +%token T_STR_END +%token T_VAR_BEGIN +%token T_VAR_END + +%token T_OP_EQ +%token T_OP_NE +%token T_OP_LT +%token T_OP_LE +%token T_OP_GT +%token T_OP_GE +%token T_OP_REG +%token T_OP_NRE +%token T_OP_IN +%token T_OP_STR_EQ +%token T_OP_STR_NE +%token T_OP_STR_LT +%token T_OP_STR_LE +%token T_OP_STR_GT +%token T_OP_STR_GE +%token T_OP_CONCAT + +%token T_OP_OR +%token T_OP_AND +%token T_OP_NOT + +%left T_OP_OR +%left T_OP_AND +%left T_OP_NOT +%left T_OP_CONCAT + +%type <exVal> expr +%type <exVal> comparison +%type <exVal> strfunccall +%type <exVal> lstfunccall +%type <exVal> regex +%type <exVal> words +%type <exVal> wordlist +%type <exVal> word +%type <exVal> string +%type <exVal> strpart +%type <exVal> var + +%{ +#include "util_expr_private.h" +#define yyscanner ctx->scanner + +int ap_expr_yylex(YYSTYPE *lvalp, void *scanner); +%} + + +%% + +root : expr { ctx->expr = $1; } + | ERROR { YYABORT; } + ; + +expr : T_TRUE { $$ = ap_expr_make(op_True, NULL, NULL, ctx); } + | T_FALSE { $$ = ap_expr_make(op_False, NULL, NULL, ctx); } + | T_OP_NOT expr { $$ = ap_expr_make(op_Not, $2, NULL, ctx); } + | expr T_OP_OR expr { $$ = ap_expr_make(op_Or, $1, $3, ctx); } + | expr T_OP_AND expr { $$ = ap_expr_make(op_And, $1, $3, ctx); } + | comparison { $$ = ap_expr_make(op_Comp, $1, NULL, ctx); } + | T_OP_UNARY word { $$ = ap_expr_unary_op_make( $1, $2, ctx); } + | '(' expr ')' { $$ = $2; } + ; + +comparison: word T_OP_EQ word { $$ = ap_expr_make(op_EQ, $1, $3, ctx); } + | word T_OP_NE word { $$ = ap_expr_make(op_NE, $1, $3, ctx); } + | word T_OP_LT word { $$ = ap_expr_make(op_LT, $1, $3, ctx); } + | word T_OP_LE word { $$ = ap_expr_make(op_LE, $1, $3, ctx); } + | word T_OP_GT word { $$ = ap_expr_make(op_GT, $1, $3, ctx); } + | word T_OP_GE word { $$ = ap_expr_make(op_GE, $1, $3, ctx); } + | word T_OP_STR_EQ word { $$ = ap_expr_make(op_STR_EQ, $1, $3, ctx); } + | word T_OP_STR_NE word { $$ = ap_expr_make(op_STR_NE, $1, $3, ctx); } + | word T_OP_STR_LT word { $$ = ap_expr_make(op_STR_LT, $1, $3, ctx); } + | word T_OP_STR_LE word { $$ = ap_expr_make(op_STR_LE, $1, $3, ctx); } + | word T_OP_STR_GT word { $$ = ap_expr_make(op_STR_GT, $1, $3, ctx); } + | word T_OP_STR_GE word { $$ = ap_expr_make(op_STR_GE, $1, $3, ctx); } + | word T_OP_IN wordlist { $$ = ap_expr_make(op_IN, $1, $3, ctx); } + | word T_OP_REG regex { $$ = ap_expr_make(op_REG, $1, $3, ctx); } + | word T_OP_NRE regex { $$ = ap_expr_make(op_NRE, $1, $3, ctx); } + | word T_OP_BINARY word { $$ = ap_expr_binary_op_make($2, $1, $3, ctx); } + ; + +wordlist : lstfunccall { $$ = $1; } + | '{' words '}' { $$ = $2; } + ; + +words : word { $$ = ap_expr_make(op_ListElement, $1, NULL, ctx); } + | words ',' word { $$ = ap_expr_make(op_ListElement, $3, $1, ctx); } + ; + +string : string strpart { $$ = ap_expr_make(op_Concat, $1, $2, ctx); } + | strpart { $$ = $1; } + ; + + +strpart : T_STRING { $$ = ap_expr_make(op_String, $1, NULL, ctx); } + | var { $$ = $1; } + ; + +var : T_VAR_BEGIN T_ID T_VAR_END { $$ = ap_expr_var_make($2, ctx); } + | T_VAR_BEGIN T_ID ':' string T_VAR_END { $$ = ap_expr_str_func_make($2, $4, ctx); } + ; + +word : T_DIGIT { $$ = ap_expr_make(op_Digit, $1, NULL, ctx); } + | word T_OP_CONCAT word { $$ = ap_expr_make(op_Concat, $1, $3, ctx); } + | var { $$ = $1; } + | strfunccall { $$ = $1; } + | T_STR_BEGIN string T_STR_END { $$ = $2; } + | T_STR_BEGIN T_STR_END { $$ = ap_expr_make(op_String, "", NULL, ctx); } + ; + +regex : T_REGEX { + ap_regex_t *regex; + if ((regex = ap_pregcomp(ctx->pool, $1, + AP_REG_EXTENDED|AP_REG_NOSUB)) == NULL) { + ctx->error = "Failed to compile regular expression"; + YYERROR; + } + $$ = ap_expr_make(op_Regex, regex, NULL, ctx); + } + | T_REGEX_I { + ap_regex_t *regex; + if ((regex = ap_pregcomp(ctx->pool, $1, + AP_REG_EXTENDED|AP_REG_NOSUB|AP_REG_ICASE)) == NULL) { + ctx->error = "Failed to compile regular expression"; + YYERROR; + } + $$ = ap_expr_make(op_Regex, regex, NULL, ctx); + } + ; + +lstfunccall : T_ID '(' word ')' { $$ = ap_expr_list_func_make($1, $3, ctx); } + ; + +strfunccall : T_ID '(' word ')' { $$ = ap_expr_str_func_make($1, $3, ctx); } + ; + +%% + +void yyerror(ap_expr_parse_ctx *ctx, char *s) +{ + ctx->error = s; +} + diff --git a/server/util_expr_private.h b/server/util_expr_private.h new file mode 100644 index 0000000000..48d1199a79 --- /dev/null +++ b/server/util_expr_private.h @@ -0,0 +1,129 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __AP_EXPR_PRIVATE_H__ +#define __AP_EXPR_PRIVATE_H__ + +#include "httpd.h" +#include "apr_strings.h" +#include "apr_tables.h" +#include "ap_expr.h" + +#ifndef YY_NULL +#define YY_NULL 0 +#endif + +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + +#ifndef YYDEBUG +#define YYDEBUG 0 +#endif + +/** The operations in a parse tree node */ +typedef enum { + op_NOP, + op_True, op_False, + op_Not, op_Or, op_And, + op_Comp, + op_EQ, op_NE, op_LT, op_LE, op_GT, op_GE, op_IN, + op_REG, op_NRE, + op_STR_EQ, op_STR_NE, op_STR_LT, op_STR_LE, op_STR_GT, op_STR_GE, + op_Concat, + op_Digit, op_String, op_Regex, + op_Var, + op_ListElement, + /* + * call external functions/operators. + * The info node contains the function pointer and some function specific + * info. + * For Binary operators, the Call node links to the Info node and the + * Args node, which in turn links to the left and right operand. + * For all other variants, the Call node links to the Info node and the + * argument. + */ + op_UnaryOpCall, op_UnaryOpInfo, + op_BinaryOpCall, op_BinaryOpInfo, op_BinaryOpArgs, + op_StringFuncCall, op_StringFuncInfo, + op_ListFuncCall, op_ListFuncInfo +} ap_expr_node_op; + +/** The basic parse tree node */ +struct ap_expr_node { + ap_expr_node_op node_op; + const void *node_arg1; + const void *node_arg2; +}; + +/** The context used by scanner and parser */ +typedef struct { + /* internal state of the scanner */ + const char *inputbuf; + int inputlen; + const char *inputptr; + void *scanner; + char *scan_ptr; + char scan_buf[MAX_STRING_LEN]; + char scan_del; + + /* pools for result and temporary usage */ + apr_pool_t *pool; + apr_pool_t *ptemp; + + /* The created parse tree */ + ap_expr *expr; + + const char *error; + const char *error2; + unsigned flags; + + /* + * The function to use to lookup provider functions for variables + * and funtctions + */ + ap_expr_lookup_fn *lookup_fn; +} ap_expr_parse_ctx; + +/* flex/bison functions */ +int ap_expr_yyparse(ap_expr_parse_ctx *context); +void ap_expr_yyerror(ap_expr_parse_ctx *context, char *err); +int ap_expr_yylex_init(void **scanner); +int ap_expr_yylex_destroy(void *scanner); +void ap_expr_yyset_extra(ap_expr_parse_ctx *context, void *scanner); + +/* create a parse tree node */ +ap_expr *ap_expr_make(ap_expr_node_op op, const void *arg1, const void *arg2, + ap_expr_parse_ctx *ctx); +/* create parse tree node for the string-returning function 'name' */ +ap_expr *ap_expr_str_func_make(const char *name, const ap_expr *arg, + ap_expr_parse_ctx *ctx); +/* create parse tree node for the list-returning function 'name' */ +ap_expr *ap_expr_list_func_make(const char *name, const ap_expr *arg, + ap_expr_parse_ctx *ctx); +/* create parse tree node for the variable 'name' */ +ap_expr *ap_expr_var_make(const char *name, ap_expr_parse_ctx *ctx); +/* create parse tree node for the unary operator 'name' */ +ap_expr *ap_expr_unary_op_make(const char *name, const ap_expr *arg, + ap_expr_parse_ctx *ctx); +/* create parse tree node for the binary operator 'name' */ +ap_expr *ap_expr_binary_op_make(const char *name, const ap_expr *arg1, + const ap_expr *arg2, ap_expr_parse_ctx *ctx); + + +#endif /* __AP_EXPR_PRIVATE_H__ */ +/** @} */ + diff --git a/modules/ssl/ssl_expr_scan.c b/server/util_expr_scan.c index 1151692ea6..86e7a39eee 100644 --- a/modules/ssl/ssl_expr_scan.c +++ b/server/util_expr_scan.c @@ -1,6 +1,6 @@ -#line 2 "ssl_expr_scan.c" +#line 2 "util_expr_scan.c" -#line 4 "ssl_expr_scan.c" +#line 4 "util_expr_scan.c" #define YY_INT_ALIGNED short int @@ -153,7 +153,7 @@ typedef void* yyscan_t; #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE ssl_expr_yyrestart(yyin ,yyscanner ) +#define YY_NEW_FILE ap_expr_yyrestart(yyin ,yyscanner ) #define YY_END_OF_BUFFER_CHAR 0 @@ -263,7 +263,7 @@ struct yy_buffer_state * possible backing-up. * * When we actually see the EOF, we change the status to "new" - * (via ssl_expr_yyrestart()), so that the user can continue scanning by + * (via ap_expr_yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 @@ -286,36 +286,36 @@ struct yy_buffer_state */ #define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] -void ssl_expr_yyrestart (FILE *input_file ,yyscan_t yyscanner ); -void ssl_expr_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); -YY_BUFFER_STATE ssl_expr_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); -void ssl_expr_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); -void ssl_expr_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); -void ssl_expr_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); -void ssl_expr_yypop_buffer_state (yyscan_t yyscanner ); +void ap_expr_yyrestart (FILE *input_file ,yyscan_t yyscanner ); +void ap_expr_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +YY_BUFFER_STATE ap_expr_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); +void ap_expr_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void ap_expr_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void ap_expr_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +void ap_expr_yypop_buffer_state (yyscan_t yyscanner ); -static void ssl_expr_yyensure_buffer_stack (yyscan_t yyscanner ); -static void ssl_expr_yy_load_buffer_state (yyscan_t yyscanner ); -static void ssl_expr_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); +static void ap_expr_yyensure_buffer_stack (yyscan_t yyscanner ); +static void ap_expr_yy_load_buffer_state (yyscan_t yyscanner ); +static void ap_expr_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); -#define YY_FLUSH_BUFFER ssl_expr_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner) +#define YY_FLUSH_BUFFER ap_expr_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner) -YY_BUFFER_STATE ssl_expr_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); -YY_BUFFER_STATE ssl_expr_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); -YY_BUFFER_STATE ssl_expr_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); +YY_BUFFER_STATE ap_expr_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); +YY_BUFFER_STATE ap_expr_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); +YY_BUFFER_STATE ap_expr_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); -void *ssl_expr_yyalloc (yy_size_t ,yyscan_t yyscanner ); -void *ssl_expr_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); -void ssl_expr_yyfree (void * ,yyscan_t yyscanner ); +void *ap_expr_yyalloc (yy_size_t ,yyscan_t yyscanner ); +void *ap_expr_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); +void ap_expr_yyfree (void * ,yyscan_t yyscanner ); -#define yy_new_buffer ssl_expr_yy_create_buffer +#define yy_new_buffer ap_expr_yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ - ssl_expr_yyensure_buffer_stack (yyscanner); \ + ap_expr_yyensure_buffer_stack (yyscanner); \ YY_CURRENT_BUFFER_LVALUE = \ - ssl_expr_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + ap_expr_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } @@ -323,9 +323,9 @@ void ssl_expr_yyfree (void * ,yyscan_t yyscanner ); #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ - ssl_expr_yyensure_buffer_stack (yyscanner); \ + ap_expr_yyensure_buffer_stack (yyscanner); \ YY_CURRENT_BUFFER_LVALUE = \ - ssl_expr_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + ap_expr_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } @@ -334,7 +334,7 @@ void ssl_expr_yyfree (void * ,yyscan_t yyscanner ); /* Begin user sect3 */ -#define ssl_expr_yywrap(n) 1 +#define ap_expr_yywrap(n) 1 #define YY_SKIP_YYWRAP typedef unsigned char YY_CHAR; @@ -358,8 +358,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); *yy_cp = '\0'; \ yyg->yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 47 -#define YY_END_OF_BUFFER 48 +#define YY_NUM_RULES 65 +#define YY_END_OF_BUFFER 66 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -367,19 +367,21 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[97] = +static yyconst flex_int16_t yy_accept[119] = { 0, - 0, 0, 0, 0, 0, 0, 0, 0, 48, 46, - 1, 38, 2, 46, 44, 24, 46, 28, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 46, 13, 4, 3, 14, 16, 18, 17, 1, 22, - 32, 34, 44, 26, 20, 31, 30, 45, 45, 45, - 19, 45, 45, 29, 27, 39, 25, 23, 15, 15, - 21, 45, 35, 45, 36, 13, 12, 5, 6, 10, - 11, 7, 8, 9, 45, 33, 45, 45, 37, 45, - 5, 6, 45, 45, 41, 42, 5, 45, 43, 45, - 45, 45, 45, 45, 40, 0 - + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 66, 64, 1, 41, 2, 64, 64, 63, + 64, 42, 24, 61, 30, 28, 32, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 64, 13, + 4, 3, 16, 65, 16, 21, 4, 20, 18, 19, + 65, 15, 22, 25, 27, 26, 1, 29, 35, 17, + 37, 61, 57, 57, 57, 57, 57, 57, 31, 28, + 34, 33, 62, 62, 55, 62, 53, 52, 56, 51, + 50, 23, 23, 54, 62, 38, 62, 39, 13, 14, + 12, 5, 6, 10, 11, 7, 8, 9, 18, 58, + + 44, 46, 48, 43, 47, 49, 45, 36, 62, 40, + 62, 5, 6, 62, 59, 5, 60, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -387,17 +389,17 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 4, 5, 1, 1, 1, 6, 1, 1, - 1, 1, 1, 1, 7, 1, 1, 8, 8, 8, - 8, 8, 8, 8, 8, 9, 9, 7, 1, 10, - 11, 12, 1, 1, 13, 13, 13, 13, 14, 13, - 13, 13, 15, 13, 13, 16, 13, 13, 13, 17, - 13, 18, 19, 20, 13, 13, 13, 21, 13, 13, - 1, 22, 1, 1, 7, 1, 23, 24, 13, 25, - - 26, 27, 28, 13, 29, 13, 13, 30, 31, 32, - 33, 17, 34, 35, 36, 37, 38, 13, 13, 21, - 13, 13, 1, 39, 1, 40, 1, 1, 1, 1, + 1, 2, 4, 5, 6, 6, 7, 8, 5, 9, + 9, 1, 1, 10, 11, 12, 13, 14, 14, 14, + 14, 14, 14, 14, 14, 15, 15, 16, 6, 17, + 18, 19, 6, 1, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 1, 21, 1, 6, 22, 1, 23, 24, 20, 25, + + 26, 27, 28, 20, 29, 20, 20, 30, 31, 32, + 33, 20, 34, 35, 36, 37, 38, 20, 20, 20, + 20, 20, 39, 40, 41, 42, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -414,100 +416,125 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst flex_int32_t yy_meta[41] = +static yyconst flex_int32_t yy_meta[43] = { 0, - 1, 1, 2, 1, 3, 1, 4, 4, 4, 1, - 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 1, 1 + 1, 1, 2, 1, 2, 1, 2, 1, 1, 1, + 1, 1, 1, 3, 3, 1, 1, 1, 1, 3, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, + 2, 1 } ; -static yyconst flex_int16_t yy_base[104] = +static yyconst flex_int16_t yy_base[128] = { 0, - 0, 0, 38, 39, 0, 0, 101, 100, 128, 174, - 43, 36, 174, 121, 40, 115, 39, 114, 0, 37, - 92, 89, 29, 27, 90, 28, 79, 29, 82, 81, - 76, 0, 174, 174, 112, 174, 174, 174, 54, 174, - 174, 174, 58, 174, 174, 174, 174, 0, 45, 87, - 0, 81, 80, 0, 0, 0, 0, 0, 174, 0, - 0, 71, 0, 69, 174, 0, 174, 60, 64, 174, - 174, 174, 174, 174, 52, 0, 70, 79, 0, 78, - 66, 69, 68, 74, 0, 0, 84, 78, 0, 66, - 72, 80, 77, 77, 0, 174, 149, 153, 157, 94, - - 161, 165, 169 + 0, 0, 40, 41, 82, 0, 122, 123, 0, 0, + 138, 133, 161, 260, 47, 33, 260, 121, 151, 260, + 151, 260, 260, 38, 140, 36, 139, 0, 124, 121, + 131, 29, 121, 30, 180, 31, 117, 116, 110, 0, + 260, 260, 110, 207, 260, 260, 260, 260, 0, 260, + 260, 260, 260, 260, 260, 260, 56, 260, 260, 260, + 260, 54, 0, 114, 34, 115, 37, 120, 260, 260, + 260, 260, 0, 120, 0, 112, 0, 0, 0, 0, + 0, 260, 0, 0, 104, 0, 102, 260, 0, 260, + 260, 58, 62, 260, 260, 260, 260, 260, 0, 260, + + 260, 260, 260, 260, 260, 260, 260, 0, 103, 0, + 112, 65, 117, 111, 0, 119, 0, 260, 244, 247, + 250, 133, 132, 253, 256, 67, 62 } ; -static yyconst flex_int16_t yy_def[104] = +static yyconst flex_int16_t yy_def[128] = { 0, - 96, 1, 97, 97, 98, 98, 99, 99, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 100, 100, - 100, 100, 100, 100, 100, 100, 101, 100, 100, 100, - 96, 102, 96, 96, 103, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 100, 100, 100, - 100, 100, 100, 100, 100, 100, 100, 100, 96, 100, - 100, 100, 100, 100, 96, 102, 96, 96, 96, 96, - 96, 96, 96, 96, 100, 100, 100, 100, 100, 100, - 96, 96, 100, 100, 100, 100, 96, 100, 100, 100, - 100, 100, 100, 100, 100, 0, 96, 96, 96, 96, - - 96, 96, 96 + 118, 1, 119, 119, 118, 5, 119, 119, 120, 120, + 121, 121, 118, 118, 118, 118, 118, 118, 118, 118, + 122, 118, 118, 118, 118, 118, 118, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 118, 124, + 118, 118, 118, 125, 118, 118, 118, 118, 126, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 127, 127, 127, 127, 127, 127, 118, 118, + 118, 118, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 118, 123, 123, 123, 123, 123, 118, 124, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 126, 118, + + 118, 118, 118, 118, 118, 118, 118, 123, 123, 123, + 123, 118, 118, 123, 123, 118, 123, 0, 118, 118, + 118, 118, 118, 118, 118, 118, 118 } ; -static yyconst flex_int16_t yy_nxt[215] = +static yyconst flex_int16_t yy_nxt[303] = { 0, - 10, 11, 11, 12, 13, 14, 10, 15, 15, 16, - 17, 18, 19, 19, 19, 19, 20, 19, 19, 19, - 19, 10, 21, 19, 19, 22, 23, 24, 25, 26, - 27, 28, 29, 19, 19, 19, 30, 19, 31, 10, - 33, 33, 34, 34, 39, 39, 40, 43, 43, 45, - 49, 52, 54, 57, 61, 39, 39, 53, 75, 35, - 35, 62, 49, 55, 58, 43, 43, 81, 82, 83, - 75, 82, 82, 87, 82, 41, 82, 82, 46, 59, - 59, 88, 59, 59, 59, 91, 83, 92, 59, 59, - 59, 82, 82, 88, 93, 94, 95, 48, 90, 89, - - 59, 92, 91, 86, 85, 84, 80, 79, 93, 78, - 77, 76, 94, 95, 65, 64, 63, 59, 59, 68, - 69, 56, 51, 50, 47, 44, 42, 96, 38, 38, - 96, 96, 96, 96, 96, 70, 96, 96, 71, 96, - 96, 96, 96, 72, 96, 96, 73, 96, 74, 32, - 32, 32, 32, 36, 36, 36, 36, 37, 37, 37, - 37, 60, 96, 60, 60, 66, 96, 96, 66, 67, - 67, 67, 67, 9, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96 + 14, 15, 15, 16, 17, 14, 18, 19, 20, 20, + 21, 22, 23, 24, 24, 20, 25, 26, 27, 28, + 14, 14, 29, 28, 28, 30, 31, 32, 33, 34, + 35, 36, 37, 28, 28, 28, 38, 28, 20, 39, + 20, 14, 41, 41, 42, 42, 43, 43, 57, 57, + 58, 62, 62, 70, 77, 80, 84, 57, 57, 102, + 44, 44, 105, 85, 100, 78, 81, 62, 62, 99, + 103, 112, 113, 106, 59, 113, 113, 71, 116, 113, + 45, 45, 46, 46, 47, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 48, 46, 46, + + 46, 49, 46, 46, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 46, 46, 50, 46, 41, 41, 51, 51, 52, 52, + 113, 113, 113, 113, 73, 63, 117, 115, 114, 111, + 110, 109, 44, 44, 108, 107, 104, 101, 90, 88, + 87, 86, 79, 76, 75, 74, 72, 69, 61, 60, + 118, 56, 53, 53, 62, 62, 56, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 64, 118, 65, 66, + 67, 118, 68, 82, 82, 82, 82, 118, 118, 82, + 82, 82, 82, 118, 118, 82, 118, 118, 118, 118, + + 118, 83, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 82, + 92, 93, 118, 118, 118, 118, 118, 118, 118, 118, + 94, 118, 118, 95, 118, 118, 118, 118, 96, 118, + 118, 97, 118, 98, 40, 40, 40, 54, 54, 54, + 55, 55, 55, 89, 118, 89, 91, 91, 91, 13, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + + 118, 118 } ; -static yyconst flex_int16_t yy_chk[215] = +static yyconst flex_int16_t yy_chk[303] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 3, 4, 3, 4, 11, 11, 12, 15, 15, 17, - 20, 23, 24, 26, 28, 39, 39, 23, 49, 3, - 4, 28, 20, 24, 26, 43, 43, 68, 68, 75, - 49, 69, 69, 81, 81, 12, 82, 82, 17, 27, - 27, 83, 27, 27, 27, 90, 75, 91, 27, 27, - 27, 87, 87, 83, 92, 93, 94, 100, 88, 84, - - 27, 91, 90, 80, 78, 77, 64, 62, 92, 53, - 52, 50, 93, 94, 31, 30, 29, 27, 27, 35, - 35, 25, 22, 21, 18, 16, 14, 9, 8, 7, - 0, 0, 0, 0, 0, 35, 0, 0, 35, 0, - 0, 0, 0, 35, 0, 0, 35, 0, 35, 97, - 97, 97, 97, 98, 98, 98, 98, 99, 99, 99, - 99, 101, 0, 101, 101, 102, 0, 0, 102, 103, - 103, 103, 103, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - - 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 96, 96 + 1, 1, 3, 4, 3, 4, 3, 4, 15, 15, + 16, 24, 24, 26, 32, 34, 36, 57, 57, 65, + 3, 4, 67, 36, 127, 32, 34, 62, 62, 126, + 65, 92, 92, 67, 16, 93, 93, 26, 112, 112, + 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 7, 8, 7, 8, 7, 8, + 113, 113, 116, 116, 123, 122, 114, 111, 109, 87, + 85, 76, 7, 8, 74, 68, 66, 64, 43, 39, + 38, 37, 33, 31, 30, 29, 27, 25, 19, 18, + 13, 12, 7, 8, 21, 21, 11, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 21, 0, 21, 21, + 21, 0, 21, 35, 35, 35, 35, 0, 0, 35, + 35, 35, 35, 0, 0, 35, 0, 0, 0, 0, + + 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, + 44, 44, 0, 0, 0, 0, 0, 0, 0, 0, + 44, 0, 0, 44, 0, 0, 0, 0, 44, 0, + 0, 44, 0, 44, 119, 119, 119, 120, 120, 120, + 121, 121, 121, 124, 0, 124, 125, 125, 125, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + + 118, 118 } ; /* The intent behind this definition is that it'll catch @@ -517,7 +544,7 @@ static yyconst flex_int16_t yy_chk[215] = #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET -#line 1 "ssl_expr_scan.l" +#line 1 "util_expr_scan.l" /* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. @@ -533,18 +560,9 @@ static yyconst flex_int16_t yy_chk[215] = * See the License for the specific language governing permissions and * limitations under the License. */ -/* _ _ - * _ __ ___ ___ __| | ___ ___| | - * | '_ ` _ \ / _ \ / _` | / __/ __| | - * | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to OpenSSL - * |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.modssl.org/ - * |_____| - * ssl_expr_scan.l - * Expression Scanner +/* + * ap_expr_scan.l, based on ssl_expr_scan.l from mod_ssl */ -/* ``Killing for peace is -like fucking for virginity.'' --- Unknown */ /* _________________________________________________________________ ** ** Expression Scanner @@ -553,11 +571,11 @@ like fucking for virginity.'' #define YY_NO_INPUT 1 -#line 49 "ssl_expr_scan.l" -#include "ssl_private.h" -#include "ssl_expr_parse.h" -#include "ssl_expr.h" + +#line 43 "util_expr_scan.l" +#include "util_expr_private.h" +#include "util_expr_parse.h" #undef YY_INPUT #define YY_INPUT(buf,result,max_size) \ @@ -574,14 +592,22 @@ like fucking for virginity.'' } \ } -#define MAX_STR_LEN 2048 -#define YY_EXTRA_TYPE ssl_expr_info_type* -#line 580 "ssl_expr_scan.c" +#define YY_EXTRA_TYPE ap_expr_parse_ctx* + +#define PERROR(msg) yyextra->error2 = msg ; return ERROR; + +#define str_ptr (yyextra->scan_ptr) +#define str_buf (yyextra->scan_buf) +#define str_del (yyextra->scan_del) + +#line 604 "util_expr_scan.c" #define INITIAL 0 #define str 1 -#define regex 2 -#define regex_flags 3 +#define var 2 +#define vararg 3 +#define regex 4 +#define regex_flags 5 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way @@ -637,42 +663,42 @@ static int yy_init_globals (yyscan_t yyscanner ); * from bison output in section 1.*/ # define yylval yyg->yylval_r -int ssl_expr_yylex_init (yyscan_t* scanner); +int ap_expr_yylex_init (yyscan_t* scanner); -int ssl_expr_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); +int ap_expr_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ -int ssl_expr_yylex_destroy (yyscan_t yyscanner ); +int ap_expr_yylex_destroy (yyscan_t yyscanner ); -int ssl_expr_yyget_debug (yyscan_t yyscanner ); +int ap_expr_yyget_debug (yyscan_t yyscanner ); -void ssl_expr_yyset_debug (int debug_flag ,yyscan_t yyscanner ); +void ap_expr_yyset_debug (int debug_flag ,yyscan_t yyscanner ); -YY_EXTRA_TYPE ssl_expr_yyget_extra (yyscan_t yyscanner ); +YY_EXTRA_TYPE ap_expr_yyget_extra (yyscan_t yyscanner ); -void ssl_expr_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); +void ap_expr_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); -FILE *ssl_expr_yyget_in (yyscan_t yyscanner ); +FILE *ap_expr_yyget_in (yyscan_t yyscanner ); -void ssl_expr_yyset_in (FILE * in_str ,yyscan_t yyscanner ); +void ap_expr_yyset_in (FILE * in_str ,yyscan_t yyscanner ); -FILE *ssl_expr_yyget_out (yyscan_t yyscanner ); +FILE *ap_expr_yyget_out (yyscan_t yyscanner ); -void ssl_expr_yyset_out (FILE * out_str ,yyscan_t yyscanner ); +void ap_expr_yyset_out (FILE * out_str ,yyscan_t yyscanner ); -int ssl_expr_yyget_leng (yyscan_t yyscanner ); +int ap_expr_yyget_leng (yyscan_t yyscanner ); -char *ssl_expr_yyget_text (yyscan_t yyscanner ); +char *ap_expr_yyget_text (yyscan_t yyscanner ); -int ssl_expr_yyget_lineno (yyscan_t yyscanner ); +int ap_expr_yyget_lineno (yyscan_t yyscanner ); -void ssl_expr_yyset_lineno (int line_number ,yyscan_t yyscanner ); +void ap_expr_yyset_lineno (int line_number ,yyscan_t yyscanner ); -YYSTYPE * ssl_expr_yyget_lval (yyscan_t yyscanner ); +YYSTYPE * ap_expr_yyget_lval (yyscan_t yyscanner ); -void ssl_expr_yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); +void ap_expr_yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); /* Macros after this point can all be overridden by user definitions in * section 1. @@ -680,9 +706,9 @@ void ssl_expr_yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus -extern "C" int ssl_expr_yywrap (yyscan_t yyscanner ); +extern "C" int ap_expr_yywrap (yyscan_t yyscanner ); #else -extern int ssl_expr_yywrap (yyscan_t yyscanner ); +extern int ap_expr_yywrap (yyscan_t yyscanner ); #endif #endif @@ -704,6 +730,12 @@ static int input (yyscan_t yyscanner ); #endif + static void yy_push_state (int new_state ,yyscan_t yyscanner); + + static void yy_pop_state (yyscan_t yyscanner ); + + static int yy_top_state (yyscan_t yyscanner ); + /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #ifdef __ia64__ @@ -784,10 +816,10 @@ static int input (yyscan_t yyscanner ); #ifndef YY_DECL #define YY_DECL_IS_OURS 1 -extern int ssl_expr_yylex \ +extern int ap_expr_yylex \ (YYSTYPE * yylval_param ,yyscan_t yyscanner); -#define YY_DECL int ssl_expr_yylex \ +#define YY_DECL int ap_expr_yylex \ (YYSTYPE * yylval_param , yyscan_t yyscanner) #endif /* !YY_DECL */ @@ -815,19 +847,17 @@ YY_DECL register int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; -#line 74 "ssl_expr_scan.l" +#line 72 "util_expr_scan.l" - - char caStr[MAX_STR_LEN]; - char *cpStr = NULL; - char caRegex[MAX_STR_LEN]; - char *cpRegex = NULL; - char cRegexDel = NUL; + + char regex_buf[MAX_STRING_LEN]; + char *regex_ptr = NULL; + char regex_del = '\0'; /* * Whitespaces */ -#line 831 "ssl_expr_scan.c" +#line 861 "util_expr_scan.c" yylval = yylval_param; @@ -849,12 +879,12 @@ YY_DECL yyout = stdout; if ( ! YY_CURRENT_BUFFER ) { - ssl_expr_yyensure_buffer_stack (yyscanner); + ap_expr_yyensure_buffer_stack (yyscanner); YY_CURRENT_BUFFER_LVALUE = - ssl_expr_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + ap_expr_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); } - ssl_expr_yy_load_buffer_state(yyscanner ); + ap_expr_yy_load_buffer_state(yyscanner ); } while ( 1 ) /* loops until end-of-file is reached */ @@ -882,13 +912,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 97 ) + if ( yy_current_state >= 119 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_current_state != 96 ); + while ( yy_current_state != 118 ); yy_cp = yyg->yy_last_accepting_cpos; yy_current_state = yyg->yy_last_accepting_state; @@ -911,303 +941,474 @@ do_action: /* This label is used only to access EOF actions. */ case 1: /* rule 1 can match eol */ YY_RULE_SETUP -#line 85 "ssl_expr_scan.l" +#line 81 "util_expr_scan.l" { /* NOP */ } YY_BREAK /* - * C-style strings ("...") + * strings ("..." and '...') */ case 2: YY_RULE_SETUP -#line 92 "ssl_expr_scan.l" +#line 88 "util_expr_scan.l" { - cpStr = caStr; + str_ptr = str_buf; + str_del = yytext[0]; BEGIN(str); + return T_STR_BEGIN; } YY_BREAK case 3: YY_RULE_SETUP -#line 96 "ssl_expr_scan.l" +#line 94 "util_expr_scan.l" { - BEGIN(INITIAL); - *cpStr = NUL; - yylval->cpVal = apr_pstrdup(yyextra->pool, caStr); - return T_STRING; + if (yytext[0] == str_del) { + if (YY_START == var) { + PERROR("Unterminated variable in string"); + } + else if (str_ptr == str_buf) { + BEGIN(INITIAL); + return T_STR_END; + } + else { + /* return what we have so far and scan delimiter again */ + *str_ptr = '\0'; + yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf); + yyless(0); + str_ptr = str_buf; + return T_STRING; + } + } + else { + *str_ptr++ = yytext[0]; + } } YY_BREAK case 4: /* rule 4 can match eol */ YY_RULE_SETUP -#line 102 "ssl_expr_scan.l" +#line 116 "util_expr_scan.l" { - ssl_expr_yyerror(yyextra, "Unterminated string"); + PERROR("Unterminated string or variable"); +} + YY_BREAK +case YY_STATE_EOF(str): +case YY_STATE_EOF(var): +case YY_STATE_EOF(vararg): +#line 119 "util_expr_scan.l" +{ + PERROR("Unterminated string or variable"); } YY_BREAK case 5: YY_RULE_SETUP -#line 105 "ssl_expr_scan.l" +#line 122 "util_expr_scan.l" { int result; (void)sscanf(yytext+1, "%o", &result); - if (result > 0xff) - ssl_expr_yyerror(yyextra, "Escape sequence out of bound"); - else - *cpStr++ = result; + if (result > 0xff) { + PERROR("Escape sequence out of bound"); + } + else { + *str_ptr++ = result; + } } YY_BREAK case 6: YY_RULE_SETUP -#line 114 "ssl_expr_scan.l" +#line 133 "util_expr_scan.l" { - ssl_expr_yyerror(yyextra, "Bad escape sequence"); + PERROR("Bad escape sequence"); } YY_BREAK case 7: YY_RULE_SETUP -#line 117 "ssl_expr_scan.l" -{ *cpStr++ = '\n'; } +#line 136 "util_expr_scan.l" +{ *str_ptr++ = '\n'; } YY_BREAK case 8: YY_RULE_SETUP -#line 118 "ssl_expr_scan.l" -{ *cpStr++ = '\r'; } +#line 137 "util_expr_scan.l" +{ *str_ptr++ = '\r'; } YY_BREAK case 9: YY_RULE_SETUP -#line 119 "ssl_expr_scan.l" -{ *cpStr++ = '\t'; } +#line 138 "util_expr_scan.l" +{ *str_ptr++ = '\t'; } YY_BREAK case 10: YY_RULE_SETUP -#line 120 "ssl_expr_scan.l" -{ *cpStr++ = '\b'; } +#line 139 "util_expr_scan.l" +{ *str_ptr++ = '\b'; } YY_BREAK case 11: YY_RULE_SETUP -#line 121 "ssl_expr_scan.l" -{ *cpStr++ = '\f'; } +#line 140 "util_expr_scan.l" +{ *str_ptr++ = '\f'; } YY_BREAK case 12: /* rule 12 can match eol */ YY_RULE_SETUP -#line 122 "ssl_expr_scan.l" +#line 141 "util_expr_scan.l" { - *cpStr++ = yytext[1]; + *str_ptr++ = yytext[1]; } YY_BREAK case 13: YY_RULE_SETUP -#line 125 "ssl_expr_scan.l" +#line 145 "util_expr_scan.l" { char *cp = yytext; - while (*cp != NUL) - *cpStr++ = *cp++; + while (*cp != '\0') + *str_ptr++ = *cp++; } YY_BREAK +/* variable inside string */ case 14: YY_RULE_SETUP -#line 130 "ssl_expr_scan.l" +#line 152 "util_expr_scan.l" { - *cpStr++ = yytext[1]; + if (str_ptr != str_buf) { + /* return what we have so far and scan '%{' again */ + *str_ptr = '\0'; + yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf); + yyless(0); + str_ptr = str_buf; + return T_STRING; + } + else { + yy_push_state(var, yyscanner); + return T_VAR_BEGIN; + } } YY_BREAK -/* - * Regular Expression - */ case 15: YY_RULE_SETUP -#line 137 "ssl_expr_scan.l" +#line 167 "util_expr_scan.l" { - cRegexDel = yytext[1]; - cpRegex = caRegex; - BEGIN(regex); + *str_ptr++ = yytext[0]; } YY_BREAK case 16: -/* rule 16 can match eol */ YY_RULE_SETUP -#line 142 "ssl_expr_scan.l" +#line 171 "util_expr_scan.l" { - if (yytext[0] == cRegexDel) { - *cpRegex = NUL; - BEGIN(regex_flags); - } - else { - *cpRegex++ = yytext[0]; - } + *str_ptr++ = yytext[0]; } YY_BREAK case 17: YY_RULE_SETUP -#line 151 "ssl_expr_scan.l" +#line 175 "util_expr_scan.l" { - yylval->cpVal = apr_pstrdup(yyextra->pool, caRegex); - BEGIN(INITIAL); - return T_REGEX_I; + yy_push_state(var, yyscanner); + return T_VAR_BEGIN; } YY_BREAK +/* + * fixed name variable expansion %{XXX} and function call in %{func:arg} syntax + */ case 18: -/* rule 18 can match eol */ YY_RULE_SETUP -#line 156 "ssl_expr_scan.l" -{ - yylval->cpVal = apr_pstrdup(yyextra->pool, caRegex); - yyless(0); - BEGIN(INITIAL); - return T_REGEX; -} - YY_BREAK -case YY_STATE_EOF(regex_flags): -#line 162 "ssl_expr_scan.l" +#line 183 "util_expr_scan.l" { - yylval->cpVal = apr_pstrdup(yyextra->pool, caRegex); - BEGIN(INITIAL); - return T_REGEX; + yylval->cpVal = apr_pstrdup(yyextra->pool, yytext); + return T_ID; } YY_BREAK -/* - * Operators - */ case 19: YY_RULE_SETUP -#line 171 "ssl_expr_scan.l" -{ return T_OP_EQ; } +#line 188 "util_expr_scan.l" +{ + yy_pop_state(yyscanner); + return T_VAR_END; +} YY_BREAK case 20: YY_RULE_SETUP -#line 172 "ssl_expr_scan.l" -{ return T_OP_EQ; } +#line 193 "util_expr_scan.l" +{ + BEGIN(vararg); + return yytext[0]; +} YY_BREAK case 21: +/* rule 21 can match eol */ YY_RULE_SETUP -#line 173 "ssl_expr_scan.l" -{ return T_OP_NE; } +#line 198 "util_expr_scan.l" +{ + char c[2] = { yytext[0], '\0' }; + char *msg = apr_psprintf(yyextra->pool, + "Invalid character in variable name '%s'", c); + PERROR(msg); +} YY_BREAK case 22: YY_RULE_SETUP -#line 174 "ssl_expr_scan.l" -{ return T_OP_NE; } +#line 205 "util_expr_scan.l" +{ + if (str_ptr != str_buf) { + /* return what we have so far and scan '}' again */ + *str_ptr = '\0'; + yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf); + str_ptr = str_buf; + yyless(0); + return T_STRING; + } + else { + yy_pop_state(yyscanner); + return T_VAR_END; + } +} YY_BREAK +/* + * Regular Expression + */ case 23: YY_RULE_SETUP -#line 175 "ssl_expr_scan.l" -{ return T_OP_LT; } +#line 223 "util_expr_scan.l" +{ + regex_del = yytext[1]; + regex_ptr = regex_buf; + BEGIN(regex); +} YY_BREAK case 24: YY_RULE_SETUP -#line 176 "ssl_expr_scan.l" -{ return T_OP_LT; } +#line 228 "util_expr_scan.l" +{ + regex_del = yytext[0]; + regex_ptr = regex_buf; + BEGIN(regex); +} YY_BREAK case 25: +/* rule 25 can match eol */ YY_RULE_SETUP -#line 177 "ssl_expr_scan.l" -{ return T_OP_LE; } +#line 233 "util_expr_scan.l" +{ + if (yytext[0] == regex_del) { + *regex_ptr = '\0'; + BEGIN(regex_flags); + } + else { + *regex_ptr++ = yytext[0]; + } +} YY_BREAK case 26: YY_RULE_SETUP -#line 178 "ssl_expr_scan.l" -{ return T_OP_LE; } +#line 242 "util_expr_scan.l" +{ + yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf); + BEGIN(INITIAL); + return T_REGEX_I; +} YY_BREAK case 27: +/* rule 27 can match eol */ YY_RULE_SETUP -#line 179 "ssl_expr_scan.l" -{ return T_OP_GT; } +#line 247 "util_expr_scan.l" +{ + yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf); + yyless(0); + BEGIN(INITIAL); + return T_REGEX; +} YY_BREAK +case YY_STATE_EOF(regex_flags): +#line 253 "util_expr_scan.l" +{ + yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf); + BEGIN(INITIAL); + return T_REGEX; +} + YY_BREAK +/* + * Operators + */ case 28: YY_RULE_SETUP -#line 180 "ssl_expr_scan.l" -{ return T_OP_GT; } +#line 262 "util_expr_scan.l" +{ return T_OP_STR_EQ; } YY_BREAK case 29: YY_RULE_SETUP -#line 181 "ssl_expr_scan.l" -{ return T_OP_GE; } +#line 263 "util_expr_scan.l" +{ return T_OP_STR_NE; } YY_BREAK case 30: YY_RULE_SETUP -#line 182 "ssl_expr_scan.l" -{ return T_OP_GE; } +#line 264 "util_expr_scan.l" +{ return T_OP_STR_LT; } YY_BREAK case 31: YY_RULE_SETUP -#line 183 "ssl_expr_scan.l" -{ return T_OP_REG; } +#line 265 "util_expr_scan.l" +{ return T_OP_STR_LE; } YY_BREAK case 32: YY_RULE_SETUP -#line 184 "ssl_expr_scan.l" -{ return T_OP_NRE; } +#line 266 "util_expr_scan.l" +{ return T_OP_STR_GT; } YY_BREAK case 33: YY_RULE_SETUP -#line 185 "ssl_expr_scan.l" -{ return T_OP_AND; } +#line 267 "util_expr_scan.l" +{ return T_OP_STR_GE; } YY_BREAK case 34: YY_RULE_SETUP -#line 186 "ssl_expr_scan.l" -{ return T_OP_AND; } +#line 268 "util_expr_scan.l" +{ return T_OP_REG; } YY_BREAK case 35: YY_RULE_SETUP -#line 187 "ssl_expr_scan.l" -{ return T_OP_OR; } +#line 269 "util_expr_scan.l" +{ return T_OP_NRE; } YY_BREAK case 36: YY_RULE_SETUP -#line 188 "ssl_expr_scan.l" -{ return T_OP_OR; } +#line 270 "util_expr_scan.l" +{ return T_OP_AND; } YY_BREAK case 37: YY_RULE_SETUP -#line 189 "ssl_expr_scan.l" -{ return T_OP_NOT; } +#line 271 "util_expr_scan.l" +{ return T_OP_AND; } YY_BREAK case 38: YY_RULE_SETUP -#line 190 "ssl_expr_scan.l" -{ return T_OP_NOT; } +#line 272 "util_expr_scan.l" +{ return T_OP_OR; } YY_BREAK case 39: YY_RULE_SETUP -#line 191 "ssl_expr_scan.l" -{ return T_OP_IN; } +#line 273 "util_expr_scan.l" +{ return T_OP_OR; } YY_BREAK case 40: YY_RULE_SETUP -#line 192 "ssl_expr_scan.l" -{ return T_OP_PEEREXTLIST; } +#line 274 "util_expr_scan.l" +{ return T_OP_NOT; } YY_BREAK -/* - * Functions - */ case 41: YY_RULE_SETUP -#line 197 "ssl_expr_scan.l" -{ return T_FUNC_FILE; } +#line 275 "util_expr_scan.l" +{ return T_OP_NOT; } + YY_BREAK +case 42: +YY_RULE_SETUP +#line 276 "util_expr_scan.l" +{ return T_OP_CONCAT; } + YY_BREAK +case 43: +YY_RULE_SETUP +#line 277 "util_expr_scan.l" +{ return T_OP_IN; } + YY_BREAK +case 44: +YY_RULE_SETUP +#line 278 "util_expr_scan.l" +{ return T_OP_EQ; } + YY_BREAK +case 45: +YY_RULE_SETUP +#line 279 "util_expr_scan.l" +{ return T_OP_NE; } + YY_BREAK +case 46: +YY_RULE_SETUP +#line 280 "util_expr_scan.l" +{ return T_OP_GE; } + YY_BREAK +case 47: +YY_RULE_SETUP +#line 281 "util_expr_scan.l" +{ return T_OP_LE; } + YY_BREAK +case 48: +YY_RULE_SETUP +#line 282 "util_expr_scan.l" +{ return T_OP_GT; } + YY_BREAK +case 49: +YY_RULE_SETUP +#line 283 "util_expr_scan.l" +{ return T_OP_LT; } + YY_BREAK +/* for compatibility with ssl_expr */ +case 50: +YY_RULE_SETUP +#line 286 "util_expr_scan.l" +{ return T_OP_LT; } + YY_BREAK +case 51: +YY_RULE_SETUP +#line 287 "util_expr_scan.l" +{ return T_OP_LE; } + YY_BREAK +case 52: +YY_RULE_SETUP +#line 288 "util_expr_scan.l" +{ return T_OP_GT; } + YY_BREAK +case 53: +YY_RULE_SETUP +#line 289 "util_expr_scan.l" +{ return T_OP_GE; } + YY_BREAK +case 54: +YY_RULE_SETUP +#line 290 "util_expr_scan.l" +{ return T_OP_NE; } + YY_BREAK +case 55: +YY_RULE_SETUP +#line 291 "util_expr_scan.l" +{ return T_OP_EQ; } + YY_BREAK +case 56: +YY_RULE_SETUP +#line 292 "util_expr_scan.l" +{ return T_OP_IN; } + YY_BREAK +case 57: +YY_RULE_SETUP +#line 294 "util_expr_scan.l" +{ + yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1); + return T_OP_UNARY; +} + YY_BREAK +case 58: +YY_RULE_SETUP +#line 299 "util_expr_scan.l" +{ + yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1); + return T_OP_BINARY; +} YY_BREAK /* * Specials */ -case 42: +case 59: YY_RULE_SETUP -#line 202 "ssl_expr_scan.l" +#line 307 "util_expr_scan.l" { return T_TRUE; } YY_BREAK -case 43: +case 60: YY_RULE_SETUP -#line 203 "ssl_expr_scan.l" +#line 308 "util_expr_scan.l" { return T_FALSE; } YY_BREAK /* * Digits */ -case 44: +case 61: YY_RULE_SETUP -#line 208 "ssl_expr_scan.l" +#line 313 "util_expr_scan.l" { yylval->cpVal = apr_pstrdup(yyextra->pool, yytext); return T_DIGIT; @@ -1216,33 +1417,44 @@ YY_RULE_SETUP /* * Identifiers */ -case 45: +case 62: YY_RULE_SETUP -#line 216 "ssl_expr_scan.l" +#line 321 "util_expr_scan.l" { yylval->cpVal = apr_pstrdup(yyextra->pool, yytext); return T_ID; } YY_BREAK /* - * Anything else is returned as is... + * These are parts of the grammar and are returned as is */ -case 46: -/* rule 46 can match eol */ +case 63: YY_RULE_SETUP -#line 224 "ssl_expr_scan.l" -{ +#line 329 "util_expr_scan.l" +{ return yytext[0]; } YY_BREAK -case 47: +/* + * Anything else is an error + */ +case 64: +/* rule 64 can match eol */ YY_RULE_SETUP -#line 228 "ssl_expr_scan.l" +#line 336 "util_expr_scan.l" +{ + char c[2] = { yytext[0], '\0' }; + char *msg = apr_psprintf(yyextra->pool, "Parse error near '%s'", c); + PERROR(msg); +} + YY_BREAK +case 65: +YY_RULE_SETUP +#line 342 "util_expr_scan.l" YY_FATAL_ERROR( "flex scanner jammed" ); YY_BREAK -#line 1244 "ssl_expr_scan.c" +#line 1457 "util_expr_scan.c" case YY_STATE_EOF(INITIAL): -case YY_STATE_EOF(str): case YY_STATE_EOF(regex): yyterminate(); @@ -1260,7 +1472,7 @@ case YY_STATE_EOF(regex): /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called - * ssl_expr_yylex(). If so, then we have to assure + * ap_expr_yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a @@ -1321,7 +1533,7 @@ case YY_STATE_EOF(regex): { yyg->yy_did_buffer_switch_on_eof = 0; - if ( ssl_expr_yywrap(yyscanner ) ) + if ( ap_expr_yywrap(yyscanner ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up @@ -1374,7 +1586,7 @@ case YY_STATE_EOF(regex): "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ -} /* end of ssl_expr_yylex */ +} /* end of ap_expr_yylex */ /* yy_get_next_buffer - try to read in a new buffer * @@ -1453,7 +1665,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ - ssl_expr_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); + ap_expr_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); } else /* Can't grow it, we don't own it. */ @@ -1485,7 +1697,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; - ssl_expr_yyrestart(yyin ,yyscanner); + ap_expr_yyrestart(yyin ,yyscanner); } else @@ -1502,7 +1714,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) ssl_expr_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) ap_expr_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } @@ -1537,7 +1749,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 97 ) + if ( yy_current_state >= 119 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1566,11 +1778,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 97 ) + if ( yy_current_state >= 119 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 96); + yy_is_jam = (yy_current_state == 118); return yy_is_jam ? 0 : yy_current_state; } @@ -1617,13 +1829,13 @@ static int yy_get_next_buffer (yyscan_t yyscanner) */ /* Reset buffer status. */ - ssl_expr_yyrestart(yyin ,yyscanner); + ap_expr_yyrestart(yyin ,yyscanner); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { - if ( ssl_expr_yywrap(yyscanner ) ) + if ( ap_expr_yywrap(yyscanner ) ) return EOF; if ( ! yyg->yy_did_buffer_switch_on_eof ) @@ -1655,34 +1867,34 @@ static int yy_get_next_buffer (yyscan_t yyscanner) * @param yyscanner The scanner object. * @note This function does not reset the start condition to @c INITIAL . */ - void ssl_expr_yyrestart (FILE * input_file , yyscan_t yyscanner) + void ap_expr_yyrestart (FILE * input_file , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if ( ! YY_CURRENT_BUFFER ){ - ssl_expr_yyensure_buffer_stack (yyscanner); + ap_expr_yyensure_buffer_stack (yyscanner); YY_CURRENT_BUFFER_LVALUE = - ssl_expr_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + ap_expr_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); } - ssl_expr_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner); - ssl_expr_yy_load_buffer_state(yyscanner ); + ap_expr_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner); + ap_expr_yy_load_buffer_state(yyscanner ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * @param yyscanner The scanner object. */ - void ssl_expr_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) + void ap_expr_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* TODO. We should be able to replace this entire function body * with - * ssl_expr_yypop_buffer_state(); - * ssl_expr_yypush_buffer_state(new_buffer); + * ap_expr_yypop_buffer_state(); + * ap_expr_yypush_buffer_state(new_buffer); */ - ssl_expr_yyensure_buffer_stack (yyscanner); + ap_expr_yyensure_buffer_stack (yyscanner); if ( YY_CURRENT_BUFFER == new_buffer ) return; @@ -1695,17 +1907,17 @@ static int yy_get_next_buffer (yyscan_t yyscanner) } YY_CURRENT_BUFFER_LVALUE = new_buffer; - ssl_expr_yy_load_buffer_state(yyscanner ); + ap_expr_yy_load_buffer_state(yyscanner ); /* We don't actually know whether we did this switch during - * EOF (ssl_expr_yywrap()) processing, but the only time this flag - * is looked at is after ssl_expr_yywrap() is called, so it's safe + * EOF (ap_expr_yywrap()) processing, but the only time this flag + * is looked at is after ap_expr_yywrap() is called, so it's safe * to go ahead and always set it. */ yyg->yy_did_buffer_switch_on_eof = 1; } -static void ssl_expr_yy_load_buffer_state (yyscan_t yyscanner) +static void ap_expr_yy_load_buffer_state (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; @@ -1720,35 +1932,35 @@ static void ssl_expr_yy_load_buffer_state (yyscan_t yyscanner) * @param yyscanner The scanner object. * @return the allocated buffer state. */ - YY_BUFFER_STATE ssl_expr_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) + YY_BUFFER_STATE ap_expr_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) { YY_BUFFER_STATE b; - b = (YY_BUFFER_STATE) ssl_expr_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + b = (YY_BUFFER_STATE) ap_expr_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in ssl_expr_yy_create_buffer()" ); + YY_FATAL_ERROR( "out of dynamic memory in ap_expr_yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ - b->yy_ch_buf = (char *) ssl_expr_yyalloc(b->yy_buf_size + 2 ,yyscanner ); + b->yy_ch_buf = (char *) ap_expr_yyalloc(b->yy_buf_size + 2 ,yyscanner ); if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in ssl_expr_yy_create_buffer()" ); + YY_FATAL_ERROR( "out of dynamic memory in ap_expr_yy_create_buffer()" ); b->yy_is_our_buffer = 1; - ssl_expr_yy_init_buffer(b,file ,yyscanner); + ap_expr_yy_init_buffer(b,file ,yyscanner); return b; } /** Destroy the buffer. - * @param b a buffer created with ssl_expr_yy_create_buffer() + * @param b a buffer created with ap_expr_yy_create_buffer() * @param yyscanner The scanner object. */ - void ssl_expr_yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) + void ap_expr_yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; @@ -1759,28 +1971,28 @@ static void ssl_expr_yy_load_buffer_state (yyscan_t yyscanner) YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) - ssl_expr_yyfree((void *) b->yy_ch_buf ,yyscanner ); + ap_expr_yyfree((void *) b->yy_ch_buf ,yyscanner ); - ssl_expr_yyfree((void *) b ,yyscanner ); + ap_expr_yyfree((void *) b ,yyscanner ); } /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, - * such as during a ssl_expr_yyrestart() or at EOF. + * such as during a ap_expr_yyrestart() or at EOF. */ - static void ssl_expr_yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) + static void ap_expr_yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) { int oerrno = errno; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - ssl_expr_yy_flush_buffer(b ,yyscanner); + ap_expr_yy_flush_buffer(b ,yyscanner); b->yy_input_file = file; b->yy_fill_buffer = 1; - /* If b is the current buffer, then ssl_expr_yy_init_buffer was _probably_ - * called from ssl_expr_yyrestart() or through yy_get_next_buffer. + /* If b is the current buffer, then ap_expr_yy_init_buffer was _probably_ + * called from ap_expr_yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ @@ -1797,7 +2009,7 @@ static void ssl_expr_yy_load_buffer_state (yyscan_t yyscanner) * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * @param yyscanner The scanner object. */ - void ssl_expr_yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) + void ap_expr_yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if ( ! b ) @@ -1818,7 +2030,7 @@ static void ssl_expr_yy_load_buffer_state (yyscan_t yyscanner) b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) - ssl_expr_yy_load_buffer_state(yyscanner ); + ap_expr_yy_load_buffer_state(yyscanner ); } /** Pushes the new state onto the stack. The new state becomes @@ -1827,15 +2039,15 @@ static void ssl_expr_yy_load_buffer_state (yyscan_t yyscanner) * @param new_buffer The new state. * @param yyscanner The scanner object. */ -void ssl_expr_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +void ap_expr_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (new_buffer == NULL) return; - ssl_expr_yyensure_buffer_stack(yyscanner); + ap_expr_yyensure_buffer_stack(yyscanner); - /* This block is copied from ssl_expr_yy_switch_to_buffer. */ + /* This block is copied from ap_expr_yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ @@ -1849,8 +2061,8 @@ void ssl_expr_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscann yyg->yy_buffer_stack_top++; YY_CURRENT_BUFFER_LVALUE = new_buffer; - /* copied from ssl_expr_yy_switch_to_buffer. */ - ssl_expr_yy_load_buffer_state(yyscanner ); + /* copied from ap_expr_yy_switch_to_buffer. */ + ap_expr_yy_load_buffer_state(yyscanner ); yyg->yy_did_buffer_switch_on_eof = 1; } @@ -1858,19 +2070,19 @@ void ssl_expr_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscann * The next element becomes the new top. * @param yyscanner The scanner object. */ -void ssl_expr_yypop_buffer_state (yyscan_t yyscanner) +void ap_expr_yypop_buffer_state (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; if (!YY_CURRENT_BUFFER) return; - ssl_expr_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner); + ap_expr_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner); YY_CURRENT_BUFFER_LVALUE = NULL; if (yyg->yy_buffer_stack_top > 0) --yyg->yy_buffer_stack_top; if (YY_CURRENT_BUFFER) { - ssl_expr_yy_load_buffer_state(yyscanner ); + ap_expr_yy_load_buffer_state(yyscanner ); yyg->yy_did_buffer_switch_on_eof = 1; } } @@ -1878,7 +2090,7 @@ void ssl_expr_yypop_buffer_state (yyscan_t yyscanner) /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ -static void ssl_expr_yyensure_buffer_stack (yyscan_t yyscanner) +static void ap_expr_yyensure_buffer_stack (yyscan_t yyscanner) { int num_to_alloc; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; @@ -1890,11 +2102,11 @@ static void ssl_expr_yyensure_buffer_stack (yyscan_t yyscanner) * immediate realloc on the next call. */ num_to_alloc = 1; - yyg->yy_buffer_stack = (struct yy_buffer_state**)ssl_expr_yyalloc + yyg->yy_buffer_stack = (struct yy_buffer_state**)ap_expr_yyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) , yyscanner); if ( ! yyg->yy_buffer_stack ) - YY_FATAL_ERROR( "out of dynamic memory in ssl_expr_yyensure_buffer_stack()" ); + YY_FATAL_ERROR( "out of dynamic memory in ap_expr_yyensure_buffer_stack()" ); memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); @@ -1909,12 +2121,12 @@ static void ssl_expr_yyensure_buffer_stack (yyscan_t yyscanner) int grow_size = 8 /* arbitrary grow size */; num_to_alloc = yyg->yy_buffer_stack_max + grow_size; - yyg->yy_buffer_stack = (struct yy_buffer_state**)ssl_expr_yyrealloc + yyg->yy_buffer_stack = (struct yy_buffer_state**)ap_expr_yyrealloc (yyg->yy_buffer_stack, num_to_alloc * sizeof(struct yy_buffer_state*) , yyscanner); if ( ! yyg->yy_buffer_stack ) - YY_FATAL_ERROR( "out of dynamic memory in ssl_expr_yyensure_buffer_stack()" ); + YY_FATAL_ERROR( "out of dynamic memory in ap_expr_yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); @@ -1928,7 +2140,7 @@ static void ssl_expr_yyensure_buffer_stack (yyscan_t yyscanner) * @param yyscanner The scanner object. * @return the newly allocated buffer state object. */ -YY_BUFFER_STATE ssl_expr_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) +YY_BUFFER_STATE ap_expr_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) { YY_BUFFER_STATE b; @@ -1938,9 +2150,9 @@ YY_BUFFER_STATE ssl_expr_yy_scan_buffer (char * base, yy_size_t size , yyscan_ /* They forgot to leave room for the EOB's. */ return 0; - b = (YY_BUFFER_STATE) ssl_expr_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + b = (YY_BUFFER_STATE) ap_expr_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in ssl_expr_yy_scan_buffer()" ); + YY_FATAL_ERROR( "out of dynamic memory in ap_expr_yy_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; @@ -1952,33 +2164,33 @@ YY_BUFFER_STATE ssl_expr_yy_scan_buffer (char * base, yy_size_t size , yyscan_ b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; - ssl_expr_yy_switch_to_buffer(b ,yyscanner ); + ap_expr_yy_switch_to_buffer(b ,yyscanner ); return b; } -/** Setup the input buffer state to scan a string. The next call to ssl_expr_yylex() will +/** Setup the input buffer state to scan a string. The next call to ap_expr_yylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * @param yyscanner The scanner object. * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use - * ssl_expr_yy_scan_bytes() instead. + * ap_expr_yy_scan_bytes() instead. */ -YY_BUFFER_STATE ssl_expr_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner) +YY_BUFFER_STATE ap_expr_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner) { - return ssl_expr_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner); + return ap_expr_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner); } -/** Setup the input buffer state to scan the given bytes. The next call to ssl_expr_yylex() will +/** Setup the input buffer state to scan the given bytes. The next call to ap_expr_yylex() will * scan from a @e copy of @a bytes. * @param yybytes the byte buffer to scan * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * @param yyscanner The scanner object. * @return the newly allocated buffer state object. */ -YY_BUFFER_STATE ssl_expr_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner) +YY_BUFFER_STATE ap_expr_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner) { YY_BUFFER_STATE b; char *buf; @@ -1987,18 +2199,18 @@ YY_BUFFER_STATE ssl_expr_yy_scan_bytes (yyconst char * yybytes, int _yybytes_l /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; - buf = (char *) ssl_expr_yyalloc(n ,yyscanner ); + buf = (char *) ap_expr_yyalloc(n ,yyscanner ); if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in ssl_expr_yy_scan_bytes()" ); + YY_FATAL_ERROR( "out of dynamic memory in ap_expr_yy_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; - b = ssl_expr_yy_scan_buffer(buf,n ,yyscanner); + b = ap_expr_yy_scan_buffer(buf,n ,yyscanner); if ( ! b ) - YY_FATAL_ERROR( "bad buffer in ssl_expr_yy_scan_bytes()" ); + YY_FATAL_ERROR( "bad buffer in ap_expr_yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. @@ -2008,6 +2220,46 @@ YY_BUFFER_STATE ssl_expr_yy_scan_bytes (yyconst char * yybytes, int _yybytes_l return b; } + static void yy_push_state (int new_state , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( yyg->yy_start_stack_ptr >= yyg->yy_start_stack_depth ) + { + yy_size_t new_size; + + yyg->yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yyg->yy_start_stack_depth * sizeof( int ); + + if ( ! yyg->yy_start_stack ) + yyg->yy_start_stack = (int *) ap_expr_yyalloc(new_size ,yyscanner ); + + else + yyg->yy_start_stack = (int *) ap_expr_yyrealloc((void *) yyg->yy_start_stack,new_size ,yyscanner ); + + if ( ! yyg->yy_start_stack ) + YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); + } + + yyg->yy_start_stack[yyg->yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); +} + + static void yy_pop_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( --yyg->yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yyg->yy_start_stack[yyg->yy_start_stack_ptr]); +} + + static int yy_top_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyg->yy_start_stack[yyg->yy_start_stack_ptr - 1]; +} + #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif @@ -2040,7 +2292,7 @@ static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) /** Get the user-defined data for this scanner. * @param yyscanner The scanner object. */ -YY_EXTRA_TYPE ssl_expr_yyget_extra (yyscan_t yyscanner) +YY_EXTRA_TYPE ap_expr_yyget_extra (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyextra; @@ -2049,7 +2301,7 @@ YY_EXTRA_TYPE ssl_expr_yyget_extra (yyscan_t yyscanner) /** Get the current line number. * @param yyscanner The scanner object. */ -int ssl_expr_yyget_lineno (yyscan_t yyscanner) +int ap_expr_yyget_lineno (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; @@ -2062,7 +2314,7 @@ int ssl_expr_yyget_lineno (yyscan_t yyscanner) /** Get the current column number. * @param yyscanner The scanner object. */ -int ssl_expr_yyget_column (yyscan_t yyscanner) +int ap_expr_yyget_column (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; @@ -2075,7 +2327,7 @@ int ssl_expr_yyget_column (yyscan_t yyscanner) /** Get the input stream. * @param yyscanner The scanner object. */ -FILE *ssl_expr_yyget_in (yyscan_t yyscanner) +FILE *ap_expr_yyget_in (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyin; @@ -2084,7 +2336,7 @@ FILE *ssl_expr_yyget_in (yyscan_t yyscanner) /** Get the output stream. * @param yyscanner The scanner object. */ -FILE *ssl_expr_yyget_out (yyscan_t yyscanner) +FILE *ap_expr_yyget_out (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyout; @@ -2093,7 +2345,7 @@ FILE *ssl_expr_yyget_out (yyscan_t yyscanner) /** Get the length of the current token. * @param yyscanner The scanner object. */ -int ssl_expr_yyget_leng (yyscan_t yyscanner) +int ap_expr_yyget_leng (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yyleng; @@ -2103,7 +2355,7 @@ int ssl_expr_yyget_leng (yyscan_t yyscanner) * @param yyscanner The scanner object. */ -char *ssl_expr_yyget_text (yyscan_t yyscanner) +char *ap_expr_yyget_text (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yytext; @@ -2113,7 +2365,7 @@ char *ssl_expr_yyget_text (yyscan_t yyscanner) * @param user_defined The data to be associated with this scanner. * @param yyscanner The scanner object. */ -void ssl_expr_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) +void ap_expr_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyextra = user_defined ; @@ -2123,13 +2375,13 @@ void ssl_expr_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) * @param line_number * @param yyscanner The scanner object. */ -void ssl_expr_yyset_lineno (int line_number , yyscan_t yyscanner) +void ap_expr_yyset_lineno (int line_number , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* lineno is only valid if an input buffer exists. */ if (! YY_CURRENT_BUFFER ) - yy_fatal_error( "ssl_expr_yyset_lineno called with no buffer" , yyscanner); + yy_fatal_error( "ap_expr_yyset_lineno called with no buffer" , yyscanner); yylineno = line_number; } @@ -2138,13 +2390,13 @@ void ssl_expr_yyset_lineno (int line_number , yyscan_t yyscanner) * @param line_number * @param yyscanner The scanner object. */ -void ssl_expr_yyset_column (int column_no , yyscan_t yyscanner) +void ap_expr_yyset_column (int column_no , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* column is only valid if an input buffer exists. */ if (! YY_CURRENT_BUFFER ) - yy_fatal_error( "ssl_expr_yyset_column called with no buffer" , yyscanner); + yy_fatal_error( "ap_expr_yyset_column called with no buffer" , yyscanner); yycolumn = column_no; } @@ -2153,27 +2405,27 @@ void ssl_expr_yyset_column (int column_no , yyscan_t yyscanner) * input buffer. * @param in_str A readable stream. * @param yyscanner The scanner object. - * @see ssl_expr_yy_switch_to_buffer + * @see ap_expr_yy_switch_to_buffer */ -void ssl_expr_yyset_in (FILE * in_str , yyscan_t yyscanner) +void ap_expr_yyset_in (FILE * in_str , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyin = in_str ; } -void ssl_expr_yyset_out (FILE * out_str , yyscan_t yyscanner) +void ap_expr_yyset_out (FILE * out_str , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yyout = out_str ; } -int ssl_expr_yyget_debug (yyscan_t yyscanner) +int ap_expr_yyget_debug (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yy_flex_debug; } -void ssl_expr_yyset_debug (int bdebug , yyscan_t yyscanner) +void ap_expr_yyset_debug (int bdebug , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yy_flex_debug = bdebug ; @@ -2181,13 +2433,13 @@ void ssl_expr_yyset_debug (int bdebug , yyscan_t yyscanner) /* Accessor methods for yylval and yylloc */ -YYSTYPE * ssl_expr_yyget_lval (yyscan_t yyscanner) +YYSTYPE * ap_expr_yyget_lval (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; return yylval; } -void ssl_expr_yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) +void ap_expr_yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; yylval = yylval_param; @@ -2195,12 +2447,12 @@ void ssl_expr_yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) /* User-visible API */ -/* ssl_expr_yylex_init is special because it creates the scanner itself, so it is +/* ap_expr_yylex_init is special because it creates the scanner itself, so it is * the ONLY reentrant function that doesn't take the scanner as the last argument. * That's why we explicitly handle the declaration, instead of using our macros. */ -int ssl_expr_yylex_init(yyscan_t* ptr_yy_globals) +int ap_expr_yylex_init(yyscan_t* ptr_yy_globals) { if (ptr_yy_globals == NULL){ @@ -2208,7 +2460,7 @@ int ssl_expr_yylex_init(yyscan_t* ptr_yy_globals) return 1; } - *ptr_yy_globals = (yyscan_t) ssl_expr_yyalloc ( sizeof( struct yyguts_t ), NULL ); + *ptr_yy_globals = (yyscan_t) ap_expr_yyalloc ( sizeof( struct yyguts_t ), NULL ); if (*ptr_yy_globals == NULL){ errno = ENOMEM; @@ -2221,27 +2473,27 @@ int ssl_expr_yylex_init(yyscan_t* ptr_yy_globals) return yy_init_globals ( *ptr_yy_globals ); } -/* ssl_expr_yylex_init_extra has the same functionality as ssl_expr_yylex_init, but follows the +/* ap_expr_yylex_init_extra has the same functionality as ap_expr_yylex_init, but follows the * convention of taking the scanner as the last argument. Note however, that * this is a *pointer* to a scanner, as it will be allocated by this call (and * is the reason, too, why this function also must handle its own declaration). - * The user defined value in the first argument will be available to ssl_expr_yyalloc in + * The user defined value in the first argument will be available to ap_expr_yyalloc in * the yyextra field. */ -int ssl_expr_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals ) +int ap_expr_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals ) { struct yyguts_t dummy_yyguts; - ssl_expr_yyset_extra (yy_user_defined, &dummy_yyguts); + ap_expr_yyset_extra (yy_user_defined, &dummy_yyguts); if (ptr_yy_globals == NULL){ errno = EINVAL; return 1; } - *ptr_yy_globals = (yyscan_t) ssl_expr_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); + *ptr_yy_globals = (yyscan_t) ap_expr_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); if (*ptr_yy_globals == NULL){ errno = ENOMEM; @@ -2252,7 +2504,7 @@ int ssl_expr_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_glo yy_init_globals. Leave at 0x00 for releases. */ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); - ssl_expr_yyset_extra (yy_user_defined, *ptr_yy_globals); + ap_expr_yyset_extra (yy_user_defined, *ptr_yy_globals); return yy_init_globals ( *ptr_yy_globals ); } @@ -2261,7 +2513,7 @@ static int yy_init_globals (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* Initialization is the same as for the non-reentrant scanner. - * This function is called from ssl_expr_yylex_destroy(), so don't allocate here. + * This function is called from ap_expr_yylex_destroy(), so don't allocate here. */ yyg->yy_buffer_stack = 0; @@ -2285,37 +2537,37 @@ static int yy_init_globals (yyscan_t yyscanner) #endif /* For future reference: Set errno on error, since we are called by - * ssl_expr_yylex_init() + * ap_expr_yylex_init() */ return 0; } -/* ssl_expr_yylex_destroy is for both reentrant and non-reentrant scanners. */ -int ssl_expr_yylex_destroy (yyscan_t yyscanner) +/* ap_expr_yylex_destroy is for both reentrant and non-reentrant scanners. */ +int ap_expr_yylex_destroy (yyscan_t yyscanner) { struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ - ssl_expr_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner ); + ap_expr_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner ); YY_CURRENT_BUFFER_LVALUE = NULL; - ssl_expr_yypop_buffer_state(yyscanner); + ap_expr_yypop_buffer_state(yyscanner); } /* Destroy the stack itself. */ - ssl_expr_yyfree(yyg->yy_buffer_stack ,yyscanner); + ap_expr_yyfree(yyg->yy_buffer_stack ,yyscanner); yyg->yy_buffer_stack = NULL; /* Destroy the start condition stack. */ - ssl_expr_yyfree(yyg->yy_start_stack ,yyscanner ); + ap_expr_yyfree(yyg->yy_start_stack ,yyscanner ); yyg->yy_start_stack = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time - * ssl_expr_yylex() is called, initialization will occur. */ + * ap_expr_yylex() is called, initialization will occur. */ yy_init_globals( yyscanner); /* Destroy the main struct (reentrant only). */ - ssl_expr_yyfree ( yyscanner , yyscanner ); + ap_expr_yyfree ( yyscanner , yyscanner ); yyscanner = NULL; return 0; } @@ -2344,12 +2596,12 @@ static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) } #endif -void *ssl_expr_yyalloc (yy_size_t size , yyscan_t yyscanner) +void *ap_expr_yyalloc (yy_size_t size , yyscan_t yyscanner) { return (void *) malloc( size ); } -void *ssl_expr_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner) +void *ap_expr_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those @@ -2361,14 +2613,14 @@ void *ssl_expr_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner) return (void *) realloc( (char *) ptr, size ); } -void ssl_expr_yyfree (void * ptr , yyscan_t yyscanner) +void ap_expr_yyfree (void * ptr , yyscan_t yyscanner) { - free( (char *) ptr ); /* see ssl_expr_yyrealloc() for (char *) cast */ + free( (char *) ptr ); /* see ap_expr_yyrealloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" -#line 228 "ssl_expr_scan.l" +#line 342 "util_expr_scan.l" diff --git a/server/util_expr_scan.l b/server/util_expr_scan.l new file mode 100644 index 0000000000..d2840a00b4 --- /dev/null +++ b/server/util_expr_scan.l @@ -0,0 +1,344 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * ap_expr_scan.l, based on ssl_expr_scan.l from mod_ssl + */ + +/* _________________________________________________________________ +** +** Expression Scanner +** _________________________________________________________________ +*/ + +%pointer +%option batch +%option never-interactive +%option nodefault +%option noyywrap +%option reentrant +%option bison-bridge +%option warn +%option noinput nounput +%option stack +%x str +%x var +%x vararg +%x regex regex_flags + +%{ +#include "util_expr_private.h" +#include "util_expr_parse.h" + +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ +{ \ + if ((result = MIN(max_size, yyextra->inputbuf \ + + yyextra->inputlen \ + - yyextra->inputptr)) <= 0) \ + { \ + result = YY_NULL; \ + } \ + else { \ + memcpy(buf, yyextra->inputptr, result); \ + yyextra->inputptr += result; \ + } \ +} + +#define YY_EXTRA_TYPE ap_expr_parse_ctx* + +#define PERROR(msg) yyextra->error2 = msg ; return ERROR; + +#define str_ptr (yyextra->scan_ptr) +#define str_buf (yyextra->scan_buf) +#define str_del (yyextra->scan_del) + +%} + + +%% + + char regex_buf[MAX_STRING_LEN]; + char *regex_ptr = NULL; + char regex_del = '\0'; + + /* + * Whitespaces + */ +[ \t\n]+ { + /* NOP */ +} + + /* + * strings ("..." and '...') + */ +["'] { + str_ptr = str_buf; + str_del = yytext[0]; + BEGIN(str); + return T_STR_BEGIN; +} +<str>["'] { + if (yytext[0] == str_del) { + if (YY_START == var) { + PERROR("Unterminated variable in string"); + } + else if (str_ptr == str_buf) { + BEGIN(INITIAL); + return T_STR_END; + } + else { + /* return what we have so far and scan delimiter again */ + *str_ptr = '\0'; + yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf); + yyless(0); + str_ptr = str_buf; + return T_STRING; + } + } + else { + *str_ptr++ = yytext[0]; + } +} +<str,var,vararg>\n { + PERROR("Unterminated string or variable"); +} +<str,var,vararg><<EOF>> { + PERROR("Unterminated string or variable"); +} +<str,vararg>\\[0-7]{1,3} { + int result; + + (void)sscanf(yytext+1, "%o", &result); + if (result > 0xff) { + PERROR("Escape sequence out of bound"); + } + else { + *str_ptr++ = result; + } +} +<str,vararg>\\[0-9]+ { + PERROR("Bad escape sequence"); +} +<str,vararg>\\n { *str_ptr++ = '\n'; } +<str,vararg>\\r { *str_ptr++ = '\r'; } +<str,vararg>\\t { *str_ptr++ = '\t'; } +<str,vararg>\\b { *str_ptr++ = '\b'; } +<str,vararg>\\f { *str_ptr++ = '\f'; } +<str,vararg>\\(.|\n) { + *str_ptr++ = yytext[1]; +} + +<str,vararg>[^\\\n"'%}]+ { + char *cp = yytext; + while (*cp != '\0') + *str_ptr++ = *cp++; +} + + /* variable inside string */ +<str>%\{ { + if (str_ptr != str_buf) { + /* return what we have so far and scan '%{' again */ + *str_ptr = '\0'; + yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf); + yyless(0); + str_ptr = str_buf; + return T_STRING; + } + else { + yy_push_state(var, yyscanner); + return T_VAR_BEGIN; + } +} + +<vararg>% { + *str_ptr++ = yytext[0]; +} + +<str>[%}] { + *str_ptr++ = yytext[0]; +} + +%\{ { + yy_push_state(var, yyscanner); + return T_VAR_BEGIN; +} + + /* + * fixed name variable expansion %{XXX} and function call in %{func:arg} syntax + */ +<var>[a-zA-Z][a-zA-Z0-9_]* { + yylval->cpVal = apr_pstrdup(yyextra->pool, yytext); + return T_ID; +} + +<var>\} { + yy_pop_state(yyscanner); + return T_VAR_END; +} + +<var>: { + BEGIN(vararg); + return yytext[0]; +} + +<var>.|\n { + char c[2] = { yytext[0], '\0' }; + char *msg = apr_psprintf(yyextra->pool, + "Invalid character in variable name '%s'", c); + PERROR(msg); +} + +<vararg>\} { + if (str_ptr != str_buf) { + /* return what we have so far and scan '}' again */ + *str_ptr = '\0'; + yylval->cpVal = apr_pstrdup(yyextra->pool, str_buf); + str_ptr = str_buf; + yyless(0); + return T_STRING; + } + else { + yy_pop_state(yyscanner); + return T_VAR_END; + } +} + + /* + * Regular Expression + */ +"m"[/#$%^,;:_\?\|\^\-\!\.\'\"] { + regex_del = yytext[1]; + regex_ptr = regex_buf; + BEGIN(regex); +} +"/" { + regex_del = yytext[0]; + regex_ptr = regex_buf; + BEGIN(regex); +} +<regex>.|\n { + if (yytext[0] == regex_del) { + *regex_ptr = '\0'; + BEGIN(regex_flags); + } + else { + *regex_ptr++ = yytext[0]; + } +} +<regex_flags>i { + yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf); + BEGIN(INITIAL); + return T_REGEX_I; +} +<regex_flags>.|\n { + yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf); + yyless(0); + BEGIN(INITIAL); + return T_REGEX; +} +<regex_flags><<EOF>> { + yylval->cpVal = apr_pstrdup(yyextra->pool, regex_buf); + BEGIN(INITIAL); + return T_REGEX; +} + + /* + * Operators + */ +==? { return T_OP_STR_EQ; } +"!=" { return T_OP_STR_NE; } +"<" { return T_OP_STR_LT; } +"<=" { return T_OP_STR_LE; } +">" { return T_OP_STR_GT; } +">=" { return T_OP_STR_GE; } +"=~" { return T_OP_REG; } +"!~" { return T_OP_NRE; } +"and" { return T_OP_AND; } +"&&" { return T_OP_AND; } +"or" { return T_OP_OR; } +"||" { return T_OP_OR; } +"not" { return T_OP_NOT; } +"!" { return T_OP_NOT; } +"." { return T_OP_CONCAT; } +"-in" { return T_OP_IN; } +"-eq" { return T_OP_EQ; } +"-ne" { return T_OP_NE; } +"-ge" { return T_OP_GE; } +"-le" { return T_OP_LE; } +"-gt" { return T_OP_GT; } +"-lt" { return T_OP_LT; } + + /* for compatibility with ssl_expr */ +"lt" { return T_OP_LT; } +"le" { return T_OP_LE; } +"gt" { return T_OP_GT; } +"ge" { return T_OP_GE; } +"ne" { return T_OP_NE; } +"eq" { return T_OP_EQ; } +"in" { return T_OP_IN; } + +"-"[a-zA-Z_] { + yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1); + return T_OP_UNARY; +} + +"-"[a-zA-Z_][a-zA-Z_0-9] { + yylval->cpVal = apr_pstrdup(yyextra->pool, yytext + 1); + return T_OP_BINARY; +} + + /* + * Specials + */ +"true" { return T_TRUE; } +"false" { return T_FALSE; } + + /* + * Digits + */ +-?[0-9]+ { + yylval->cpVal = apr_pstrdup(yyextra->pool, yytext); + return T_DIGIT; +} + + /* + * Identifiers + */ +[a-zA-Z][a-zA-Z0-9_]* { + yylval->cpVal = apr_pstrdup(yyextra->pool, yytext); + return T_ID; +} + + /* + * These are parts of the grammar and are returned as is + */ +[(){},:] { + return yytext[0]; +} + + /* + * Anything else is an error + */ +.|\n { + char c[2] = { yytext[0], '\0' }; + char *msg = apr_psprintf(yyextra->pool, "Parse error near '%s'", c); + PERROR(msg); +} + +%% + + |