]> granicus.if.org Git - apache/blob - server/util_expr_eval.c
mpm_event,worker: Mask signals for threads created by modules in child init.
[apache] / server / util_expr_eval.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /*                      _             _
18  *  ap_expr_eval.c, based on ssl_expr_eval.c from mod_ssl
19  */
20
21 #include "httpd.h"
22 #include "http_log.h"
23 #include "http_core.h"
24 #include "http_protocol.h"
25 #include "http_request.h"
26 #include "ap_provider.h"
27 #include "util_varbuf.h"
28 #include "util_expr_private.h"
29 #include "util_md5.h"
30 #include "util_varbuf.h"
31
32 #include "apr_lib.h"
33 #include "apr_fnmatch.h"
34 #include "apr_base64.h"
35 #include "apr_sha1.h"
36 #include "apr_version.h"
37 #include "apr_strings.h"
38 #include "apr_strmatch.h"
39 #if APR_VERSION_AT_LEAST(1,5,0)
40 #include "apr_escape.h"
41 #endif
42
43 #include <limits.h>     /* for INT_MAX */
44
45 /* we know core's module_index is 0 */
46 #undef APLOG_MODULE_INDEX
47 #define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
48
49 APR_HOOK_STRUCT(
50     APR_HOOK_LINK(expr_lookup)
51 )
52
53 AP_IMPLEMENT_HOOK_RUN_FIRST(int, expr_lookup, (ap_expr_lookup_parms *parms),
54                             (parms), DECLINED)
55
56 #define  LOG_MARK(info)  __FILE__, __LINE__, (info)->module_index
57
58 static int ap_expr_eval_cond(ap_expr_eval_ctx_t *ctx, const ap_expr_t *node);
59
60 static const char *ap_expr_eval_string_func(ap_expr_eval_ctx_t *ctx,
61                                             const ap_expr_t *info,
62                                             const ap_expr_t *args);
63 static const char *ap_expr_eval_re_backref(ap_expr_eval_ctx_t *ctx,
64                                            unsigned int n);
65 static const char *ap_expr_eval_var(ap_expr_eval_ctx_t *ctx,
66                                     ap_expr_var_func_t *func,
67                                     const void *data);
68
69 typedef struct {
70     int flags;
71     const ap_expr_t *subst;
72 } ap_expr_regctx_t;
73
74 static const char *ap_expr_regexec(const char *subject,
75                                    const ap_expr_t *reg,
76                                    apr_array_header_t *list,
77                                    ap_expr_eval_ctx_t *ctx);
78
79 static apr_array_header_t *ap_expr_list_make(ap_expr_eval_ctx_t *ctx,
80                                              const ap_expr_t *node);
81
82 /* define AP_EXPR_DEBUG to log the parse tree when parsing an expression */
83 #ifdef AP_EXPR_DEBUG
84 static void expr_dump_tree(const ap_expr_t *e, const server_rec *s,
85                            int loglevel, int indent);
86 #endif
87
88 /*
89  * To reduce counting overhead, we only count calls to
90  * ap_expr_eval_word() and ap_expr_eval_cond(). The max number of
91  * stack frames is larger by some factor.
92  */
93 #define AP_EXPR_MAX_RECURSION   20
94 static int inc_rec(ap_expr_eval_ctx_t *ctx)
95 {
96     if (ctx->reclvl < AP_EXPR_MAX_RECURSION) {
97         ctx->reclvl++;
98         return 0;
99     }
100     *ctx->err = "Recursion limit reached";
101     /* short circuit further evaluation */
102     ctx->reclvl = INT_MAX;
103     return 1;
104 }
105
106 static const char *ap_expr_list_pstrcat(apr_pool_t *p,
107                                         const apr_array_header_t *list,
108                                         const char *sep)
109 {
110     if (list->nelts <= 0) {
111         return NULL;
112     }
113     else if (list->nelts == 1) {
114         return APR_ARRAY_IDX(list, 0, const char*);
115     }
116     else {
117         struct ap_varbuf vb;
118         int n = list->nelts - 1, i;
119         apr_size_t slen = strlen(sep), vlen;
120         const char *val;
121
122         ap_varbuf_init(p, &vb, 0);
123         for (i = 0; i < n; ++i) {
124             val = APR_ARRAY_IDX(list, i, const char*);
125             vlen = strlen(val);
126             ap_varbuf_grow(&vb, vlen + slen + 1);
127             ap_varbuf_strmemcat(&vb, val, vlen);
128             ap_varbuf_strmemcat(&vb, sep, slen);
129         }
130         val = APR_ARRAY_IDX(list, n, const char*);
131         ap_varbuf_strmemcat(&vb, val, strlen(val));
132
133         return vb.buf;
134     }
135 }
136
137 static const char *ap_expr_eval_word(ap_expr_eval_ctx_t *ctx,
138                                      const ap_expr_t *node)
139 {
140     const char *result = "";
141     if (inc_rec(ctx))
142         return result;
143     switch (node->node_op) {
144     case op_Digit:
145     case op_String:
146         result = node->node_arg1;
147         break;
148     case op_Word:
149         result = ap_expr_eval_word(ctx, node->node_arg1);
150         break;
151     case op_Bool:
152         result = ap_expr_eval_cond(ctx, node->node_arg1) ? "true" : "false";
153         break;
154     case op_Var:
155         result = ap_expr_eval_var(ctx, (ap_expr_var_func_t *)node->node_arg1,
156                                   node->node_arg2);
157         break;
158     case op_Concat:
159         if (((ap_expr_t *)node->node_arg2)->node_op != op_Concat &&
160             ((ap_expr_t *)node->node_arg1)->node_op != op_Concat) {
161             const char *s1 = ap_expr_eval_word(ctx, node->node_arg1);
162             const char *s2 = ap_expr_eval_word(ctx, node->node_arg2);
163             if (!*s1)
164                 result = s2;
165             else if (!*s2)
166                 result = s1;
167             else
168                 result = apr_pstrcat(ctx->p, s1, s2, NULL);
169         }
170         else if (((ap_expr_t *)node->node_arg1)->node_op == op_Concat) {
171             const ap_expr_t *nodep = node;
172             int n;
173             int i = 1;
174             struct iovec *vec;
175             do {
176                 nodep = nodep->node_arg1;
177                 i++;
178             } while (nodep->node_op == op_Concat);
179             vec = apr_palloc(ctx->p, i * sizeof(struct iovec));
180             n = i;
181             nodep = node;
182             i--;
183             do {
184                 vec[i].iov_base = (void *)ap_expr_eval_word(ctx,
185                                                             nodep->node_arg2);
186                 vec[i].iov_len = strlen(vec[i].iov_base);
187                 i--;
188                 nodep = nodep->node_arg1;
189             } while (nodep->node_op == op_Concat);
190             vec[i].iov_base = (void *)ap_expr_eval_word(ctx, nodep);
191             vec[i].iov_len = strlen(vec[i].iov_base);
192             result = apr_pstrcatv(ctx->p, vec, n, NULL);
193         }
194         else {
195             const ap_expr_t *nodep = node;
196             int i = 1;
197             struct iovec *vec;
198             do {
199                 nodep = nodep->node_arg2;
200                 i++;
201             } while (nodep->node_op == op_Concat);
202             vec = apr_palloc(ctx->p, i * sizeof(struct iovec));
203             nodep = node;
204             i = 0;
205             do {
206                 vec[i].iov_base = (void *)ap_expr_eval_word(ctx,
207                                                             nodep->node_arg1);
208                 vec[i].iov_len = strlen(vec[i].iov_base);
209                 i++;
210                 nodep = nodep->node_arg2;
211             } while (nodep->node_op == op_Concat);
212             vec[i].iov_base = (void *)ap_expr_eval_word(ctx, nodep);
213             vec[i].iov_len = strlen(vec[i].iov_base);
214             i++;
215             result = apr_pstrcatv(ctx->p, vec, i, NULL);
216         }
217         break;
218     case op_StringFuncCall: {
219         const ap_expr_t *info = node->node_arg1;
220         const ap_expr_t *args = node->node_arg2;
221         result = ap_expr_eval_string_func(ctx, info, args);
222         break;
223     }
224     case op_Join: {
225         const char *sep;
226         apr_array_header_t *list = ap_expr_list_make(ctx, node->node_arg1);
227         sep = node->node_arg2 ? ap_expr_eval_word(ctx, node->node_arg2) : "";
228         result = ap_expr_list_pstrcat(ctx->p, list, sep);
229         break;
230     }
231     case op_Sub: {
232         const ap_expr_t *reg = node->node_arg2;
233         const char *subject = ap_expr_eval_word(ctx, node->node_arg1);
234         result = ap_expr_regexec(subject, reg, NULL, ctx);
235         break;
236     }
237     case op_Backref: {
238         const unsigned int *np = node->node_arg1;
239         result = ap_expr_eval_re_backref(ctx, *np);
240         break;
241     }
242     default:
243         *ctx->err = "Internal evaluation error: Unknown word expression node";
244         break;
245     }
246     if (!result)
247         result = "";
248     ctx->reclvl--;
249     return result;
250 }
251
252 static const char *ap_expr_eval_var(ap_expr_eval_ctx_t *ctx,
253                                     ap_expr_var_func_t *func,
254                                     const void *data)
255 {
256     AP_DEBUG_ASSERT(func != NULL);
257     AP_DEBUG_ASSERT(data != NULL);
258     return (*func)(ctx, data);
259 }
260
261 static const char *ap_expr_eval_re_backref(ap_expr_eval_ctx_t *ctx, unsigned int n)
262 {
263     int len;
264
265     if (!ctx->re_pmatch || !ctx->re_source || !*ctx->re_source
266         || **ctx->re_source == '\0' || ctx->re_nmatch < n + 1)
267         return "";
268
269     len = ctx->re_pmatch[n].rm_eo - ctx->re_pmatch[n].rm_so;
270     if (len == 0)
271         return "";
272
273     return apr_pstrndup(ctx->p, *ctx->re_source + ctx->re_pmatch[n].rm_so, len);
274 }
275
276 static const char *ap_expr_eval_string_func(ap_expr_eval_ctx_t *ctx,
277                                             const ap_expr_t *info,
278                                             const ap_expr_t *arg)
279 {
280     const void *data = info->node_arg2;
281
282     AP_DEBUG_ASSERT(info->node_op == op_StringFuncInfo);
283     AP_DEBUG_ASSERT(info->node_arg1 != NULL);
284     AP_DEBUG_ASSERT(data != NULL);
285     if (arg->node_op == op_ListElement) {
286         /* Evaluate the list elements and store them in apr_array_header. */
287         ap_expr_string_list_func_t *func = (ap_expr_string_list_func_t *)info->node_arg1;
288         apr_array_header_t *args = ap_expr_list_make(ctx, arg->node_arg1);
289         return (*func)(ctx, data, args);
290     }
291     else {
292         ap_expr_string_func_t *func = (ap_expr_string_func_t *)info->node_arg1;
293         return (*func)(ctx, data, ap_expr_eval_word(ctx, arg));
294     }
295 }
296
297 static int intstrcmp(const char *s1, const char *s2)
298 {
299     apr_int64_t i1 = apr_atoi64(s1);
300     apr_int64_t i2 = apr_atoi64(s2);
301
302     if (i1 < i2)
303         return -1;
304     else if (i1 == i2)
305         return 0;
306     else
307         return 1;
308 }
309
310 static const char *ap_expr_regexec(const char *subject,
311                                    const ap_expr_t *reg,
312                                    apr_array_header_t *list,
313                                    ap_expr_eval_ctx_t *ctx)
314 {
315     struct ap_varbuf vb;
316     const char *val = subject;
317     const ap_regex_t *regex = reg->node_arg1;
318     const ap_expr_regctx_t *regctx = reg->node_arg2;
319     ap_regmatch_t *pmatch = NULL, match0;
320     apr_size_t nmatch = 0;
321     const char *str = "";
322     apr_size_t len = 0;
323     int empty = 0, rv;
324
325     ap_varbuf_init(ctx->p, &vb, 0);
326     if (ctx->re_nmatch > 0) {
327         nmatch = ctx->re_nmatch;
328         pmatch = ctx->re_pmatch;
329     }
330     else if (regctx->subst) {
331         nmatch = 1;
332         pmatch = &match0;
333     }
334     do {
335         /* If previous match was empty, we can't issue the exact same one or
336          * we'd loop indefinitively.  So let's instead ask for an anchored and
337          * non-empty match (i.e. something not empty at the start of the value)
338          * and if nothing is found advance by one character below.
339          */
340         rv = ap_regexec(regex, val, nmatch, pmatch, 
341                         empty ? AP_REG_ANCHORED | AP_REG_NOTEMPTY : 0);
342         if (rv == 0) {
343             int pos = pmatch[0].rm_so,
344                 end = pmatch[0].rm_eo;
345             AP_DEBUG_ASSERT(pos >= 0 && pos <= end);
346
347             if (regctx->subst) {
348                 *ctx->re_source = val;
349                 str = ap_expr_eval_word(ctx, regctx->subst);
350                 len = strlen(str);
351             }
352             if (list) {
353                 char *tmp = apr_palloc(ctx->p, pos + len + 1);
354                 memcpy(tmp, val, pos);
355                 memcpy(tmp + pos, str, len + 1);
356                 APR_ARRAY_PUSH(list, const char*) = tmp;
357             }
358             else {
359                 ap_varbuf_grow(&vb, pos + len + 1);
360                 ap_varbuf_strmemcat(&vb, val, pos);
361                 ap_varbuf_strmemcat(&vb, str, len);
362                 if (!(regctx->flags & AP_REG_MULTI)) {
363                     /* Single substitution, preserve remaining data */
364                     ap_varbuf_strmemcat(&vb, val + end, strlen(val) - end);
365                     break;
366                 }
367             }
368             /* Note an empty match */
369             empty = (end == 0);
370             val += end;
371         }
372         else if (empty) {
373             /* Skip this non-matching character (or full CRLF) and restart
374              * another "normal" match (possibly empty) from there.
375              */
376             if (val[0] == '\r' && val[1] == '\n') {
377                 val += 2;
378             }
379             else {
380                 val++;
381             }
382             empty = 0;
383         }
384         else {
385             if (list) {
386                 APR_ARRAY_PUSH(list, const char*) = val;
387             }
388             else if (vb.avail) {
389                 ap_varbuf_strmemcat(&vb, val, strlen(val));
390             }
391             else {
392                 return val;
393             }
394             break;
395         }
396     } while (*val);
397
398     return vb.buf;
399 }
400
401 static apr_array_header_t *ap_expr_list_make(ap_expr_eval_ctx_t *ctx,
402                                              const ap_expr_t *node)
403 {
404     apr_array_header_t *list = NULL;
405
406     if (node->node_op == op_Split) {
407         const ap_expr_t *arg = node->node_arg1;
408         const ap_expr_t *reg = node->node_arg2;
409         const apr_array_header_t *source = ap_expr_list_make(ctx, arg);
410         int i;
411
412         list = apr_array_make(ctx->p, source->nelts, sizeof(const char*));
413         for (i = 0; i < source->nelts; ++i) {
414             const char *val = APR_ARRAY_IDX(source, i, const char*);
415             (void)ap_expr_regexec(val, reg, list, ctx);
416         }
417     }
418     else if (node->node_op == op_ListElement) {
419         int n = 0;
420         const ap_expr_t *elem;
421         for (elem = node; elem; elem = elem->node_arg2) {
422             AP_DEBUG_ASSERT(elem->node_op == op_ListElement);
423             n++;
424         }
425
426         list = apr_array_make(ctx->p, n, sizeof(const char*));
427         for (elem = node; elem; elem = elem->node_arg2) {
428             APR_ARRAY_PUSH(list, const char*) =
429                 ap_expr_eval_word(ctx, elem->node_arg1);
430         }
431     }
432     else if (node->node_op == op_ListFuncCall) {
433         const ap_expr_t *info = node->node_arg1;
434         ap_expr_list_func_t *func = info->node_arg1;
435
436         AP_DEBUG_ASSERT(func != NULL);
437         AP_DEBUG_ASSERT(info->node_op == op_ListFuncInfo);
438         list = (*func)(ctx, info->node_arg2,
439                        ap_expr_eval_word(ctx, node->node_arg2));
440     }
441     else {
442         list = apr_array_make(ctx->p, 1, sizeof(const char*));
443         APR_ARRAY_PUSH(list, const char*) = ap_expr_eval_word(ctx, node);
444     }
445
446     return list;
447 }
448
449 static int ap_expr_eval_comp(ap_expr_eval_ctx_t *ctx, const ap_expr_t *node)
450 {
451     const ap_expr_t *e1 = node->node_arg1;
452     const ap_expr_t *e2 = node->node_arg2;
453     switch (node->node_op) {
454     case op_EQ:
455         return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) == 0);
456     case op_NE:
457         return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) != 0);
458     case op_LT:
459         return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <  0);
460     case op_LE:
461         return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <= 0);
462     case op_GT:
463         return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >  0);
464     case op_GE:
465         return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >= 0);
466     case op_STR_EQ:
467         return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) == 0);
468     case op_STR_NE:
469         return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) != 0);
470     case op_STR_LT:
471         return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <  0);
472     case op_STR_LE:
473         return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <= 0);
474     case op_STR_GT:
475         return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >  0);
476     case op_STR_GE:
477         return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >= 0);
478     case op_IN: {
479             int n;
480             const char *needle, *subject;
481             apr_array_header_t *haystack;
482             haystack = ap_expr_list_make(ctx, e2);
483             if (haystack) {
484                 needle = ap_expr_eval_word(ctx, e1);
485                 for (n = 0; n < haystack->nelts; ++n) {
486                     subject = APR_ARRAY_IDX(haystack, n, const char*);
487                     if (strcmp(needle, subject) == 0) {
488                         return 1;
489                     }
490                 }
491             }
492             return 0;
493         }
494     case op_REG:
495     case op_NRE: {
496             const char *word = ap_expr_eval_word(ctx, e1);
497             const ap_regex_t *regex = e2->node_arg1;
498             int result;
499
500             /*
501              * $0 ... $9 may contain stuff the user wants to keep. Therefore
502              * we only set them if there are capturing parens in the regex.
503              */
504             if (regex->re_nsub > 0) {
505                 result = (0 == ap_regexec(regex, word, ctx->re_nmatch,
506                                           ctx->re_pmatch, 0));
507                 *ctx->re_source = result ? word : NULL;
508             }
509             else {
510                 result = (0 == ap_regexec(regex, word, 0, NULL, 0));
511             }
512
513             return result ^ (node->node_op == op_NRE);
514         }
515     default:
516         *ctx->err = "Internal evaluation error: Unknown comp expression node";
517         return -1;
518     }
519 }
520
521 /* combined string/int comparison for compatibility with ssl_expr */
522 static int strcmplex(const char *str1, const char *str2)
523 {
524     int i, n1, n2;
525
526     if (str1 == NULL)
527         return -1;
528     if (str2 == NULL)
529         return +1;
530     n1 = strlen(str1);
531     n2 = strlen(str2);
532     if (n1 > n2)
533         return 1;
534     if (n1 < n2)
535         return -1;
536     for (i = 0; i < n1; i++) {
537         if (str1[i] > str2[i])
538             return 1;
539         if (str1[i] < str2[i])
540             return -1;
541     }
542     return 0;
543 }
544
545 static int ssl_expr_eval_comp(ap_expr_eval_ctx_t *ctx, const ap_expr_t *node)
546 {
547     const ap_expr_t *e1 = node->node_arg1;
548     const ap_expr_t *e2 = node->node_arg2;
549     switch (node->node_op) {
550     case op_EQ:
551     case op_STR_EQ:
552         return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) == 0);
553     case op_NE:
554     case op_STR_NE:
555         return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) != 0);
556     case op_LT:
557     case op_STR_LT:
558         return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <  0);
559     case op_LE:
560     case op_STR_LE:
561         return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <= 0);
562     case op_GT:
563     case op_STR_GT:
564         return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >  0);
565     case op_GE:
566     case op_STR_GE:
567         return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >= 0);
568     default:
569         return ap_expr_eval_comp(ctx, node);
570     }
571 }
572
573 AP_DECLARE_NONSTD(int) ap_expr_lookup_default(ap_expr_lookup_parms *parms)
574 {
575     return ap_run_expr_lookup(parms);
576 }
577
578 AP_DECLARE(const char *) ap_expr_parse(apr_pool_t *pool, apr_pool_t *ptemp,
579                                        ap_expr_info_t *info, const char *expr,
580                                        ap_expr_lookup_fn_t *lookup_fn)
581 {
582     ap_expr_parse_ctx_t ctx;
583     int rc;
584
585     memset(&ctx, 0, sizeof ctx);
586     ctx.pool     = pool;
587     ctx.ptemp    = ptemp;
588     ctx.inputbuf = expr;
589     ctx.inputlen = strlen(expr);
590     ctx.inputptr = ctx.inputbuf;
591     ctx.flags    = info->flags;
592     ctx.lookup_fn   = lookup_fn ? lookup_fn : ap_expr_lookup_default;
593     ctx.at_start    = 1;
594
595     ap_expr_yylex_init(&ctx.scanner);
596     ap_expr_yyset_extra(&ctx, ctx.scanner);
597     rc = ap_expr_yyparse(&ctx);
598     ap_expr_yylex_destroy(ctx.scanner);
599
600     /* ctx.error: the generic bison error message
601      *            (XXX: usually not very useful, should be axed)
602      * ctx.error2: an additional error message
603      */
604     if (ctx.error) {
605         if (ctx.error2)
606             return apr_psprintf(pool, "%s: %s", ctx.error, ctx.error2);
607         else
608             return ctx.error;
609     }
610     else if (ctx.error2) {
611         return ctx.error2;
612     }
613
614     if (rc) /* XXX can this happen? */
615         return "syntax error";
616
617 #ifdef AP_EXPR_DEBUG
618     if (ctx.expr)
619         expr_dump_tree(ctx.expr, NULL, APLOG_NOTICE, 2);
620 #endif
621
622     info->root_node = ctx.expr;
623
624     return NULL;
625 }
626
627 AP_DECLARE(ap_expr_info_t*) ap_expr_parse_cmd_mi(const cmd_parms *cmd,
628                                                  const char *expr,
629                                                  unsigned int flags,
630                                                  const char **err,
631                                                  ap_expr_lookup_fn_t *lookup_fn,
632                                                  int module_index)
633 {
634     ap_expr_info_t *info = apr_pcalloc(cmd->pool, sizeof(ap_expr_info_t));
635     info->filename = cmd->directive->filename;
636     info->line_number = cmd->directive->line_num;
637     info->flags = flags;
638     info->module_index = module_index;
639     *err = ap_expr_parse(cmd->pool, cmd->temp_pool, info, expr, lookup_fn);
640
641     if (*err)
642         return NULL;
643
644     return info;
645 }
646
647 ap_expr_t *ap_expr_make(ap_expr_node_op_e op, const void *a1, const void *a2,
648                         ap_expr_parse_ctx_t *ctx)
649 {
650     ap_expr_t *node = apr_palloc(ctx->pool, sizeof(ap_expr_t));
651     node->node_op   = op;
652     node->node_arg1 = a1;
653     node->node_arg2 = a2;
654     return node;
655 }
656
657 ap_expr_t *ap_expr_concat_make(const void *a1, const void *a2,
658                                ap_expr_parse_ctx_t *ctx)
659 {
660     const ap_expr_t *node;
661
662     /* Optimize out empty string(s) concatenation */
663     if ((node = a1)
664             && node->node_op == op_String
665             && !*(const char *)node->node_arg1) {
666         return (ap_expr_t *)a2;
667     }
668     if ((node = a2)
669             && node->node_op == op_String
670             && !*(const char *)node->node_arg1) {
671         return (ap_expr_t *)a1;
672     }
673
674     return ap_expr_make(op_Concat, a1, a2, ctx);
675 }
676
677 ap_expr_t *ap_expr_regex_make(const char *pattern, const ap_expr_t *subst,
678                               const char *flags, ap_expr_parse_ctx_t *ctx)
679 {
680     ap_expr_t *node = NULL;
681     ap_expr_regctx_t *regctx;
682     ap_regex_t *regex;
683
684     regctx = apr_pcalloc(ctx->pool, sizeof *regctx);
685     regctx->subst = subst;
686     if (flags) {
687         for (; *flags; ++flags) {
688             switch (*flags) {
689             case 'i':
690                 regctx->flags |= AP_REG_ICASE;
691                 break;
692             case 'm':
693                 regctx->flags |= AP_REG_NEWLINE;
694                 break;
695             case 's':
696                 regctx->flags |= AP_REG_DOTALL;
697                 break;
698             case 'g':
699                 regctx->flags |= AP_REG_MULTI;
700                 break;
701             }
702         }
703     }
704     regex = ap_pregcomp(ctx->pool, pattern, regctx->flags);
705     if (!regex) {
706         return NULL;
707     }
708
709     node = apr_palloc(ctx->pool, sizeof(ap_expr_t));
710     node->node_op   = op_Regex;
711     node->node_arg1 = regex;
712     node->node_arg2 = regctx;
713     return node;
714 }
715
716 static ap_expr_t *ap_expr_info_make(int type, const char *name,
717                                   ap_expr_parse_ctx_t *ctx,
718                                   const ap_expr_t *arg)
719 {
720     ap_expr_t *info = apr_palloc(ctx->pool, sizeof(ap_expr_t));
721     ap_expr_lookup_parms parms;
722     parms.type  = type;
723     parms.flags = ctx->flags;
724     parms.pool  = ctx->pool;
725     parms.ptemp = ctx->ptemp;
726     parms.name  = name;
727     parms.func  = &info->node_arg1;
728     parms.data  = &info->node_arg2;
729     parms.err   = &ctx->error2;
730     parms.arg   = NULL;
731     if (arg) {
732         switch(arg->node_op) {
733             case op_String:
734                 parms.arg = arg->node_arg1;
735                 break;
736             case op_ListElement:
737                 do {
738                     const ap_expr_t *val = arg->node_arg1;
739                     if (val->node_op == op_String) {
740                         parms.arg = val->node_arg1;
741                     }
742                     arg = arg->node_arg2;
743                 } while (arg != NULL);
744                 break;
745             default:
746                 break;
747         }
748     }
749     if (ctx->lookup_fn(&parms) != OK)
750         return NULL;
751     return info;
752 }
753
754 ap_expr_t *ap_expr_str_func_make(const char *name, const ap_expr_t *arg,
755                                ap_expr_parse_ctx_t *ctx)
756 {
757     ap_expr_t *info = ap_expr_info_make(AP_EXPR_FUNC_STRING, name, ctx, arg);
758     if (!info)
759         return NULL;
760
761     info->node_op = op_StringFuncInfo;
762     return ap_expr_make(op_StringFuncCall, info, arg, ctx);
763 }
764
765 ap_expr_t *ap_expr_list_func_make(const char *name, const ap_expr_t *arg,
766                                 ap_expr_parse_ctx_t *ctx)
767 {
768     ap_expr_t *info = ap_expr_info_make(AP_EXPR_FUNC_LIST, name, ctx, arg);
769     if (!info)
770         return NULL;
771
772     info->node_op = op_ListFuncInfo;
773     return ap_expr_make(op_ListFuncCall, info, arg, ctx);
774 }
775
776 ap_expr_t *ap_expr_unary_op_make(const char *name, const ap_expr_t *arg,
777                                ap_expr_parse_ctx_t *ctx)
778 {
779     ap_expr_t *info = ap_expr_info_make(AP_EXPR_FUNC_OP_UNARY, name, ctx, arg);
780     if (!info)
781         return NULL;
782
783     info->node_op = op_UnaryOpInfo;
784     return ap_expr_make(op_UnaryOpCall, info, arg, ctx);
785 }
786
787 ap_expr_t *ap_expr_binary_op_make(const char *name, const ap_expr_t *arg1,
788                                 const ap_expr_t *arg2, ap_expr_parse_ctx_t *ctx)
789 {
790     ap_expr_t *args;
791     ap_expr_t *info = ap_expr_info_make(AP_EXPR_FUNC_OP_BINARY, name, ctx,
792                                         arg2);
793     if (!info)
794         return NULL;
795
796     info->node_op = op_BinaryOpInfo;
797     args = ap_expr_make(op_BinaryOpArgs, arg1, arg2, ctx);
798     return ap_expr_make(op_BinaryOpCall, info, args, ctx);
799 }
800
801
802 ap_expr_t *ap_expr_var_make(const char *name, ap_expr_parse_ctx_t *ctx)
803 {
804     ap_expr_t *node = ap_expr_info_make(AP_EXPR_FUNC_VAR, name, ctx, NULL);
805     if (!node)
806         return NULL;
807
808     node->node_op = op_Var;
809     return node;
810 }
811
812 ap_expr_t *ap_expr_backref_make(int num, ap_expr_parse_ctx_t *ctx)
813 {
814     int *n = apr_pmemdup(ctx->pool, &num, sizeof(num));
815     return ap_expr_make(op_Backref, n, NULL, ctx);
816 }
817
818 #ifdef AP_EXPR_DEBUG
819
820 #define MARK                        APLOG_MARK,loglevel,0,s
821 #define DUMP_E_E(op, e1, e2)                                                \
822     do { ap_log_error(MARK,"%*s%s: %pp %pp", indent, " ", op, e1, e2);      \
823          if (e1) expr_dump_tree(e1, s, loglevel, indent + 2);               \
824          if (e2) expr_dump_tree(e2, s, loglevel, indent + 2);               \
825     } while (0)
826 #define DUMP_S_E(op, s1, e1)                                                    \
827     do { ap_log_error(MARK,"%*s%s: '%s' %pp", indent, " ", op, (char *)s1, e1); \
828          if (e1) expr_dump_tree(e1, s, loglevel, indent + 2);                   \
829     } while (0)
830 #define DUMP_S_P(op, s1, p1)                                                \
831     ap_log_error(MARK,"%*s%s: '%s' %pp", indent, " ", op, (char *)s1, p1);
832 #define DUMP_P_P(op, p1, p2)                                                \
833     ap_log_error(MARK,"%*s%s: %pp %pp", indent, " ", op, p1, p2);
834 #define DUMP_S_S(op, s1, s2)                                                       \
835     ap_log_error(MARK,"%*s%s: '%s' '%s'", indent, " ", op, (char *)s1, (char *)s2)
836 #define DUMP_P(op, p1)                                                      \
837     ap_log_error(MARK,"%*s%s: %pp", indent, " ", op, p1);
838 #define DUMP_IP(op, p1)                                                     \
839     ap_log_error(MARK,"%*s%s: %d", indent, " ", op, *(int *)p1);
840 #define DUMP_S(op, s1)                                                      \
841     ap_log_error(MARK,"%*s%s: '%s'", indent, " ", op, (char *)s1)
842
843 #define CASE_OP(op)                  case op: name = #op ; break;
844
845 static void expr_dump_tree(const ap_expr_t *e, const server_rec *s,
846                            int loglevel, int indent)
847 {
848     switch (e->node_op) {
849     /* no arg */
850     case op_NOP:
851     case op_True:
852     case op_False:
853         {
854             char *name;
855             switch (e->node_op) {
856             CASE_OP(op_NOP);
857             CASE_OP(op_True);
858             CASE_OP(op_False);
859             default:
860                 ap_assert(0);
861             }
862             ap_log_error(MARK, "%*s%s", indent, " ", name);
863         }
864         break;
865
866     /* arg1: string, arg2: expr */
867     case op_UnaryOpCall:
868     case op_BinaryOpCall:
869     case op_BinaryOpArgs:
870         {
871             char *name;
872             switch (e->node_op) {
873             CASE_OP(op_BinaryOpCall);
874             CASE_OP(op_UnaryOpCall);
875             CASE_OP(op_BinaryOpArgs);
876             default:
877                 ap_assert(0);
878             }
879             DUMP_S_E(name, e->node_arg1, e->node_arg2);
880         }
881         break;
882
883     /* arg1: expr, arg2: expr */
884     case op_Comp:
885     case op_Not:
886     case op_Or:
887     case op_And:
888     case op_EQ:
889     case op_NE:
890     case op_LT:
891     case op_LE:
892     case op_GT:
893     case op_GE:
894     case op_STR_EQ:
895     case op_STR_NE:
896     case op_STR_LT:
897     case op_STR_LE:
898     case op_STR_GT:
899     case op_STR_GE:
900     case op_IN:
901     case op_REG:
902     case op_NRE:
903     case op_Word:
904     case op_Bool:
905     case op_Sub:
906     case op_Join:
907     case op_Split:
908     case op_Concat:
909     case op_StringFuncCall:
910     case op_ListFuncCall:
911     case op_ListElement:
912         {
913             char *name;
914             switch (e->node_op) {
915             CASE_OP(op_Comp);
916             CASE_OP(op_Not);
917             CASE_OP(op_Or);
918             CASE_OP(op_And);
919             CASE_OP(op_EQ);
920             CASE_OP(op_NE);
921             CASE_OP(op_LT);
922             CASE_OP(op_LE);
923             CASE_OP(op_GT);
924             CASE_OP(op_GE);
925             CASE_OP(op_STR_EQ);
926             CASE_OP(op_STR_NE);
927             CASE_OP(op_STR_LT);
928             CASE_OP(op_STR_LE);
929             CASE_OP(op_STR_GT);
930             CASE_OP(op_STR_GE);
931             CASE_OP(op_IN);
932             CASE_OP(op_REG);
933             CASE_OP(op_NRE);
934             CASE_OP(op_Word);
935             CASE_OP(op_Bool);
936             CASE_OP(op_Sub);
937             CASE_OP(op_Join);
938             CASE_OP(op_Split);
939             CASE_OP(op_Concat);
940             CASE_OP(op_StringFuncCall);
941             CASE_OP(op_ListFuncCall);
942             CASE_OP(op_ListElement);
943             default:
944                 ap_assert(0);
945             }
946             DUMP_E_E(name, e->node_arg1, e->node_arg2);
947         }
948         break;
949     /* arg1: string */
950     case op_Digit:
951     case op_String:
952         {
953             char *name;
954             switch (e->node_op) {
955             CASE_OP(op_Digit);
956             CASE_OP(op_String);
957             default:
958                 ap_assert(0);
959             }
960             DUMP_S(name, e->node_arg1);
961         }
962         break;
963     /* arg1: pointer, arg2: pointer */
964     case op_Var:
965     case op_StringFuncInfo:
966     case op_UnaryOpInfo:
967     case op_BinaryOpInfo:
968     case op_ListFuncInfo:
969         {
970             char *name;
971             switch (e->node_op) {
972             CASE_OP(op_Var);
973             CASE_OP(op_StringFuncInfo);
974             CASE_OP(op_UnaryOpInfo);
975             CASE_OP(op_BinaryOpInfo);
976             CASE_OP(op_ListFuncInfo);
977             default:
978                 ap_assert(0);
979             }
980             DUMP_P_P(name, e->node_arg1, e->node_arg2);
981         }
982         break;
983     /* arg1: pointer */
984     case op_Regex:
985         DUMP_P("op_Regex", e->node_arg1);
986         break;
987     /* arg1: pointer to int */
988     case op_Backref:
989         DUMP_IP("op_Backref", e->node_arg1);
990         break;
991     default:
992         ap_log_error(MARK, "%*sERROR: INVALID OP %d", indent, " ", e->node_op);
993         break;
994     }
995 }
996 #endif /* AP_EXPR_DEBUG */
997
998 static int ap_expr_eval_unary_op(ap_expr_eval_ctx_t *ctx, const ap_expr_t *info,
999                                  const ap_expr_t *arg)
1000 {
1001     ap_expr_op_unary_t *op_func = (ap_expr_op_unary_t *)info->node_arg1;
1002     const void *data = info->node_arg2;
1003
1004     AP_DEBUG_ASSERT(info->node_op == op_UnaryOpInfo);
1005     AP_DEBUG_ASSERT(op_func != NULL);
1006     AP_DEBUG_ASSERT(data != NULL);
1007     return (*op_func)(ctx, data, ap_expr_eval_word(ctx, arg));
1008 }
1009
1010 static int ap_expr_eval_binary_op(ap_expr_eval_ctx_t *ctx,
1011                                   const ap_expr_t *info,
1012                                   const ap_expr_t *args)
1013 {
1014     ap_expr_op_binary_t *op_func = (ap_expr_op_binary_t *)info->node_arg1;
1015     const void *data = info->node_arg2;
1016     const ap_expr_t *a1 = args->node_arg1;
1017     const ap_expr_t *a2 = args->node_arg2;
1018
1019     AP_DEBUG_ASSERT(info->node_op == op_BinaryOpInfo);
1020     AP_DEBUG_ASSERT(args->node_op == op_BinaryOpArgs);
1021     AP_DEBUG_ASSERT(op_func != NULL);
1022     AP_DEBUG_ASSERT(data != NULL);
1023     return (*op_func)(ctx, data, ap_expr_eval_word(ctx, a1),
1024                       ap_expr_eval_word(ctx, a2));
1025 }
1026
1027
1028 static int ap_expr_eval_cond(ap_expr_eval_ctx_t *ctx, const ap_expr_t *node)
1029 {
1030     const ap_expr_t *e1 = node->node_arg1;
1031     const ap_expr_t *e2 = node->node_arg2;
1032     int result = FALSE;
1033     if (inc_rec(ctx))
1034         return result;
1035     while (1) {
1036         switch (node->node_op) {
1037         case op_True:
1038             result ^= TRUE;
1039             goto out;
1040         case op_False:
1041             result ^= FALSE;
1042             goto out;
1043         case op_Not:
1044             result = !result;
1045             node = e1;
1046             break;
1047         case op_Or:
1048             do {
1049                 if (e1->node_op == op_Not) {
1050                     if (!ap_expr_eval_cond(ctx, e1->node_arg1)) {
1051                         result ^= TRUE;
1052                         goto out;
1053                     }
1054                 }
1055                 else {
1056                     if (ap_expr_eval_cond(ctx, e1)) {
1057                         result ^= TRUE;
1058                         goto out;
1059                     }
1060                 }
1061                 node = node->node_arg2;
1062                 e1 = node->node_arg1;
1063             } while (node->node_op == op_Or);
1064             break;
1065         case op_And:
1066             do {
1067                 if (e1->node_op == op_Not) {
1068                     if (ap_expr_eval_cond(ctx, e1->node_arg1)) {
1069                         result ^= FALSE;
1070                         goto out;
1071                     }
1072                 }
1073                 else {
1074                     if (!ap_expr_eval_cond(ctx, e1)) {
1075                         result ^= FALSE;
1076                         goto out;
1077                     }
1078                 }
1079                 node = node->node_arg2;
1080                 e1 = node->node_arg1;
1081             } while (node->node_op == op_And);
1082             break;
1083         case op_UnaryOpCall:
1084             result ^= ap_expr_eval_unary_op(ctx, e1, e2);
1085             goto out;
1086         case op_BinaryOpCall:
1087             result ^= ap_expr_eval_binary_op(ctx, e1, e2);
1088             goto out;
1089         case op_Comp:
1090             if (ctx->info->flags & AP_EXPR_FLAG_SSL_EXPR_COMPAT)
1091                 result ^= ssl_expr_eval_comp(ctx, e1);
1092             else
1093                 result ^= ap_expr_eval_comp(ctx, e1);
1094             goto out;
1095         default:
1096             *ctx->err = "Internal evaluation error: Unknown expression node";
1097             goto out;
1098         }
1099         e1 = node->node_arg1;
1100         e2 = node->node_arg2;
1101     }
1102 out:
1103     ctx->reclvl--;
1104     return result;
1105 }
1106
1107 AP_DECLARE(int) ap_expr_exec(request_rec *r, const ap_expr_info_t *info,
1108                              const char **err)
1109 {
1110     return ap_expr_exec_re(r, info, 0, NULL, NULL, err);
1111 }
1112
1113 AP_DECLARE(int) ap_expr_exec_ctx(ap_expr_eval_ctx_t *ctx)
1114 {
1115     int rc;
1116
1117     AP_DEBUG_ASSERT(ctx->p != NULL);
1118     /* XXX: allow r, c == NULL */
1119     AP_DEBUG_ASSERT(ctx->r != NULL);
1120     AP_DEBUG_ASSERT(ctx->c != NULL);
1121     AP_DEBUG_ASSERT(ctx->s != NULL);
1122     AP_DEBUG_ASSERT(ctx->err != NULL);
1123     AP_DEBUG_ASSERT(ctx->info != NULL);
1124     if (ctx->re_pmatch) {
1125         AP_DEBUG_ASSERT(ctx->re_source != NULL);
1126         AP_DEBUG_ASSERT(ctx->re_nmatch > 0);
1127     }
1128     ctx->reclvl = 0;
1129
1130     *ctx->err = NULL;
1131     if (ctx->info->flags & AP_EXPR_FLAG_STRING_RESULT) {
1132         *ctx->result_string = ap_expr_eval_word(ctx, ctx->info->root_node);
1133         if (*ctx->err != NULL) {
1134             ap_log_rerror(LOG_MARK(ctx->info), APLOG_ERR, 0, ctx->r,
1135                           APLOGNO(03298)
1136                           "Evaluation of string expression from %s:%d failed: %s",
1137                           ctx->info->filename, ctx->info->line_number, *ctx->err);
1138             return -1;
1139         } else {
1140             ap_log_rerror(LOG_MARK(ctx->info), APLOG_TRACE4, 0, ctx->r,
1141                           "Evaluation of string expression from %s:%d gave: %s",
1142                           ctx->info->filename, ctx->info->line_number,
1143                           *ctx->result_string);
1144             return 1;
1145         }
1146     }
1147     else {
1148         rc = ap_expr_eval_cond(ctx, ctx->info->root_node);
1149         if (*ctx->err != NULL) {
1150             ap_log_rerror(LOG_MARK(ctx->info), APLOG_ERR, 0, ctx->r,
1151                           APLOGNO(03299)
1152                           "Evaluation of expression from %s:%d failed: %s",
1153                           ctx->info->filename, ctx->info->line_number, *ctx->err);
1154             return -1;
1155         } else {
1156             rc = rc ? 1 : 0;
1157             ap_log_rerror(LOG_MARK(ctx->info), APLOG_TRACE4, 0, ctx->r,
1158                           "Evaluation of expression from %s:%d gave: %d",
1159                           ctx->info->filename, ctx->info->line_number, rc);
1160
1161             if (ctx->vary_this && *ctx->vary_this)
1162                 apr_table_merge(ctx->r->headers_out, "Vary", *ctx->vary_this);
1163
1164             return rc;
1165         }
1166     }
1167 }
1168
1169 AP_DECLARE(int) ap_expr_exec_re(request_rec *r, const ap_expr_info_t *info,
1170                                 apr_size_t nmatch, ap_regmatch_t *pmatch,
1171                                 const char **source, const char **err)
1172 {
1173     ap_expr_eval_ctx_t ctx;
1174     int dont_vary = (info->flags & AP_EXPR_FLAG_DONT_VARY);
1175     const char *tmp_source = NULL, *vary_this = NULL;
1176     ap_regmatch_t tmp_pmatch[AP_MAX_REG_MATCH];
1177
1178     AP_DEBUG_ASSERT((info->flags & AP_EXPR_FLAG_STRING_RESULT) == 0);
1179
1180     ctx.r = r;
1181     ctx.c = r->connection;
1182     ctx.s = r->server;
1183     ctx.p = r->pool;
1184     ctx.err  = err;
1185     ctx.info = info;
1186     ctx.re_nmatch = nmatch;
1187     ctx.re_pmatch = pmatch;
1188     ctx.re_source = source;
1189     ctx.vary_this = dont_vary ? NULL : &vary_this;
1190     ctx.data = NULL;
1191
1192     if (!pmatch) {
1193         ctx.re_nmatch = AP_MAX_REG_MATCH;
1194         ctx.re_pmatch = tmp_pmatch;
1195         ctx.re_source = &tmp_source;
1196     }
1197
1198     return ap_expr_exec_ctx(&ctx);
1199 }
1200
1201 AP_DECLARE(const char *) ap_expr_str_exec_re(request_rec *r,
1202                                              const ap_expr_info_t *info,
1203                                              apr_size_t nmatch,
1204                                              ap_regmatch_t *pmatch,
1205                                              const char **source,
1206                                              const char **err)
1207 {
1208     ap_expr_eval_ctx_t ctx;
1209     int dont_vary, rc;
1210     const char *tmp_source, *vary_this;
1211     ap_regmatch_t tmp_pmatch[AP_MAX_REG_MATCH];
1212     const char *result;
1213
1214     AP_DEBUG_ASSERT(info->flags & AP_EXPR_FLAG_STRING_RESULT);
1215
1216     if (info->root_node->node_op == op_String) {
1217         /* short-cut for constant strings */
1218         *err = NULL;
1219         return (const char *)info->root_node->node_arg1;
1220     }
1221
1222     tmp_source = NULL;
1223     vary_this = NULL;
1224
1225     dont_vary = (info->flags & AP_EXPR_FLAG_DONT_VARY);
1226
1227     ctx.r = r;
1228     ctx.c = r->connection;
1229     ctx.s = r->server;
1230     ctx.p = r->pool;
1231     ctx.err  = err;
1232     ctx.info = info;
1233     ctx.re_nmatch = nmatch;
1234     ctx.re_pmatch = pmatch;
1235     ctx.re_source = source;
1236     ctx.vary_this = dont_vary ? NULL : &vary_this;
1237     ctx.data = NULL;
1238     ctx.result_string = &result;
1239
1240     if (!pmatch) {
1241         ctx.re_nmatch = AP_MAX_REG_MATCH;
1242         ctx.re_pmatch = tmp_pmatch;
1243         ctx.re_source = &tmp_source;
1244     }
1245
1246     rc = ap_expr_exec_ctx(&ctx);
1247     if (rc > 0)
1248         return result;
1249     else if (rc < 0)
1250         return NULL;
1251     else
1252         ap_assert(0);
1253     /* Not reached */
1254     return NULL;
1255 }
1256
1257 AP_DECLARE(const char *) ap_expr_str_exec(request_rec *r,
1258                                           const ap_expr_info_t *info,
1259                                           const char **err)
1260 {
1261     return ap_expr_str_exec_re(r, info, 0, NULL, NULL, err);
1262 }
1263
1264
1265 static void add_vary(ap_expr_eval_ctx_t *ctx, const char *name)
1266 {
1267     if (!ctx->vary_this)
1268         return;
1269
1270     if (*ctx->vary_this) {
1271         *ctx->vary_this = apr_pstrcat(ctx->p, *ctx->vary_this, ", ", name,
1272                                       NULL);
1273     }
1274     else {
1275         *ctx->vary_this = name;
1276     }
1277 }
1278
1279 static const char *req_table_func(ap_expr_eval_ctx_t *ctx, const void *data,
1280                                   const char *arg)
1281 {
1282     const char *name = (const char *)data;
1283     apr_table_t *t;
1284     if (!ctx->r)
1285         return "";
1286
1287     if (name[2] == 's') {           /* resp */
1288         /* Try r->headers_out first, fall back on err_headers_out. */
1289         const char *v = apr_table_get(ctx->r->headers_out, arg);
1290         if (v) {
1291             return v;
1292         }
1293         t = ctx->r->err_headers_out;
1294     }
1295     else if (name[0] == 'n')        /* notes */
1296         t = ctx->r->notes;
1297     else if (name[3] == 'e')        /* reqenv */
1298         t = ctx->r->subprocess_env;
1299     else if (name[3] == '_')        /* req_novary */
1300         t = ctx->r->headers_in;
1301     else {                          /* req, http */
1302         t = ctx->r->headers_in;
1303         /* Skip the 'Vary: Host' header combination
1304          * as indicated in rfc7231 section-7.1.4
1305          */
1306         if (strcasecmp(arg, "Host")){
1307             add_vary(ctx, arg);
1308         }
1309     }
1310     return apr_table_get(t, arg);
1311 }
1312
1313 static const char *env_func(ap_expr_eval_ctx_t *ctx, const void *data,
1314                             const char *arg)
1315 {
1316     const char *res;
1317     /* this order is for ssl_expr compatibility */
1318     if (ctx->r) {
1319         if ((res = apr_table_get(ctx->r->notes, arg)) != NULL)
1320             return res;
1321         else if ((res = apr_table_get(ctx->r->subprocess_env, arg)) != NULL)
1322             return res;
1323     }
1324     return getenv(arg);
1325 }
1326
1327 static const char *osenv_func(ap_expr_eval_ctx_t *ctx, const void *data,
1328                               const char *arg)
1329 {
1330     return getenv(arg);
1331 }
1332
1333 static const char *tolower_func(ap_expr_eval_ctx_t *ctx, const void *data,
1334                                 const char *arg)
1335 {
1336     char *result = apr_pstrdup(ctx->p, arg);
1337     ap_str_tolower(result);
1338     return result;
1339 }
1340
1341 static const char *toupper_func(ap_expr_eval_ctx_t *ctx, const void *data,
1342                                 const char *arg)
1343 {
1344     char *result = apr_pstrdup(ctx->p, arg);
1345     ap_str_toupper(result);
1346     return result;
1347 }
1348
1349 static const char *escape_func(ap_expr_eval_ctx_t *ctx, const void *data,
1350                                const char *arg)
1351 {
1352     return ap_escape_uri(ctx->p, arg);
1353 }
1354
1355 static const char *base64_func(ap_expr_eval_ctx_t *ctx, const void *data,
1356                                const char *arg)
1357 {
1358     return ap_pbase64encode(ctx->p, (char *)arg);
1359 }
1360
1361 static const char *unbase64_func(ap_expr_eval_ctx_t *ctx, const void *data,
1362                                const char *arg)
1363 {
1364     return ap_pbase64decode(ctx->p, arg);
1365 }
1366
1367 static const char *sha1_func(ap_expr_eval_ctx_t *ctx, const void *data,
1368                                const char *arg)
1369 {
1370     apr_sha1_ctx_t context;
1371     apr_byte_t sha1[APR_SHA1_DIGESTSIZE];
1372     char *out;
1373
1374     out = apr_palloc(ctx->p, APR_SHA1_DIGESTSIZE*2+1);
1375
1376     apr_sha1_init(&context);
1377     apr_sha1_update(&context, arg, strlen(arg));
1378     apr_sha1_final(sha1, &context);
1379
1380     ap_bin2hex(sha1, APR_SHA1_DIGESTSIZE, out);
1381
1382     return out;
1383 }
1384
1385 static const char *md5_func(ap_expr_eval_ctx_t *ctx, const void *data,
1386                                const char *arg)
1387 {
1388     return ap_md5(ctx->p, (const unsigned char *)arg);
1389 }
1390
1391 #if APR_VERSION_AT_LEAST(1,6,0)
1392 static const char *ldap_func(ap_expr_eval_ctx_t *ctx, const void *data,
1393                                const char *arg)
1394 {
1395     return apr_pescape_ldap(ctx->p, arg, APR_ESCAPE_STRING, APR_ESCAPE_LDAP_ALL);
1396 }
1397 #endif
1398
1399 static int replace_func_parse_arg(ap_expr_lookup_parms *parms)
1400 {
1401     const char *original = parms->arg;
1402     const apr_strmatch_pattern *pattern;
1403
1404     if (!parms->arg) {
1405         *parms->err = apr_psprintf(parms->ptemp, "replace() function needs "
1406                                    "exactly 3 arguments");
1407         return !OK;
1408     }
1409     pattern = apr_strmatch_precompile(parms->pool, original, 0);
1410     *parms->data = pattern;
1411     return OK;
1412 }
1413
1414 static const char *replace_func(ap_expr_eval_ctx_t *ctx, const void *data,
1415                                const apr_array_header_t *args)
1416 {
1417     char *buff, *original, *replacement;
1418     struct ap_varbuf vb;
1419     apr_size_t repl_len, orig_len;
1420     const char *repl;
1421     apr_size_t bytes;
1422     apr_size_t len;
1423     const apr_strmatch_pattern *pattern = data;
1424     if (args->nelts != 3) {
1425         *ctx->err = apr_psprintf(ctx->p, "replace() function needs "
1426                                  "exactly 3 arguments");
1427         return "";
1428     }
1429
1430     buff = APR_ARRAY_IDX(args, 2, char *);
1431     original = APR_ARRAY_IDX(args, 1, char *);
1432     replacement = APR_ARRAY_IDX(args, 0, char *);
1433     repl_len = strlen(replacement);
1434     orig_len = strlen(original);
1435     bytes = strlen(buff);
1436
1437     ap_varbuf_init(ctx->p, &vb, 0);
1438     vb.strlen = 0;
1439     
1440     while ((repl = apr_strmatch(pattern, buff, bytes))) {
1441         len = (apr_size_t) (repl - buff);
1442         ap_varbuf_strmemcat(&vb, buff, len);
1443         ap_varbuf_strmemcat(&vb, replacement, repl_len);
1444
1445         len += orig_len;
1446         bytes -= len;
1447         buff += len;
1448     }
1449
1450     return ap_varbuf_pdup(ctx->p, &vb, NULL, 0, buff, bytes, &len);
1451 }
1452
1453 #define MAX_FILE_SIZE 10*1024*1024
1454 static const char *file_func(ap_expr_eval_ctx_t *ctx, const void *data,
1455                              char *arg)
1456 {
1457     apr_file_t *fp;
1458     char *buf;
1459     apr_off_t offset;
1460     apr_size_t len;
1461     apr_finfo_t finfo;
1462
1463     if (apr_file_open(&fp, arg, APR_READ|APR_BUFFERED,
1464                       APR_OS_DEFAULT, ctx->p) != APR_SUCCESS) {
1465         *ctx->err = apr_psprintf(ctx->p, "Cannot open file %s", arg);
1466         return "";
1467     }
1468     apr_file_info_get(&finfo, APR_FINFO_SIZE, fp);
1469     if (finfo.size > MAX_FILE_SIZE) {
1470         *ctx->err = apr_psprintf(ctx->p, "File %s too large", arg);
1471         apr_file_close(fp);
1472         return "";
1473     }
1474     len = (apr_size_t)finfo.size;
1475     if (len == 0) {
1476         apr_file_close(fp);
1477         return "";
1478     }
1479     else {
1480         if ((buf = (char *)apr_palloc(ctx->p, sizeof(char)*(len+1))) == NULL) {
1481             *ctx->err = "Cannot allocate memory";
1482             apr_file_close(fp);
1483             return "";
1484         }
1485         offset = 0;
1486         apr_file_seek(fp, APR_SET, &offset);
1487         if (apr_file_read(fp, buf, &len) != APR_SUCCESS) {
1488             *ctx->err = apr_psprintf(ctx->p, "Cannot read from file %s", arg);
1489             apr_file_close(fp);
1490             return "";
1491         }
1492         buf[len] = '\0';
1493     }
1494     apr_file_close(fp);
1495     return buf;
1496 }
1497
1498 static const char *filesize_func(ap_expr_eval_ctx_t *ctx, const void *data,
1499                                   char *arg)
1500 {
1501     apr_finfo_t sb;
1502     if (apr_stat(&sb, arg, APR_FINFO_MIN, ctx->p) == APR_SUCCESS
1503         && sb.filetype == APR_REG && sb.size > 0)
1504         return apr_psprintf(ctx->p, "%" APR_OFF_T_FMT, sb.size);
1505     else
1506         return "0";
1507 }
1508
1509 static const char *filemod_func(ap_expr_eval_ctx_t *ctx, const void *data,
1510                                   char *arg)
1511 {
1512     apr_finfo_t sb;
1513     if (apr_stat(&sb, arg, APR_FINFO_MIN, ctx->p) == APR_SUCCESS
1514         && sb.filetype == APR_REG && sb.mtime > 0)
1515         return apr_psprintf(ctx->p, "%" APR_OFF_T_FMT, (apr_off_t)sb.mtime);
1516     else
1517         return "0";
1518 }
1519
1520
1521 static const char *unescape_func(ap_expr_eval_ctx_t *ctx, const void *data,
1522                                  const char *arg)
1523 {
1524     char *result = apr_pstrdup(ctx->p, arg);
1525     int ret = ap_unescape_url_keep2f(result, 0);
1526     if (ret == OK)
1527         return result;
1528     ap_log_rerror(LOG_MARK(ctx->info), APLOG_DEBUG, 0, ctx->r, APLOGNO(00538)
1529                   "%s %% escape in unescape('%s') at %s:%d",
1530                   ret == HTTP_BAD_REQUEST ? "Bad" : "Forbidden", arg,
1531                   ctx->info->filename, ctx->info->line_number);
1532     return "";
1533 }
1534
1535 static int op_nz(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
1536 {
1537     const char *name = (const char *)data;
1538     if (name[0] == 'z')
1539         return (arg[0] == '\0');
1540     else
1541         return (arg[0] != '\0');
1542 }
1543
1544 static int op_file_min(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
1545 {
1546     apr_finfo_t sb;
1547     const char *name = (const char *)data;
1548     if (apr_stat(&sb, arg, APR_FINFO_MIN, ctx->p) != APR_SUCCESS)
1549         return FALSE;
1550     switch (name[0]) {
1551     case 'd':
1552         return (sb.filetype == APR_DIR);
1553     case 'e':
1554         return TRUE;
1555     case 'f':
1556         return (sb.filetype == APR_REG);
1557     case 's':
1558         return (sb.filetype == APR_REG && sb.size > 0);
1559     default:
1560         ap_assert(0);
1561     }
1562     return FALSE;
1563 }
1564
1565 static int op_file_link(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
1566 {
1567 #if !defined(OS2)
1568     apr_finfo_t sb;
1569     if (apr_stat(&sb, arg, APR_FINFO_MIN | APR_FINFO_LINK, ctx->p) == APR_SUCCESS
1570         && sb.filetype == APR_LNK) {
1571         return TRUE;
1572     }
1573 #endif
1574     return FALSE;
1575 }
1576
1577 static int op_file_xbit(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
1578 {
1579     apr_finfo_t sb;
1580     if (apr_stat(&sb, arg, APR_FINFO_PROT| APR_FINFO_LINK, ctx->p) == APR_SUCCESS
1581         && (sb.protection & (APR_UEXECUTE | APR_GEXECUTE | APR_WEXECUTE))) {
1582         return TRUE;
1583     }
1584     return FALSE;
1585 }
1586
1587 static int op_url_subr(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
1588 {
1589     int rc = FALSE;
1590     request_rec  *rsub, *r = ctx->r;
1591     if (!r)
1592         return FALSE;
1593     /* avoid some infinite recursions */
1594     if (r->main && r->main->uri && r->uri && strcmp(r->main->uri, r->uri) == 0)
1595         return FALSE;
1596
1597     rsub = ap_sub_req_lookup_uri(arg, r, NULL);
1598     if (rsub->status < 400) {
1599             rc = TRUE;
1600     }
1601     ap_log_rerror(LOG_MARK(ctx->info), APLOG_TRACE5, 0, r,
1602                   "Subrequest for -U %s at %s:%d gave status: %d",
1603                   arg, ctx->info->filename, ctx->info->line_number,
1604                   rsub->status);
1605     ap_destroy_sub_req(rsub);
1606     return rc;
1607 }
1608
1609 static int op_file_subr(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
1610 {
1611     int rc = FALSE;
1612     apr_finfo_t sb;
1613     request_rec *rsub, *r = ctx->r;
1614     if (!r)
1615         return FALSE;
1616     rsub = ap_sub_req_lookup_file(arg, r, NULL);
1617     if (rsub->status < 300 &&
1618         /* double-check that file exists since default result is 200 */
1619         apr_stat(&sb, rsub->filename, APR_FINFO_MIN, ctx->p) == APR_SUCCESS) {
1620         rc = TRUE;
1621     }
1622     ap_log_rerror(LOG_MARK(ctx->info), APLOG_TRACE5, 0, r,
1623                   "Subrequest for -F %s at %s:%d gave status: %d",
1624                   arg, ctx->info->filename, ctx->info->line_number,
1625                   rsub->status);
1626     ap_destroy_sub_req(rsub);
1627     return rc;
1628 }
1629
1630
1631 APR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec *));
1632 static APR_OPTIONAL_FN_TYPE(ssl_is_https) *is_https = NULL;
1633
1634 APR_DECLARE_OPTIONAL_FN(int, http2_is_h2, (conn_rec *));
1635 static APR_OPTIONAL_FN_TYPE(http2_is_h2) *is_http2 = NULL;
1636
1637 static const char *conn_var_names[] = {
1638     "HTTPS",                    /*  0 */
1639     "IPV6",                     /*  1 */
1640     "CONN_LOG_ID",              /*  2 */
1641     "CONN_REMOTE_ADDR",         /*  3 */
1642     "HTTP2",                    /*  4 */
1643     NULL
1644 };
1645
1646 static const char *conn_var_fn(ap_expr_eval_ctx_t *ctx, const void *data)
1647 {
1648     int index = ((const char **)data - conn_var_names);
1649     conn_rec *c = ctx->c;
1650     if (!c)
1651         return "";
1652
1653     switch (index) {
1654     case 0:
1655         if (is_https && is_https(c))
1656             return "on";
1657         else
1658             return "off";
1659     case 1:
1660 #if APR_HAVE_IPV6
1661         {
1662             apr_sockaddr_t *addr = c->client_addr;
1663             if (addr->family == AF_INET6
1664                 && !IN6_IS_ADDR_V4MAPPED((struct in6_addr *)addr->ipaddr_ptr))
1665                 return "on";
1666             else
1667                 return "off";
1668         }
1669 #else
1670         return "off";
1671 #endif
1672     case 2:
1673         return c->log_id;
1674     case 3:
1675         return c->client_ip;
1676     case 4:
1677         if (is_http2 && is_http2(c))
1678             return "on";
1679         else
1680             return "off";
1681     default:
1682         ap_assert(0);
1683         return NULL;
1684     }
1685 }
1686
1687 static const char *request_var_names[] = {
1688     "REQUEST_METHOD",           /*  0 */
1689     "REQUEST_SCHEME",           /*  1 */
1690     "REQUEST_URI",              /*  2 */
1691     "REQUEST_FILENAME",         /*  3 */
1692     "REMOTE_HOST",              /*  4 */
1693     "REMOTE_IDENT",             /*  5 */
1694     "REMOTE_USER",              /*  6 */
1695     "SERVER_ADMIN",             /*  7 */
1696     "SERVER_NAME",              /*  8 */
1697     "SERVER_PORT",              /*  9 */
1698     "SERVER_PROTOCOL",          /* 10 */
1699     "SCRIPT_FILENAME",          /* 11 */
1700     "PATH_INFO",                /* 12 */
1701     "QUERY_STRING",             /* 13 */
1702     "IS_SUBREQ",                /* 14 */
1703     "DOCUMENT_ROOT",            /* 15 */
1704     "AUTH_TYPE",                /* 16 */
1705     "THE_REQUEST",              /* 17 */
1706     "CONTENT_TYPE",             /* 18 */
1707     "HANDLER",                  /* 19 */
1708     "REQUEST_LOG_ID",           /* 20 */
1709     "SCRIPT_USER",              /* 21 */
1710     "SCRIPT_GROUP",             /* 22 */
1711     "DOCUMENT_URI",             /* 23 */
1712     "LAST_MODIFIED",            /* 24 */
1713     "CONTEXT_PREFIX",           /* 25 */
1714     "CONTEXT_DOCUMENT_ROOT",    /* 26 */
1715     "REQUEST_STATUS",           /* 27 */
1716     "REMOTE_ADDR",              /* 28 */
1717     "SERVER_PROTOCOL_VERSION",  /* 29 */
1718     "SERVER_PROTOCOL_VERSION_MAJOR",  /* 30 */
1719     "SERVER_PROTOCOL_VERSION_MINOR",  /* 31 */
1720     "REMOTE_PORT",                    /* 32 */
1721     NULL
1722 };
1723
1724 static const char *request_var_fn(ap_expr_eval_ctx_t *ctx, const void *data)
1725 {
1726     int index = ((const char **)data - request_var_names);
1727     request_rec *r = ctx->r;
1728     if (!r)
1729         return "";
1730
1731     switch (index) {
1732     case 0:
1733         return r->method;
1734     case 1:
1735         return ap_http_scheme(r);
1736     case 2:
1737         return r->uri;
1738     case 3:
1739         return r->filename;
1740     case 4:
1741         return ap_get_useragent_host(r, REMOTE_NAME, NULL);
1742     case 5:
1743         return ap_get_remote_logname(r);
1744     case 6:
1745         return r->user;
1746     case 7:
1747         return r->server->server_admin;
1748     case 8:
1749         return ap_get_server_name_for_url(r);
1750     case 9:
1751         return apr_psprintf(ctx->p, "%u", ap_get_server_port(r));
1752     case 10:
1753         return r->protocol;
1754     case 11:
1755         return r->filename;
1756     case 12:
1757         return r->path_info;
1758     case 13:
1759         return r->args;
1760     case 14:
1761         return (r->main != NULL ? "true" : "false");
1762     case 15:
1763         return ap_document_root(r);
1764     case 16:
1765         return r->ap_auth_type;
1766     case 17:
1767         return r->the_request;
1768     case 18:
1769         return r->content_type;
1770     case 19:
1771         return r->handler;
1772     case 20:
1773         return r->log_id;
1774     case 21:
1775         {
1776             char *result = "";
1777             if (r->finfo.valid & APR_FINFO_USER)
1778                 apr_uid_name_get(&result, r->finfo.user, ctx->p);
1779             return result;
1780         }
1781     case 22:
1782         {
1783             char *result = "";
1784             if (r->finfo.valid & APR_FINFO_USER)
1785                 apr_gid_name_get(&result, r->finfo.group, ctx->p);
1786             return result;
1787         }
1788     case 23:
1789         {
1790             const char *uri = apr_table_get(r->subprocess_env, "DOCUMENT_URI");
1791             return uri ? uri : r->uri;
1792         }
1793     case 24:
1794         {
1795             apr_time_exp_t tm;
1796             apr_time_exp_lt(&tm, r->mtime);
1797             return apr_psprintf(ctx->p, "%02d%02d%02d%02d%02d%02d%02d",
1798                                 (tm.tm_year / 100) + 19, (tm.tm_year % 100),
1799                                 tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min,
1800                                 tm.tm_sec);
1801         }
1802     case 25:
1803         return ap_context_prefix(r);
1804     case 26:
1805         return ap_context_document_root(r);
1806     case 27:
1807         return r->status ? apr_psprintf(ctx->p, "%d", r->status) : "";
1808     case 28:
1809         return r->useragent_ip;
1810     case 29:
1811         switch (r->proto_num) {
1812         case 1001:  return "1001";   /* 1.1 */
1813         case 1000:  return "1000";   /* 1.0 */
1814         case 9:     return "9";      /* 0.9 */
1815         }
1816         return apr_psprintf(ctx->p, "%d", r->proto_num);
1817     case 30:
1818         switch (HTTP_VERSION_MAJOR(r->proto_num)) {
1819         case 0:     return "0";
1820         case 1:     return "1";
1821         }
1822         return apr_psprintf(ctx->p, "%d", HTTP_VERSION_MAJOR(r->proto_num));
1823     case 31:
1824         switch (HTTP_VERSION_MINOR(r->proto_num)) {
1825         case 0:     return "0";
1826         case 1:     return "1";
1827         case 9:     return "9";
1828         }
1829         return apr_psprintf(ctx->p, "%d", HTTP_VERSION_MINOR(r->proto_num));
1830     case 32:
1831         return apr_psprintf(ctx->p, "%u", ctx->c->client_addr->port);
1832     default:
1833         ap_assert(0);
1834         return NULL;
1835     }
1836 }
1837
1838 static const char *req_header_var_names[] = {
1839     "HTTP_USER_AGENT",       /* 0 */
1840     "HTTP_PROXY_CONNECTION", /* 1 */
1841     "HTTP_REFERER",          /* 2 */
1842     "HTTP_COOKIE",           /* 3 */
1843     "HTTP_FORWARDED",        /* 4 */
1844     "HTTP_HOST",             /* 5 */
1845     "HTTP_ACCEPT",           /* 6 */
1846     NULL
1847 };
1848
1849 static const char *req_header_header_names[] = {
1850     "User-Agent",
1851     "Proxy-Connection",
1852     "Referer",
1853     "Cookie",
1854     "Forwarded",
1855     "Host",
1856     "Accept"
1857 };
1858
1859 static const char *req_header_var_fn(ap_expr_eval_ctx_t *ctx, const void *data)
1860 {
1861     const char **varname = (const char **)data;
1862     int index = (varname - req_header_var_names);
1863     const char *name;
1864
1865     AP_DEBUG_ASSERT(index < 7);
1866     if (!ctx->r)
1867         return "";
1868
1869     name = req_header_header_names[index];
1870     /* Skip the 'Vary: Host' header combination
1871      * as indicated in rfc7231 section-7.1.4
1872      */
1873     if (strcasecmp(name, "Host")){
1874         add_vary(ctx, name);
1875     }
1876     return apr_table_get(ctx->r->headers_in, name);
1877 }
1878
1879 static const char *misc_var_names[] = {
1880     "TIME_YEAR",        /* 0 */
1881     "TIME_MON",         /* 1 */
1882     "TIME_DAY",         /* 2 */
1883     "TIME_HOUR",        /* 3 */
1884     "TIME_MIN",         /* 4 */
1885     "TIME_SEC",         /* 5 */
1886     "TIME_WDAY",        /* 6 */
1887     "TIME",             /* 7 */
1888     "SERVER_SOFTWARE",  /* 8 */
1889     "API_VERSION",      /* 9 */
1890     NULL
1891 };
1892
1893 static const char *misc_var_fn(ap_expr_eval_ctx_t *ctx, const void *data)
1894 {
1895     apr_time_exp_t tm;
1896     int index = ((const char **)data - misc_var_names);
1897     apr_time_exp_lt(&tm, apr_time_now());
1898
1899     switch (index) {
1900     case 0:
1901         return apr_psprintf(ctx->p, "%02d%02d", (tm.tm_year / 100) + 19,
1902                             tm.tm_year % 100);
1903     case 1:
1904         return apr_psprintf(ctx->p, "%02d", tm.tm_mon+1);
1905     case 2:
1906         return apr_psprintf(ctx->p, "%02d", tm.tm_mday);
1907     case 3:
1908         return apr_psprintf(ctx->p, "%02d", tm.tm_hour);
1909     case 4:
1910         return apr_psprintf(ctx->p, "%02d", tm.tm_min);
1911     case 5:
1912         return apr_psprintf(ctx->p, "%02d", tm.tm_sec);
1913     case 6:
1914         return apr_psprintf(ctx->p, "%d", tm.tm_wday);
1915     case 7:
1916         return apr_psprintf(ctx->p, "%02d%02d%02d%02d%02d%02d%02d",
1917                             (tm.tm_year / 100) + 19, (tm.tm_year % 100),
1918                             tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min,
1919                             tm.tm_sec);
1920     case 8:
1921         return ap_get_server_banner();
1922     case 9:
1923         return apr_itoa(ctx->p, MODULE_MAGIC_NUMBER_MAJOR);
1924     default:
1925         ap_assert(0);
1926     }
1927
1928     return NULL;
1929 }
1930
1931 static int subnet_parse_arg(ap_expr_lookup_parms *parms)
1932 {
1933     apr_ipsubnet_t *subnet;
1934     const char *addr = parms->arg;
1935     const char *mask;
1936     apr_status_t ret;
1937
1938     if (!parms->arg) {
1939         *parms->err = apr_psprintf(parms->ptemp,
1940                                    "-%s requires subnet/netmask as constant argument",
1941                                    parms->name);
1942         return !OK;
1943     }
1944
1945     mask = ap_strchr_c(addr, '/');
1946     if (mask) {
1947         addr = apr_pstrmemdup(parms->ptemp, addr, mask - addr);
1948         mask++;
1949     }
1950
1951     ret = apr_ipsubnet_create(&subnet, addr, mask, parms->pool);
1952     if (ret != APR_SUCCESS) {
1953         *parms->err = "parsing of subnet/netmask failed";
1954         return !OK;
1955     }
1956
1957     *parms->data = subnet;
1958     return OK;
1959 }
1960
1961 static int op_ipmatch(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg1,
1962                 const char *arg2)
1963 {
1964     apr_ipsubnet_t *subnet = (apr_ipsubnet_t *)data;
1965     apr_sockaddr_t *saddr;
1966
1967     AP_DEBUG_ASSERT(subnet != NULL);
1968
1969     /* maybe log an error if this goes wrong? */
1970     if (apr_sockaddr_info_get(&saddr, arg1, APR_UNSPEC, 0, 0, ctx->p) != APR_SUCCESS)
1971         return FALSE;
1972
1973     return apr_ipsubnet_test(subnet, saddr);
1974 }
1975
1976 static int op_R(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg1)
1977 {
1978     apr_ipsubnet_t *subnet = (apr_ipsubnet_t *)data;
1979
1980     AP_DEBUG_ASSERT(subnet != NULL);
1981
1982     if (!ctx->r)
1983         return FALSE;
1984
1985     return apr_ipsubnet_test(subnet, ctx->r->useragent_addr);
1986 }
1987
1988 static int op_T(ap_expr_eval_ctx_t *ctx, const void *data, const char *arg)
1989 {
1990     switch (arg[0]) {
1991     case '\0':
1992         return FALSE;
1993     case 'o':
1994     case 'O':
1995         return strcasecmp(arg, "off") == 0 ? FALSE : TRUE;
1996     case 'n':
1997     case 'N':
1998         return strcasecmp(arg, "no") == 0 ? FALSE : TRUE;
1999     case 'f':
2000     case 'F':
2001         return strcasecmp(arg, "false") == 0 ? FALSE : TRUE;
2002     case '0':
2003         return arg[1] == '\0' ? FALSE : TRUE;
2004     default:
2005         return TRUE;
2006     }
2007 }
2008
2009 static int op_fnmatch(ap_expr_eval_ctx_t *ctx, const void *data,
2010                       const char *arg1, const char *arg2)
2011 {
2012     return (APR_SUCCESS == apr_fnmatch(arg2, arg1, APR_FNM_PATHNAME));
2013 }
2014
2015 static int op_strmatch(ap_expr_eval_ctx_t *ctx, const void *data,
2016                        const char *arg1, const char *arg2)
2017 {
2018     return (APR_SUCCESS == apr_fnmatch(arg2, arg1, 0));
2019 }
2020
2021 static int op_strcmatch(ap_expr_eval_ctx_t *ctx, const void *data,
2022                         const char *arg1, const char *arg2)
2023 {
2024     return (APR_SUCCESS == apr_fnmatch(arg2, arg1, APR_FNM_CASE_BLIND));
2025 }
2026
2027 struct expr_provider_single {
2028     const void *func;
2029     const char *name;
2030     ap_expr_lookup_fn_t *arg_parsing_func;
2031     int restricted;
2032 };
2033
2034 struct expr_provider_multi {
2035     const void *func;
2036     const char **names;
2037 };
2038
2039 static const struct expr_provider_multi var_providers[] = {
2040     { misc_var_fn, misc_var_names },
2041     { req_header_var_fn, req_header_var_names },
2042     { request_var_fn, request_var_names },
2043     { conn_var_fn, conn_var_names },
2044     { NULL, NULL }
2045 };
2046
2047 static const struct expr_provider_single string_func_providers[] = {
2048     { osenv_func,           "osenv",          NULL, 0 },
2049     { env_func,             "env",            NULL, 0 },
2050     { req_table_func,       "resp",           NULL, 0 },
2051     { req_table_func,       "req",            NULL, 0 },
2052     /* 'http' as alias for 'req' for compatibility with ssl_expr */
2053     { req_table_func,       "http",           NULL, 0 },
2054     { req_table_func,       "note",           NULL, 0 },
2055     { req_table_func,       "reqenv",         NULL, 0 },
2056     { req_table_func,       "req_novary",     NULL, 0 },
2057     { tolower_func,         "tolower",        NULL, 0 },
2058     { toupper_func,         "toupper",        NULL, 0 },
2059     { escape_func,          "escape",         NULL, 0 },
2060     { unescape_func,        "unescape",       NULL, 0 },
2061     { file_func,            "file",           NULL, 1 },
2062     { filesize_func,        "filesize",       NULL, 1 },
2063     { filemod_func,         "filemod",        NULL, 1 },
2064     { base64_func,          "base64",         NULL, 0 },
2065     { unbase64_func,        "unbase64",       NULL, 0 },
2066     { sha1_func,            "sha1",           NULL, 0 },
2067     { md5_func,             "md5",            NULL, 0 },
2068 #if APR_VERSION_AT_LEAST(1,6,0)
2069     { ldap_func,            "ldap",           NULL, 0 },
2070 #endif
2071     { replace_func,         "replace",        replace_func_parse_arg, 0 },
2072     { NULL, NULL, NULL}
2073 };
2074
2075 static const struct expr_provider_single unary_op_providers[] = {
2076     { op_nz,        "n", NULL,             0 },
2077     { op_nz,        "z", NULL,             0 },
2078     { op_R,         "R", subnet_parse_arg, 0 },
2079     { op_T,         "T", NULL,             0 },
2080     { op_file_min,  "d", NULL,             1 },
2081     { op_file_min,  "e", NULL,             1 },
2082     { op_file_min,  "f", NULL,             1 },
2083     { op_file_min,  "s", NULL,             1 },
2084     { op_file_link, "L", NULL,             1 },
2085     { op_file_link, "h", NULL,             1 },
2086     { op_file_xbit, "x", NULL,             1 },
2087     { op_file_subr, "F", NULL,             0 },
2088     { op_url_subr,  "U", NULL,             0 },
2089     { op_url_subr,  "A", NULL,             0 },
2090     { NULL, NULL, NULL }
2091 };
2092
2093 static const struct expr_provider_single binary_op_providers[] = {
2094     { op_ipmatch,   "ipmatch",      subnet_parse_arg, 0 },
2095     { op_fnmatch,   "fnmatch",      NULL,             0 },
2096     { op_strmatch,  "strmatch",     NULL,             0 },
2097     { op_strcmatch, "strcmatch",    NULL,             0 },
2098     { NULL, NULL, NULL }
2099 };
2100
2101 static int core_expr_lookup(ap_expr_lookup_parms *parms)
2102 {
2103     switch (parms->type) {
2104     case AP_EXPR_FUNC_VAR: {
2105             const struct expr_provider_multi *prov = var_providers;
2106             while (prov->func) {
2107                 const char **name = prov->names;
2108                 while (*name) {
2109                     if (ap_cstr_casecmp(*name, parms->name) == 0) {
2110                         *parms->func = prov->func;
2111                         *parms->data = name;
2112                         return OK;
2113                     }
2114                     name++;
2115                 }
2116                 prov++;
2117             }
2118         }
2119         break;
2120     case AP_EXPR_FUNC_STRING:
2121     case AP_EXPR_FUNC_OP_UNARY:
2122     case AP_EXPR_FUNC_OP_BINARY: {
2123             const struct expr_provider_single *prov;
2124             switch (parms->type) {
2125             case AP_EXPR_FUNC_STRING:
2126                 prov = string_func_providers;
2127                 break;
2128             case AP_EXPR_FUNC_OP_UNARY:
2129                 prov = unary_op_providers;
2130                 break;
2131             case AP_EXPR_FUNC_OP_BINARY:
2132                 prov = binary_op_providers;
2133                 break;
2134             default:
2135                 ap_assert(0);
2136             }
2137             while (prov->func) {
2138                 int match;
2139                 if (parms->type == AP_EXPR_FUNC_OP_UNARY)
2140                     match = !strcmp(prov->name, parms->name);
2141                 else
2142                     match = !ap_cstr_casecmp(prov->name, parms->name);
2143                 if (match) {
2144                     if ((parms->flags & AP_EXPR_FLAG_RESTRICTED)
2145                         && prov->restricted) {
2146                         *parms->err =
2147                             apr_psprintf(parms->ptemp,
2148                                          "%s%s not available in restricted context",
2149                                          (parms->type == AP_EXPR_FUNC_STRING) ? "" : "-",
2150                                          prov->name);
2151                         return !OK;
2152                     }
2153                     *parms->func = prov->func;
2154                     if (prov->arg_parsing_func) {
2155                         return prov->arg_parsing_func(parms);
2156                     }
2157                     else {
2158                         *parms->data = prov->name;
2159                         return OK;
2160                     }
2161                 }
2162                 prov++;
2163             }
2164         }
2165         break;
2166     default:
2167         break;
2168     }
2169     return DECLINED;
2170 }
2171
2172 static int expr_lookup_not_found(ap_expr_lookup_parms *parms)
2173 {
2174     const char *type;
2175     const char *prefix = "";
2176
2177     switch (parms->type) {
2178     case AP_EXPR_FUNC_VAR:
2179         type = "Variable";
2180         break;
2181     case AP_EXPR_FUNC_STRING:
2182         type = "Function";
2183         break;
2184     case AP_EXPR_FUNC_LIST:
2185         type = "List-returning function";
2186         break;
2187     case AP_EXPR_FUNC_OP_UNARY:
2188         type = "Unary operator";
2189         break;
2190     case AP_EXPR_FUNC_OP_BINARY:
2191         type = "Binary operator";
2192         break;
2193     default:
2194         *parms->err = "Inavalid expression type in expr_lookup";
2195         return !OK;
2196     }
2197     if (   parms->type == AP_EXPR_FUNC_OP_UNARY
2198         || parms->type == AP_EXPR_FUNC_OP_BINARY) {
2199         prefix = "-";
2200     }
2201     *parms->err = apr_psprintf(parms->ptemp, "%s '%s%s' does not exist", type,
2202                                prefix, parms->name);
2203     return !OK;
2204 }
2205
2206 static int ap_expr_post_config(apr_pool_t *pconf, apr_pool_t *plog,
2207                                apr_pool_t *ptemp, server_rec *s)
2208 {
2209     is_https = APR_RETRIEVE_OPTIONAL_FN(ssl_is_https);
2210     is_http2 = APR_RETRIEVE_OPTIONAL_FN(http2_is_h2);
2211     apr_pool_cleanup_register(pconf, &is_https, ap_pool_cleanup_set_null,
2212                               apr_pool_cleanup_null);
2213     return OK;
2214 }
2215
2216 void ap_expr_init(apr_pool_t *p)
2217 {
2218     ap_hook_expr_lookup(core_expr_lookup, NULL, NULL, APR_HOOK_MIDDLE);
2219     ap_hook_expr_lookup(expr_lookup_not_found, NULL, NULL, APR_HOOK_REALLY_LAST);
2220     ap_hook_post_config(ap_expr_post_config, NULL, NULL, APR_HOOK_MIDDLE);
2221 }
2222