]> granicus.if.org Git - apache/blob - server/util_expr_eval.c
2b80e73efb9de0a06ce074f3ae1523064319a48a
[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 "ap_provider.h"
26 #include "util_expr_private.h"
27
28 #include "apr_lib.h"
29
30 APLOG_USE_MODULE(core);
31
32 APR_HOOK_STRUCT(
33     APR_HOOK_LINK(expr_lookup)
34 )
35
36 AP_IMPLEMENT_HOOK_RUN_FIRST(int, expr_lookup, (ap_expr_lookup_parms *parms),
37                             (parms), DECLINED)
38
39 static const char *ap_expr_eval_string_func(ap_expr_eval_ctx *ctx, const ap_expr *info,
40                                             const ap_expr *args);
41 static const char *ap_expr_eval_var(ap_expr_eval_ctx *ctx,
42                                     const ap_expr_var_func_t *func,
43                                     const void *data);
44 static void expr_dump_tree(const ap_expr *e, const server_rec *s, int loglevel, int indent);
45
46 static const char *ap_expr_eval_word(ap_expr_eval_ctx *ctx, const ap_expr *node)
47 {
48     const char *result = "";
49     switch (node->node_op) {
50         case op_Digit:
51             result = node->node_arg1;
52             break;
53         case op_String:
54             result = node->node_arg1;
55             break;
56         case op_Var:
57             result = ap_expr_eval_var(ctx, node->node_arg1, node->node_arg2);
58             break;
59         case op_StringFuncCall: {
60             const ap_expr *info = node->node_arg1;
61             const ap_expr *args = node->node_arg2;
62             result = ap_expr_eval_string_func(ctx, info, args);
63             break;
64         }
65         default:
66             *ctx->err = "Internal evaluation error: Unknown expression node";
67             break;
68     }
69     if (!result)
70         result = "";
71     return result;
72 }
73
74 static const char *ap_expr_eval_var(ap_expr_eval_ctx *ctx, 
75                                     const ap_expr_var_func_t *func,
76                                     const void *data)
77 {
78     AP_DEBUG_ASSERT(func != NULL);
79     AP_DEBUG_ASSERT(data != NULL);
80     return (*func)(ctx, data);
81 }
82
83 static const char *ap_expr_eval_string_func(ap_expr_eval_ctx *ctx, const ap_expr *info,
84                                             const ap_expr *arg)
85 {
86     ap_expr_string_func_t *func = (ap_expr_string_func_t *)info->node_arg1;
87     const void *data = info->node_arg2;
88
89     AP_DEBUG_ASSERT(info->node_op == op_StringFuncInfo);
90     AP_DEBUG_ASSERT(func != NULL);
91     AP_DEBUG_ASSERT(data != NULL);
92     return (*func)(ctx, data, ap_expr_eval_word(ctx, arg));
93 }
94
95 static int intstrcmp(const char *s1, const char *s2)
96 {
97     apr_int64_t i1 = apr_atoi64(s1);
98     apr_int64_t i2 = apr_atoi64(s2);
99
100     if (i1 < i2)
101         return -1;
102     else if (i1 == i2)
103         return 0;
104     else
105         return 1;
106 }
107
108 static int ap_expr_eval_comp(ap_expr_eval_ctx *ctx, const ap_expr *node)
109 {
110     switch (node->node_op) {
111         case op_EQ: {
112             const ap_expr *e1 = node->node_arg1;
113             const ap_expr *e2 = node->node_arg2;
114             return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) == 0);
115         }
116         case op_NE: {
117             const ap_expr *e1 = node->node_arg1;
118             const ap_expr *e2 = node->node_arg2;
119             return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) != 0);
120         }
121         case op_LT: {
122             const ap_expr *e1 = node->node_arg1;
123             const ap_expr *e2 = node->node_arg2;
124             return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <  0);
125         }
126         case op_LE: {
127             const ap_expr *e1 = node->node_arg1;
128             const ap_expr *e2 = node->node_arg2;
129             return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <= 0);
130         }
131         case op_GT: {
132             const ap_expr *e1 = node->node_arg1;
133             const ap_expr *e2 = node->node_arg2;
134             return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >  0);
135         }
136         case op_GE: {
137             const ap_expr *e1 = node->node_arg1;
138             const ap_expr *e2 = node->node_arg2;
139             return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >= 0);
140         }
141         case op_STR_EQ: {
142             const ap_expr *e1 = node->node_arg1;
143             const ap_expr *e2 = node->node_arg2;
144             return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) == 0);
145         }
146         case op_STR_NE: {
147             const ap_expr *e1 = node->node_arg1;
148             const ap_expr *e2 = node->node_arg2;
149             return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) != 0);
150         }
151         case op_STR_LT: {
152             const ap_expr *e1 = node->node_arg1;
153             const ap_expr *e2 = node->node_arg2;
154             return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <  0);
155         }
156         case op_STR_LE: {
157             const ap_expr *e1 = node->node_arg1;
158             const ap_expr *e2 = node->node_arg2;
159             return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <= 0);
160         }
161         case op_STR_GT: {
162             const ap_expr *e1 = node->node_arg1;
163             const ap_expr *e2 = node->node_arg2;
164             return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >  0);
165         }
166         case op_STR_GE: {
167             const ap_expr *e1 = node->node_arg1;
168             const ap_expr *e2 = node->node_arg2;
169             return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >= 0);
170         }
171         case op_IN: {
172             const ap_expr *e1 = node->node_arg1;
173             const ap_expr *e2 = node->node_arg2;
174             const char *needle = ap_expr_eval_word(ctx, e1);
175             if (e2->node_op == op_ListElement) {
176                 do {
177                     const ap_expr *val = e2->node_arg1;
178                     AP_DEBUG_ASSERT(e2->node_op == op_ListElement);
179                     if (strcmp(needle, ap_expr_eval_word(ctx, val)) == 0) {
180                         return 1;
181                         break;
182                     }
183                     e2 = e2->node_arg2;
184                 } while (e2 != NULL);
185             }
186             else if (e2->node_op == op_ListFuncCall) {
187                 const ap_expr *info = e2->node_arg1;
188                 const ap_expr *arg = e2->node_arg2;
189                 ap_expr_list_func_t *func = (ap_expr_list_func_t *)info->node_arg1;
190                 apr_array_header_t *haystack;
191                 int i = 0;
192                 AP_DEBUG_ASSERT(func != NULL);
193                 AP_DEBUG_ASSERT(info->node_op == op_ListFuncInfo);
194                 haystack = (*func)(ctx, info->node_arg2, ap_expr_eval_word(ctx, arg));
195                 if (haystack == NULL)
196                     return 0;
197                 for (; i < haystack->nelts; i++) {
198                     if (strcmp(needle, APR_ARRAY_IDX(haystack,i,char *)) == 0)
199                         return 1;
200                 }
201             }
202             return 0;
203         }
204         case op_REG: {
205             const ap_expr *e1;
206             const ap_expr *e2;
207             const char *word;
208             const ap_regex_t *regex;
209
210             e1 = node->node_arg1;
211             e2 = node->node_arg2;
212             word = ap_expr_eval_word(ctx, e1);
213             regex = e2->node_arg1;
214             return (ap_regexec(regex, word, 0, NULL, 0) == 0);
215         }
216         case op_NRE: {
217             const ap_expr *e1;
218             const ap_expr *e2;
219             const char *word;
220             const ap_regex_t *regex;
221
222             e1 = node->node_arg1;
223             e2 = node->node_arg2;
224             word = ap_expr_eval_word(ctx, e1);
225             regex = e2->node_arg1;
226             return !(ap_regexec(regex, word, 0, NULL, 0) == 0);
227         }
228         default: {
229             *ctx->err = "Internal evaluation error: Unknown expression node";
230             return -1;
231         }
232     }
233 }
234
235 /* combined string/int comparison for compatibility with ssl_expr */
236 static int strcmplex(const char *str1, const char *str2)
237 {
238     int i, n1, n2;
239
240     if (str1 == NULL)
241         return -1;
242     if (str2 == NULL)
243         return +1;
244     n1 = strlen(str1);
245     n2 = strlen(str2);
246     if (n1 > n2)
247         return 1;
248     if (n1 < n2)
249         return -1;
250     for (i = 0; i < n1; i++) {
251         if (str1[i] > str2[i])
252             return 1;
253         if (str1[i] < str2[i])
254             return -1;
255     }
256     return 0;
257 }
258
259 static int ssl_expr_eval_comp(ap_expr_eval_ctx *ctx, const ap_expr *node)
260 {
261     const ap_expr *e1 = node->node_arg1;
262     const ap_expr *e2 = node->node_arg2;
263     switch (node->node_op) {
264     case op_EQ:
265     case op_STR_EQ:
266         return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) == 0);
267     case op_NE:
268     case op_STR_NE:
269         return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) != 0);
270     case op_LT:
271     case op_STR_LT:
272         return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <  0);
273     case op_LE:
274     case op_STR_LE:
275         return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <= 0);
276     case op_GT:
277     case op_STR_GT:
278         return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >  0);
279     case op_GE:
280     case op_STR_GE:
281         return (strcmplex(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >= 0);
282     default:
283         return ap_expr_eval_comp(ctx, node);
284     }
285 }
286
287
288 AP_DECLARE(const char *) ap_expr_parse(apr_pool_t *pool, apr_pool_t *ptemp,
289                                        ap_expr_info_t *info, const char *expr,
290                                        ap_expr_lookup_fn *lookup_fn)
291 {
292     ap_expr_parse_ctx ctx;
293     int rc;
294
295     ctx.pool     = pool;
296     ctx.ptemp    = ptemp;
297     ctx.inputbuf = expr;
298     ctx.inputlen = strlen(expr);
299     ctx.inputptr = ctx.inputbuf;
300     ctx.expr     = NULL;
301     ctx.error    = NULL;        /* generic bison error message (usually not very useful) */
302     ctx.error2   = NULL;        /* additional error message */
303     ctx.flags    = info->flags;
304     ctx.scan_del    = '\0';
305     ctx.scan_buf[0] = '\0';
306     ctx.scan_ptr    = ctx.scan_buf;
307     ctx.lookup_fn   = lookup_fn ? lookup_fn : ap_run_expr_lookup;
308
309     ap_expr_yylex_init(&ctx.scanner);
310     ap_expr_yyset_extra(&ctx, ctx.scanner);
311     rc = ap_expr_yyparse(&ctx);
312     ap_expr_yylex_destroy(ctx.scanner);
313     if (ctx.error) {
314         if (ctx.error2)
315             return apr_psprintf(pool, "%s: %s", ctx.error, ctx.error2);
316         else
317             return ctx.error;
318     }
319     else if (ctx.error2) {
320         return ctx.error2;
321     }
322
323     if (rc) /* XXX can this happen? */
324         return "syntax error";
325
326     /* XXX Make this properly depend on the loglevel, which requires
327      * XXX having a server_rec
328      */
329     /*
330     if (ctx.expr)
331         expr_dump_tree(ctx.expr, NULL, APLOG_NOTICE, 2);
332     */
333
334     info->root_node = ctx.expr;
335
336     return NULL;
337 }
338
339 AP_DECLARE(ap_expr_info_t*) ap_expr_parse_cmd(const cmd_parms *cmd,
340                                               const char *expr,
341                                               const char **err,
342                                               ap_expr_lookup_fn *lookup_fn)
343 {
344     ap_expr_info_t *info = apr_pcalloc(cmd->pool, sizeof(ap_expr_info_t));
345     info->filename = cmd->directive->filename;
346     info->line_number = cmd->directive->line_num;
347     *err = ap_expr_parse(cmd->pool, cmd->temp_pool, info, expr, lookup_fn);
348
349     if (*err)
350         return NULL;
351
352     return info;
353 }
354
355 ap_expr *ap_expr_make(ap_expr_node_op op, const void *a1, const void *a2,
356                       ap_expr_parse_ctx *ctx)
357 {
358     ap_expr *node = apr_palloc(ctx->pool, sizeof(ap_expr));
359     node->node_op   = op;
360     node->node_arg1 = a1;
361     node->node_arg2 = a2;
362     return node;
363 }
364
365
366 static ap_expr *ap_expr_info_make(int type, const char *name, ap_expr_parse_ctx *ctx)
367 {
368     ap_expr *info = apr_palloc(ctx->pool, sizeof(ap_expr));
369     ap_expr_lookup_parms parms;
370     parms.type  = type;
371     parms.flags = 0;
372     parms.pool  = ctx->pool;
373     parms.ptemp = ctx->ptemp;
374     parms.name  = name;
375     parms.func  = &info->node_arg1;
376     parms.data  = &info->node_arg2;
377     parms.err   = &ctx->error2;
378     if (ctx->lookup_fn(&parms) != OK)
379         return NULL;
380     return info;
381 }
382
383 ap_expr *ap_expr_str_func_make(const char *name, const ap_expr *arg,
384                                ap_expr_parse_ctx *ctx)
385 {
386     ap_expr *info = ap_expr_info_make(AP_EXPR_FUNC_STRING, name, ctx);
387     if (!info)
388         return NULL;
389
390     info->node_op = op_StringFuncInfo;
391     return ap_expr_make(op_StringFuncCall, info, arg, ctx);
392 }
393
394 ap_expr *ap_expr_list_func_make(const char *name, const ap_expr *arg,
395                                 ap_expr_parse_ctx *ctx)
396 {
397     ap_expr *info = ap_expr_info_make(AP_EXPR_FUNC_LIST, name, ctx);
398     if (!info)
399         return NULL;
400
401     info->node_op = op_ListFuncInfo;
402     return ap_expr_make(op_ListFuncCall, info, arg, ctx);
403 }
404
405 ap_expr *ap_expr_unary_op_make(const char *name, const ap_expr *arg,
406                                ap_expr_parse_ctx *ctx)
407 {
408     ap_expr *info = ap_expr_info_make(AP_EXPR_FUNC_OP_UNARY, name, ctx);
409     if (!info)
410         return NULL;
411
412     info->node_op = op_UnaryOpInfo;
413     return ap_expr_make(op_UnaryOpCall, info, arg, ctx);
414 }
415
416 ap_expr *ap_expr_binary_op_make(const char *name, const ap_expr *arg1,
417                                 const ap_expr *arg2, ap_expr_parse_ctx *ctx)
418 {
419     ap_expr *args;
420     ap_expr *info = ap_expr_info_make(AP_EXPR_FUNC_OP_UNARY, name, ctx);
421     if (!info)
422         return NULL;
423
424     info->node_op = op_BinaryOpInfo;
425     args = ap_expr_make(op_BinaryOpArgs, arg1, arg2, ctx);
426     return ap_expr_make(op_BinaryOpCall, info, args, ctx);
427 }
428
429
430 ap_expr *ap_expr_var_make(const char *name, ap_expr_parse_ctx *ctx)
431 {
432     ap_expr *node = ap_expr_info_make(AP_EXPR_FUNC_VAR, name, ctx);
433     if (!node)
434         return NULL;
435
436     node->node_op = op_Var;
437     return node;
438 }
439
440
441 #define MARK                        APLOG_MARK,loglevel,0,s
442 #define DUMP_E_E(op, e1, e2)                                                \
443     do { ap_log_error(MARK,"%*s%s: %pp %pp", indent, " ", op, e1, e2);      \
444          if (e1) expr_dump_tree(e1, s, loglevel, indent + 2);               \
445          if (e2) expr_dump_tree(e2, s, loglevel, indent + 2);               \
446     } while (0)
447 #define DUMP_S_E(op, s1, e1)                                                    \
448     do { ap_log_error(MARK,"%*s%s: '%s' %pp", indent, " ", op, (char *)s1, e1); \
449          if (e1) expr_dump_tree(e1, s, loglevel, indent + 2);                   \
450     } while (0)
451 #define DUMP_S_P(op, s1, p1)                                                \
452     ap_log_error(MARK,"%*s%s: '%s' %pp", indent, " ", op, (char *)s1, p1);
453 #define DUMP_P_P(op, p1, p2)                                                \
454     ap_log_error(MARK,"%*s%s: %pp %pp", indent, " ", op, p1, p2);
455 #define DUMP_S_S(op, s1, s2)                                                       \
456     ap_log_error(MARK,"%*s%s: '%s' '%s'", indent, " ", op, (char *)s1, (char *)s2)
457 #define DUMP_P(op, p1)                                                      \
458     ap_log_error(MARK,"%*s%s: %pp", indent, " ", op, p1);
459 #define DUMP_S(op, s1)                                                      \
460     ap_log_error(MARK,"%*s%s: '%s'", indent, " ", op, (char *)s1)
461
462 #define CASE_OP(op)                  case op: name = #op ; break;
463
464 static void expr_dump_tree(const ap_expr *e, const server_rec *s, int loglevel, int indent)
465 {
466     switch (e->node_op) {
467     /* no arg */
468     case op_NOP:
469     case op_True:
470     case op_False:
471         {
472             char *name;
473             switch (e->node_op) {
474             CASE_OP(op_NOP);
475             CASE_OP(op_True);
476             CASE_OP(op_False);
477             default:
478                 ap_assert(0);
479             }
480             ap_log_error(MARK, "%*s%s", indent, " ", name);
481         }
482         break;
483
484     /* arg1: string, arg2: expr */
485     case op_UnaryOpCall:
486     case op_BinaryOpCall:
487     case op_BinaryOpArgs:
488         {
489             char *name;
490             switch (e->node_op) {
491             CASE_OP(op_BinaryOpCall);
492             CASE_OP(op_UnaryOpCall);
493             CASE_OP(op_BinaryOpArgs);
494             default:
495                 ap_assert(0);
496             }
497             DUMP_S_E(name, e->node_arg1, e->node_arg2);
498         }
499         break;
500
501     /* arg1: expr, arg2: expr */
502     case op_Comp:
503     case op_Not:
504     case op_Or:
505     case op_And:
506     case op_EQ:
507     case op_NE:
508     case op_LT:
509     case op_LE:
510     case op_GT:
511     case op_GE:
512     case op_STR_EQ:
513     case op_STR_NE:
514     case op_STR_LT:
515     case op_STR_LE:
516     case op_STR_GT:
517     case op_STR_GE:
518     case op_IN:
519     case op_REG:
520     case op_NRE:
521     case op_Concat:
522     case op_StringFuncCall:
523     case op_ListFuncCall:
524     case op_ListElement:
525         {
526             char *name;
527             switch (e->node_op) {
528             CASE_OP(op_Comp);
529             CASE_OP(op_Not);
530             CASE_OP(op_Or);
531             CASE_OP(op_And);
532             CASE_OP(op_EQ);
533             CASE_OP(op_NE);
534             CASE_OP(op_LT);
535             CASE_OP(op_LE);
536             CASE_OP(op_GT);
537             CASE_OP(op_GE);
538             CASE_OP(op_STR_EQ);
539             CASE_OP(op_STR_NE);
540             CASE_OP(op_STR_LT);
541             CASE_OP(op_STR_LE);
542             CASE_OP(op_STR_GT);
543             CASE_OP(op_STR_GE);
544             CASE_OP(op_IN);
545             CASE_OP(op_REG);
546             CASE_OP(op_NRE);
547             CASE_OP(op_Concat);
548             CASE_OP(op_StringFuncCall);
549             CASE_OP(op_ListFuncCall);
550             CASE_OP(op_ListElement);
551             default:
552                 ap_assert(0);
553             }
554             DUMP_E_E(name, e->node_arg1, e->node_arg2);
555         }
556         break;
557     /* arg1: string */
558     case op_Digit:
559     case op_String:
560         {
561             char *name;
562             switch (e->node_op) {
563             CASE_OP(op_Digit);
564             CASE_OP(op_String);
565             default:
566                 ap_assert(0);
567             }
568             DUMP_S(name, e->node_arg1);
569         }
570         break;
571     /* arg1: pointer, arg2: pointer */
572     case op_Var:
573     case op_StringFuncInfo:
574     case op_UnaryOpInfo:
575     case op_BinaryOpInfo:
576     case op_ListFuncInfo:
577         {
578             char *name;
579             switch (e->node_op) {
580             CASE_OP(op_Var);
581             CASE_OP(op_StringFuncInfo);
582             CASE_OP(op_UnaryOpInfo);
583             CASE_OP(op_BinaryOpInfo);
584             CASE_OP(op_ListFuncInfo);
585             default:
586                 ap_assert(0);
587             }
588             DUMP_P_P(name, e->node_arg1, e->node_arg2);
589         }
590         break;
591     /* arg1: pointer */
592     case op_Regex:
593         DUMP_P("op_Regex", e->node_arg1);
594         break;
595     default:
596         ap_log_error(MARK, "%*sERROR: INVALID OP %d", indent, " ", e->node_op);
597         break;
598     }
599 }
600 static int ap_expr_eval_unary_op(ap_expr_eval_ctx *ctx, const ap_expr *info,
601                                  const ap_expr *arg)
602 {
603     const ap_expr_op_unary_t *op_func = info->node_arg1;
604     const void *data = info->node_arg2;
605
606     AP_DEBUG_ASSERT(info->node_op == op_UnaryOpInfo);
607     AP_DEBUG_ASSERT(op_func != NULL);
608     AP_DEBUG_ASSERT(data != NULL);
609     return (*op_func)(ctx, data, ap_expr_eval_word(ctx, arg));
610 }
611
612 static int ap_expr_eval_binary_op(ap_expr_eval_ctx *ctx, const ap_expr *info,
613                                   const ap_expr *args)
614 {
615     const ap_expr_op_binary_t *op_func = info->node_arg1;
616     const void *data = info->node_arg2;
617     const ap_expr *a1 = args->node_arg1;
618     const ap_expr *a2 = args->node_arg2;
619
620     AP_DEBUG_ASSERT(info->node_op == op_BinaryOpInfo);
621     AP_DEBUG_ASSERT(args->node_op == op_BinaryOpArgs);
622     AP_DEBUG_ASSERT(op_func != NULL);
623     AP_DEBUG_ASSERT(data != NULL);
624     return (*op_func)(ctx, data, ap_expr_eval_word(ctx, a1),
625                       ap_expr_eval_word(ctx, a2));
626 }
627
628
629 static int ap_expr_eval(ap_expr_eval_ctx *ctx, const ap_expr *node)
630 {
631     switch (node->node_op) {
632         case op_True: {
633             return 1;
634         }
635         case op_False: {
636             return 0;
637         }
638         case op_Not: {
639             const ap_expr *e = node->node_arg1;
640             return (!ap_expr_eval(ctx, e));
641         }
642         case op_Or: {
643             const ap_expr *e1 = node->node_arg1;
644             const ap_expr *e2 = node->node_arg2;
645             return (ap_expr_eval(ctx, e1) || ap_expr_eval(ctx, e2));
646         }
647         case op_And: {
648             const ap_expr *e1 = node->node_arg1;
649             const ap_expr *e2 = node->node_arg2;
650             return (ap_expr_eval(ctx, e1) && ap_expr_eval(ctx, e2));
651         }
652         case op_UnaryOpCall: {
653             const ap_expr *info = node->node_arg1;
654             const ap_expr *args = node->node_arg2;
655             return ap_expr_eval_unary_op(ctx, info, args);
656         }
657         case op_BinaryOpCall: {
658             const ap_expr *info = node->node_arg1;
659             const ap_expr *args = node->node_arg2;
660             return ap_expr_eval_binary_op(ctx, info, args);
661         }
662         case op_Comp: {
663             const ap_expr *e = node->node_arg1;
664             if (ctx->info->flags & AP_EXPR_FLAGS_SSL_EXPR_COMPAT)
665                 return ssl_expr_eval_comp(ctx, e);
666             else
667                 return ap_expr_eval_comp(ctx, e);
668         }
669         default: {
670             *ctx->err = "Internal evaluation error: Unknown expression node";
671             return FALSE;
672         }
673     }
674 }
675
676
677 AP_DECLARE(int) ap_expr_exec(request_rec *r, const ap_expr_info_t *info, const char **err)
678 {
679     ap_expr_eval_ctx ctx;
680     int rc;
681     ctx.r = r;
682     ctx.c = r->connection;
683     ctx.s = r->server;
684     ctx.p = r->pool;
685     ctx.err  = err;
686     ctx.info = info;
687
688     *err = NULL;
689     rc = ap_expr_eval(&ctx, info->root_node);
690     if (*err != NULL)
691         return (-1);
692     else
693         return (rc ? 1 : 0);
694 }
695
696 static const char *req_table_func(ap_expr_eval_ctx *ctx, const void *data,
697                                   const char *arg)
698 {
699     const char *name = (const char *)data;
700     apr_table_t *t;
701     if (!ctx->r)
702         return "";
703
704     if (name[3] == 's')             /* resp */
705         t = ctx->r->headers_out;
706     else if (name[4] == 'e')        /* reqenv */
707         t = ctx->r->subprocess_env;
708     else if (name[0] == 'n')        /* notes */
709         t = ctx->r->notes;
710     else
711         t = ctx->r->headers_in;
712     return apr_table_get(t, arg);
713 }
714
715 static const char *env_func(ap_expr_eval_ctx *ctx, const void *data,
716                             const char *arg)
717 {
718     const char *res;
719     /* this order is for ssl_expr compatibility */
720     if (ctx->r) {
721         if ((res = apr_table_get(ctx->r->notes, arg)) != NULL)
722             return res;
723         else if ((res = apr_table_get(ctx->r->subprocess_env, arg)) != NULL)
724             return res;
725     }
726     return getenv(arg);
727 }
728
729 static const char *osenv_func(ap_expr_eval_ctx *ctx, const void *data,
730                               const char *arg)
731 {
732     return getenv(arg);
733 }
734
735 static const char *tolower_func(ap_expr_eval_ctx *ctx, const void *data,
736                                 const char *arg)
737 {
738     char *result = apr_pstrdup(ctx->p, arg);
739     ap_str_tolower(result);
740     return result;
741 }
742
743 static const char *toupper_func(ap_expr_eval_ctx *ctx, const void *data,
744                                 const char *arg)
745 {
746     char *p;
747     char *result = apr_pstrdup(ctx->p, arg);
748
749     for (p = result; *p; ++p) {
750          *p = apr_toupper(*p);
751     }
752
753     return result;
754 }
755
756 static const char *escape_func(ap_expr_eval_ctx *ctx, const void *data,
757                                const char *arg)
758 {
759     return ap_escape_uri(ctx->p, arg);
760 }
761
762 #define MAX_FILE_SIZE 10*1024*1024
763 static const char *file_func(ap_expr_eval_ctx *ctx, const void *data, char *arg)
764 {
765     apr_file_t *fp;
766     char *buf;
767     apr_off_t offset;
768     apr_size_t len;
769     apr_finfo_t finfo;
770
771     if (apr_file_open(&fp, arg, APR_READ|APR_BUFFERED,
772                       APR_OS_DEFAULT, ctx->p) != APR_SUCCESS) {
773         *ctx->err = apr_psprintf(ctx->p, "Cannot open file %s", arg);
774         return "";
775     }
776     apr_file_info_get(&finfo, APR_FINFO_SIZE, fp);
777     if (finfo.size > MAX_FILE_SIZE) {
778         *ctx->err = apr_psprintf(ctx->p, "File %s too large", arg);
779         apr_file_close(fp);
780         return "";
781     }
782     len = (apr_size_t)finfo.size;
783     if (len == 0) {
784         apr_file_close(fp);
785         return "";
786     }
787     else {
788         if ((buf = (char *)apr_palloc(ctx->p, sizeof(char)*(len+1))) == NULL) {
789             *ctx->err = "Cannot allocate memory";
790             apr_file_close(fp);
791             return "";
792         }
793         offset = 0;
794         apr_file_seek(fp, APR_SET, &offset);
795         if (apr_file_read(fp, buf, &len) != APR_SUCCESS) {
796             *ctx->err = apr_psprintf(ctx->p, "Cannot read from file %s", arg);
797             apr_file_close(fp);
798             return "";
799         }
800         buf[len] = '\0';
801     }
802     apr_file_close(fp);
803     return buf;
804 }
805
806
807 static const char *unescape_func(ap_expr_eval_ctx *ctx, const void *data,
808                                  const char *arg)
809 {
810     char *result = apr_pstrdup(ctx->p, arg);
811     if (ap_unescape_url(result))
812         return "";
813     else
814         return result;
815
816 }
817
818 static int op_nz(ap_expr_eval_ctx *ctx, const void *data, const char *arg)
819 {
820     const char *name = (const char *)data;
821     if (name[0] == 'z')
822         return (arg[0] == '\0');
823     else
824         return (arg[0] != '\0');
825 }
826
827 APR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec *));
828 static APR_OPTIONAL_FN_TYPE(ssl_is_https) *is_https = NULL;
829
830 static const char *conn_var_names[] = {
831     "REMOTE_ADDR",              /*  0 */
832     "HTTPS",                    /*  1 */
833     "IPV6",                     /*  2 */
834     NULL
835 };
836
837 static const char *conn_var_fn(ap_expr_eval_ctx *ctx, const void *data)
838 {
839     int index = ((const char **)data - conn_var_names);
840     conn_rec *c = ctx->c;
841     if (!c)
842         return "";
843
844     switch (index) {
845     case 0:
846         return c->remote_ip;
847     case 1:
848         if (is_https && is_https(c))
849             return "on";
850         else
851             return "off";
852     case 2:
853 #if APR_HAVE_IPV6
854         {
855             apr_sockaddr_t *addr = c->remote_addr;
856             if (addr->family == AF_INET6
857                 && !IN6_IS_ADDR_V4MAPPED((struct in6_addr *)addr->ipaddr_ptr))
858                 return "on";
859             else
860                 return "off";
861         }
862 #else
863         return "off";
864 #endif
865     default:
866         ap_assert(0);
867         return NULL;
868     }
869 }
870
871 static const char *request_var_names[] = {
872     "REQUEST_METHOD",           /*  0 */
873     "REQUEST_SCHEME",           /*  1 */
874     "REQUEST_URI",              /*  2 */
875     "REQUEST_FILENAME",         /*  3 */
876     "REMOTE_HOST",              /*  4 */
877     "REMOTE_IDENT",             /*  5 */
878     "REMOTE_USER",              /*  6 */
879     "SERVER_ADMIN",             /*  7 */
880     "SERVER_NAME",              /*  8 */
881     "SERVER_PORT",              /*  9 */
882     "SERVER_PROTOCOL",          /* 10 */
883     "SCRIPT_FILENAME",          /* 11 */
884     "PATH_INFO",                /* 12 */
885     "QUERY_STRING",             /* 13 */
886     "IS_SUBREQ",                /* 14 */
887     "DOCUMENT_ROOT",            /* 15 */
888     "AUTH_TYPE",                /* 16 */
889     "THE_REQUEST",              /* 17 */
890     "CONTENT_TYPE",             /* 18 */
891     NULL
892 };
893
894 static const char *request_var_fn(ap_expr_eval_ctx *ctx, const void *data)
895 {
896     int index = ((const char **)data - request_var_names);
897     request_rec *r = ctx->r;
898     if (!r)
899         return "";
900
901     switch (index) {
902     case 0:
903         return r->method;
904     case 1:
905         return ap_http_scheme(r);
906     case 2:
907         return r->uri;
908     case 3:
909         return r->filename;
910     case 4:
911         return ap_get_remote_host(r->connection, r->per_dir_config,
912                                   REMOTE_NAME, NULL);
913     case 5:
914         return ap_get_remote_logname(r);
915     case 6:
916         return r->user;
917     case 7:
918         return r->server->server_admin;
919     case 8:
920         return ap_get_server_name(r);
921     case 9:
922         return apr_psprintf(ctx->p, "%u", ap_get_server_port(r));
923     case 10:
924         return r->protocol;
925     case 11:
926         return r->filename;
927     case 12:
928         return r->path_info;
929     case 13:
930         return r->args;
931     case 14:
932         return (r->main != NULL ? "true" : "false");
933     case 15:
934         return ap_document_root(r);
935     case 16:
936         return r->ap_auth_type;
937     case 17:
938         return r->the_request;
939     case 18:
940         return r->content_type;
941     default:
942         ap_assert(0);
943         return NULL;
944     }
945 }
946
947 static const char *req_header_var_names[] = {
948     "HTTP_USER_AGENT",          /* 0 */
949     "HTTP_PROXY_CONNECTION",    /* 1 */
950     "HTTP_REFERER",
951     "HTTP_COOKIE",
952     "HTTP_FORWARDED",
953     "HTTP_HOST",
954     "HTTP_ACCEPT",
955     NULL
956 };
957
958 static const char *req_header_var_fn(ap_expr_eval_ctx *ctx, const void *data)
959 {
960     const char **name = (const char **)data;
961     int index = (name - req_header_var_names);
962     if (!ctx->r)
963         return "";
964
965     switch (index) {
966     case 0:
967         return apr_table_get(ctx->r->headers_in, "User-Agent");
968     case 1:
969         return apr_table_get(ctx->r->headers_in, "Proxy-Connection");
970     default:
971         /* apr_table_get is case insensitive, just skip leading "HTTP_" */
972         return apr_table_get(ctx->r->headers_in, *name + 5);
973     }
974 }
975
976 static const char *misc_var_names[] = {
977     "TIME_YEAR",        /* 0 */
978     "TIME_MON",         /* 1 */
979     "TIME_DAY",         /* 2 */
980     "TIME_HOUR",        /* 3 */
981     "TIME_MIN",         /* 4 */
982     "TIME_SEC",         /* 5 */
983     "TIME_WDAY",        /* 6 */
984     "TIME",             /* 7 */
985     "SERVER_SOFTWARE",  /* 8 */
986     "API_VERSION",      /* 9 */
987     NULL
988 };
989
990 static const char *misc_var_fn(ap_expr_eval_ctx *ctx, const void *data)
991 {
992     apr_time_exp_t tm;
993     int index = ((const char **)data - misc_var_names);
994     apr_time_exp_lt(&tm, apr_time_now());
995
996     switch (index) {
997     case 0:
998         return apr_psprintf(ctx->p, "%02d%02d", (tm.tm_year / 100) + 19,
999                             tm.tm_year % 100);
1000     case 1:
1001         return apr_psprintf(ctx->p, "%02d", tm.tm_mon+1);
1002     case 2:
1003         return apr_psprintf(ctx->p, "%02d", tm.tm_mday);
1004     case 3:
1005         return apr_psprintf(ctx->p, "%02d", tm.tm_hour);
1006     case 4:
1007         return apr_psprintf(ctx->p, "%02d", tm.tm_min);
1008     case 5:
1009         return apr_psprintf(ctx->p, "%02d", tm.tm_sec);
1010     case 6:
1011         return apr_psprintf(ctx->p, "%d", tm.tm_wday);
1012     case 7:
1013         return apr_psprintf(ctx->p, "%02d%02d%02d%02d%02d%02d%02d",
1014                             (tm.tm_year / 100) + 19, (tm.tm_year % 100),
1015                             tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min,
1016                             tm.tm_sec);
1017     case 8:
1018         return ap_get_server_banner();
1019     case 9:
1020         return apr_itoa(ctx->p, MODULE_MAGIC_NUMBER);
1021     default:
1022         ap_assert(0);
1023     }
1024
1025     return NULL;
1026 }
1027
1028 struct expr_provider_single {
1029     const void *func;
1030     const char *name;
1031 };
1032 struct expr_provider_multi {
1033     const void *func;
1034     const char **names;
1035 };
1036
1037 static const struct expr_provider_multi var_providers[] = {
1038     { misc_var_fn, misc_var_names },
1039     { req_header_var_fn, req_header_var_names },
1040     { request_var_fn, request_var_names },
1041     { conn_var_fn, conn_var_names },
1042     { NULL, NULL }
1043 };
1044
1045 static const struct expr_provider_single string_func_providers[] = {
1046     { osenv_func, "osenv" },
1047     { env_func, "env" },
1048     { req_table_func, "resp" },
1049     { req_table_func, "req" },
1050     /* 'http' as alias for 'req' for compatibility with ssl_expr */
1051     { req_table_func, "http" },
1052     { req_table_func, "note" },
1053     { tolower_func, "tolower" },
1054     { toupper_func, "toupper" },
1055     { escape_func, "escape" },
1056     { unescape_func, "unescape" },
1057     { file_func, "file" },
1058     { NULL, NULL}
1059 };
1060 /* XXX: base64 encode/decode ? */
1061
1062 static const struct expr_provider_single unary_op_providers[] = {
1063     { op_nz, "n" },
1064     { op_nz, "z" },
1065     { NULL, NULL}
1066 };
1067 static int core_expr_lookup(ap_expr_lookup_parms *parms)
1068 {
1069     switch (parms->type) {
1070     case AP_EXPR_FUNC_VAR: {
1071         const struct expr_provider_multi *prov = var_providers;
1072         while (prov->func) {
1073             const char **name = prov->names;
1074             while (*name) {
1075                 if (strcasecmp(*name, parms->name) == 0) {
1076                     *parms->func = prov->func;
1077                     *parms->data = name;
1078                     return OK;
1079                 }
1080                 name++;
1081             }
1082             prov++;
1083         }
1084         break;
1085     }
1086     case AP_EXPR_FUNC_STRING: {
1087         const struct expr_provider_single *prov = string_func_providers;
1088         while (prov->func) {
1089             if (strcasecmp(prov->name, parms->name) == 0) {
1090                 *parms->func = prov->func;
1091                 *parms->data = prov->name;
1092                 return OK;
1093             }
1094             prov++;
1095         }
1096         break;
1097     }
1098     case AP_EXPR_FUNC_OP_UNARY: {
1099         const struct expr_provider_single *prov = unary_op_providers;
1100         while (prov->func) {
1101             if (strcasecmp(prov->name, parms->name) == 0) {
1102                 *parms->func = prov->func;
1103                 *parms->data = prov->name;
1104                 return OK;
1105             }
1106             prov++;
1107         }
1108         break;
1109     }
1110     default:
1111         break;
1112     }
1113     return DECLINED;
1114 }
1115
1116 static int expr_lookup_not_found(ap_expr_lookup_parms *parms)
1117 {
1118     const char *type;
1119
1120     switch (parms->type) {
1121     case AP_EXPR_FUNC_VAR:
1122         type = "Variable";
1123         break;
1124     case AP_EXPR_FUNC_STRING:
1125         type = "Function";
1126         break;
1127     case AP_EXPR_FUNC_LIST:
1128         type = "List-returning function";
1129         break;
1130     case AP_EXPR_FUNC_OP_UNARY:
1131         type = "Unary operator";
1132         break;
1133     case AP_EXPR_FUNC_OP_BINARY:
1134         type = "Binary operator";
1135         break;
1136     default:
1137         *parms->err = "Inavalid expression type in expr_lookup";
1138         return !OK;
1139     }
1140     *parms->err = apr_psprintf(parms->ptemp, "%s '%s' does not exist", type,
1141                                parms->name);
1142     return !OK;
1143 }
1144
1145 static int ap_expr_post_config(apr_pool_t *pconf, apr_pool_t *plog,
1146                                apr_pool_t *ptemp, server_rec *s)
1147 {
1148     is_https = APR_RETRIEVE_OPTIONAL_FN(ssl_is_https);
1149     apr_pool_cleanup_register(pconf, &is_https, ap_pool_cleanup_set_null,
1150                               apr_pool_cleanup_null);
1151     return OK;
1152 }
1153
1154 void ap_expr_init(apr_pool_t *p)
1155 {
1156     ap_hook_expr_lookup(core_expr_lookup, NULL, NULL, APR_HOOK_MIDDLE);
1157     ap_hook_expr_lookup(expr_lookup_not_found, NULL, NULL, APR_HOOK_REALLY_LAST);
1158     ap_hook_post_config(ap_expr_post_config, NULL, NULL, APR_HOOK_MIDDLE);
1159 }
1160