diff options
author | Glenn Strauss <gstrauss@gluelogic.com> | 2021-11-09 15:00:36 -0500 |
---|---|---|
committer | Glenn Strauss <gstrauss@gluelogic.com> | 2021-11-12 17:56:38 -0500 |
commit | 741513ecd11d341d1e752175eee5d180334a4c35 (patch) | |
tree | a31a164c4948538c1182d1dce114f750867b1376 /src | |
parent | 457362cbe35533926694d97557a39e906cce4e55 (diff) | |
download | lighttpd-git-741513ecd11d341d1e752175eee5d180334a4c35.tar.gz |
[mod_ssi] merge mod_ssi_expr.c into mod_ssi.c
isolate this ancient relic
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/SConscript | 2 | ||||
-rw-r--r-- | src/meson.build | 2 | ||||
-rw-r--r-- | src/mod_ssi.c | 374 | ||||
-rw-r--r-- | src/mod_ssi.h | 47 | ||||
-rw-r--r-- | src/mod_ssi_expr.c | 335 | ||||
-rw-r--r-- | src/t/test_mod_ssi.c | 1 |
8 files changed, 377 insertions, 391 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f0e17673..1e36cc31 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -838,7 +838,7 @@ add_and_install_library(mod_secdownload "mod_secdownload.c;algo_hmac.c") add_and_install_library(mod_setenv mod_setenv.c) add_and_install_library(mod_simple_vhost mod_simple_vhost.c) add_and_install_library(mod_sockproxy mod_sockproxy.c) -add_and_install_library(mod_ssi "mod_ssi_expr.c;mod_ssi.c") +add_and_install_library(mod_ssi mod_ssi.c) add_and_install_library(mod_staticfile mod_staticfile.c) add_and_install_library(mod_status mod_status.c) add_and_install_library(mod_uploadprogress mod_uploadprogress.c) diff --git a/src/Makefile.am b/src/Makefile.am index 329c598c..ee2a403b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -282,7 +282,7 @@ mod_sockproxy_la_LDFLAGS = $(common_module_ldflags) mod_sockproxy_la_LIBADD = $(common_libadd) lib_LTLIBRARIES += mod_ssi.la -mod_ssi_la_SOURCES = mod_ssi_expr.c mod_ssi.c +mod_ssi_la_SOURCES = mod_ssi.c mod_ssi_la_LDFLAGS = $(common_module_ldflags) mod_ssi_la_LIBADD = $(common_libadd) @@ -478,7 +478,6 @@ hdr = base64.h buffer.h burl.h network.h log.h http_kv.h keyvalue.h \ plugin.h plugin_config.h \ http_etag.h array.h vector.h \ fdevent_impl.h network_write.h configfile.h \ - mod_ssi.h \ sock_addr_cache.h \ configparser.h \ rand.h \ @@ -528,7 +527,7 @@ lighttpd_SOURCES = \ mod_secdownload.c algo_hmac.c \ mod_setenv.c \ mod_simple_vhost.c \ - mod_ssi_expr.c mod_ssi.c \ + mod_ssi.c \ mod_staticfile.c \ mod_status.c \ mod_uploadprogress.c \ diff --git a/src/SConscript b/src/SConscript index 79a5df88..0b9bba20 100644 --- a/src/SConscript +++ b/src/SConscript @@ -119,7 +119,7 @@ modules = { 'mod_setenv' : { 'src' : [ 'mod_setenv.c' ] }, 'mod_simple_vhost' : { 'src' : [ 'mod_simple_vhost.c' ] }, 'mod_sockproxy' : { 'src' : [ 'mod_sockproxy.c' ] }, - 'mod_ssi' : { 'src' : [ 'mod_ssi_expr.c', 'mod_ssi.c' ] }, + 'mod_ssi' : { 'src' : [ 'mod_ssi.c' ] }, 'mod_staticfile' : { 'src' : [ 'mod_staticfile.c' ] }, 'mod_status' : { 'src' : [ 'mod_status.c' ] }, 'mod_uploadprogress' : { 'src' : [ 'mod_uploadprogress.c' ] }, diff --git a/src/meson.build b/src/meson.build index 548bb5a0..a51bb5c9 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1117,7 +1117,7 @@ modules = [ [ 'mod_setenv', [ 'mod_setenv.c' ] ], [ 'mod_simple_vhost', [ 'mod_simple_vhost.c' ] ], [ 'mod_sockproxy', [ 'mod_sockproxy.c' ] ], - [ 'mod_ssi', [ 'mod_ssi_expr.c', 'mod_ssi.c' ], libws2_32 ], + [ 'mod_ssi', [ 'mod_ssi.c' ], libws2_32 ], [ 'mod_staticfile', [ 'mod_staticfile.c' ] ], [ 'mod_status', [ 'mod_status.c' ] ], [ 'mod_uploadprogress', [ 'mod_uploadprogress.c' ] ], diff --git a/src/mod_ssi.c b/src/mod_ssi.c index 1b1cf467..5ccd92b8 100644 --- a/src/mod_ssi.c +++ b/src/mod_ssi.c @@ -3,7 +3,9 @@ #include "fdevent.h" #include "fdlog.h" #include "log.h" +#include "array.h" #include "buffer.h" +#include "chunk.h" #include "http_cgi.h" #include "http_chunk.h" #include "http_etag.h" @@ -15,8 +17,6 @@ #include "response.h" -#include "mod_ssi.h" - #include "sys-socket.h" #include "sys-time.h" @@ -41,6 +41,39 @@ # include <sys/filio.h> #endif +typedef struct { + const array *ssi_extension; + const buffer *content_type; + unsigned short conditional_requests; + unsigned short ssi_exec; + unsigned short ssi_recursion_max; +} plugin_config; + +typedef struct { + PLUGIN_DATA; + plugin_config defaults; + plugin_config conf; + array *ssi_vars; + array *ssi_cgi_env; + buffer stat_fn; + buffer timefmt; +} plugin_data; + +typedef struct { + array *ssi_vars; + array *ssi_cgi_env; + buffer *stat_fn; + buffer *timefmt; + int sizefmt; + + int if_level, if_is_false_level, if_is_false, if_is_false_endif; + unsigned short ssi_recursion_depth; + + chunkqueue wq; + log_error_st *errh; + plugin_config conf; +} handler_ctx; + static handler_ctx * handler_ctx_init(plugin_data *p, log_error_st *errh) { handler_ctx *hctx = calloc(1, sizeof(*hctx)); force_assert(hctx); @@ -178,6 +211,343 @@ SETDEFAULTS_FUNC(mod_ssi_set_defaults) { } + + +#define TK_AND 1 +#define TK_OR 2 +#define TK_EQ 3 +#define TK_NE 4 +#define TK_GT 5 +#define TK_GE 6 +#define TK_LT 7 +#define TK_LE 8 +#define TK_NOT 9 +#define TK_LPARAN 10 +#define TK_RPARAN 11 +#define TK_VALUE 12 + +typedef struct { + const char *input; + size_t offset; + size_t size; + int in_brace; + int depth; + handler_ctx *p; +} ssi_tokenizer_t; + +typedef struct { + buffer str; + enum { SSI_TYPE_UNSET, SSI_TYPE_BOOL, SSI_TYPE_STRING } type; + int bo; +} ssi_val_t; + +__attribute_pure__ +static int ssi_val_tobool(const ssi_val_t *B) { + return B->type == SSI_TYPE_BOOL ? B->bo : !buffer_is_blank(&B->str); +} + +__attribute_pure__ +static int ssi_eval_expr_cmp(const ssi_val_t * const v1, const ssi_val_t * const v2, const int cond) { + int cmp = (v1->type != SSI_TYPE_BOOL && v2->type != SSI_TYPE_BOOL) + ? strcmp(v1->str.ptr ? v1->str.ptr : "", + v2->str.ptr ? v2->str.ptr : "") + : ssi_val_tobool(v1) - ssi_val_tobool(v2); + switch (cond) { + case TK_EQ: return (cmp == 0); + case TK_NE: return (cmp != 0); + case TK_GE: return (cmp >= 0); + case TK_GT: return (cmp > 0); + case TK_LE: return (cmp <= 0); + case TK_LT: return (cmp < 0); + default: return 0;/*(should not happen)*/ + } +} + +__attribute_pure__ +static int ssi_eval_expr_cmp_bool(const ssi_val_t * const v1, const ssi_val_t * const v2, const int cond) { + return (cond == TK_OR) + ? ssi_val_tobool(v1) || ssi_val_tobool(v2) /* TK_OR */ + : ssi_val_tobool(v1) && ssi_val_tobool(v2); /* TK_AND */ +} + +static void ssi_eval_expr_append_val(buffer * const b, const char *s, const size_t slen) { + if (buffer_is_blank(b)) + buffer_append_string_len(b, s, slen); + else if (slen) + buffer_append_str2(b, CONST_STR_LEN(" "), s, slen); +} + +static int ssi_expr_tokenizer(ssi_tokenizer_t * const t, buffer * const token) { + size_t i; + + while (t->offset < t->size + && (t->input[t->offset] == ' ' || t->input[t->offset] == '\t')) { + ++t->offset; + } + if (t->offset >= t->size) + return 0; + if (t->input[t->offset] == '\0') { + log_error(t->p->errh, __FILE__, __LINE__, + "pos: %zu foobar", t->offset+1); + return -1; + } + + switch (t->input[t->offset]) { + case '=': + #if 0 /*(maybe accept "==", too)*/ + if (t->input[t->offset + 1] == '=') + ++t->offset; + #endif + t->offset++; + return TK_EQ; + case '>': + if (t->input[t->offset + 1] == '=') { + t->offset += 2; + return TK_GE; + } + else { + t->offset += 1; + return TK_GT; + } + case '<': + if (t->input[t->offset + 1] == '=') { + t->offset += 2; + return TK_LE; + } + else { + t->offset += 1; + return TK_LT; + } + case '!': + if (t->input[t->offset + 1] == '=') { + t->offset += 2; + return TK_NE; + } + else { + t->offset += 1; + return TK_NOT; + } + case '&': + if (t->input[t->offset + 1] == '&') { + t->offset += 2; + return TK_AND; + } + else { + log_error(t->p->errh, __FILE__, __LINE__, + "pos: %zu missing second &", t->offset+1); + return -1; + } + case '|': + if (t->input[t->offset + 1] == '|') { + t->offset += 2; + return TK_OR; + } + else { + log_error(t->p->errh, __FILE__, __LINE__, + "pos: %zu missing second |", t->offset+1); + return -1; + } + case '(': + t->offset++; + t->in_brace++; + return TK_LPARAN; + case ')': + t->offset++; + t->in_brace--; + return TK_RPARAN; + case '\'': + /* search for the terminating "'" */ + i = 1; + while (t->input[t->offset + i] && t->input[t->offset + i] != '\'') + ++i; + if (t->input[t->offset + i]) { + ssi_eval_expr_append_val(token, t->input + t->offset + 1, i-1); + t->offset += i + 1; + return TK_VALUE; + } + else { + log_error(t->p->errh, __FILE__, __LINE__, + "pos: %zu missing closing quote", t->offset+1); + return -1; + } + case '$': { + const char *var; + size_t varlen; + if (t->input[t->offset + 1] == '{') { + i = 2; + while (t->input[t->offset + i] && t->input[t->offset + i] != '}') + ++i; + if (t->input[t->offset + i] != '}') { + log_error(t->p->errh, __FILE__, __LINE__, + "pos: %zu missing closing curly-brace", t->offset+1); + return -1; + } + ++i; /* step past '}' */ + var = t->input + t->offset + 2; + varlen = i-3; + } + else { + for (i = 1; light_isalpha(t->input[t->offset + i]) || + t->input[t->offset + i] == '_' || + ((i > 1) && light_isdigit(t->input[t->offset + i])); ++i) ; + var = t->input + t->offset + 1; + varlen = i-1; + } + + const data_string *ds; + if ((ds = (const data_string *) + array_get_element_klen(t->p->ssi_cgi_env, var, varlen)) + || (ds = (const data_string *) + array_get_element_klen(t->p->ssi_vars, var, varlen))) + ssi_eval_expr_append_val(token, BUF_PTR_LEN(&ds->value)); + t->offset += i; + return TK_VALUE; + } + default: + for (i = 0; isgraph(((unsigned char *)t->input)[t->offset + i]); ++i) { + char d = t->input[t->offset + i]; + switch(d) { + default: continue; + case ' ': + case '\t': + case ')': + case '(': + case '\'': + case '=': + case '!': + case '<': + case '>': + case '&': + case '|': + break; + } + break; + } + ssi_eval_expr_append_val(token, t->input + t->offset, i); + t->offset += i; + return TK_VALUE; + } +} + +static int ssi_eval_expr_loop(ssi_tokenizer_t * const t, ssi_val_t * const v); + +static int ssi_eval_expr_step(ssi_tokenizer_t * const t, ssi_val_t * const v) { + buffer_clear(&v->str); + v->type = SSI_TYPE_UNSET; /*(not SSI_TYPE_BOOL)*/ + int next; + const int level = t->in_brace; + switch ((next = ssi_expr_tokenizer(t, &v->str))) { + case TK_VALUE: + do { next = ssi_expr_tokenizer(t, &v->str); } while (next == TK_VALUE); + return next; + case TK_LPARAN: + if (t->in_brace > 16) return -1; /*(arbitrary limit)*/ + next = ssi_eval_expr_loop(t, v); + if (next == TK_RPARAN && level == t->in_brace) { + int result = ssi_val_tobool(v); + next = ssi_eval_expr_step(t, v); /*(resets v)*/ + v->bo = result; + v->type = SSI_TYPE_BOOL; + return (next==TK_AND || next==TK_OR || next==TK_RPARAN || 0==next) + ? next + : -1; + } + else + return -1; + case TK_RPARAN: + return t->in_brace >= 0 ? TK_RPARAN : -1; + case TK_NOT: + if (++t->depth > 16) return -1; /*(arbitrary limit)*/ + next = ssi_eval_expr_step(t, v); + --t->depth; + if (-1 == next) return next; + v->bo = !ssi_val_tobool(v); + v->type = SSI_TYPE_BOOL; + return next; + default: + return next; + } +} + +static int ssi_eval_expr_loop_cmp(ssi_tokenizer_t * const t, ssi_val_t * const v1, int cond) { + ssi_val_t v2 = { { NULL, 0, 0 }, SSI_TYPE_UNSET, 0 }; + int next = ssi_eval_expr_step(t, &v2); + if (-1 != next) { + v1->bo = ssi_eval_expr_cmp(v1, &v2, cond); + v1->type = SSI_TYPE_BOOL; + } + buffer_free_ptr(&v2.str); + return next; +} + +static int ssi_eval_expr_loop(ssi_tokenizer_t * const t, ssi_val_t * const v1) { + int next = ssi_eval_expr_step(t, v1); + switch (next) { + case TK_AND: case TK_OR: + break; + case TK_EQ: case TK_NE: + case TK_GT: case TK_GE: + case TK_LT: case TK_LE: + next = ssi_eval_expr_loop_cmp(t, v1, next); + if (next == TK_RPARAN || 0 == next) return next; + if (next != TK_AND && next != TK_OR) { + log_error(t->p->errh, __FILE__, __LINE__, + "pos: %zu parser failed somehow near here", t->offset+1); + return -1; + } + break; + default: + return next; + } + + /*(Note: '&&' and '||' evaluations are not short-circuited)*/ + ssi_val_t v2 = { { NULL, 0, 0 }, SSI_TYPE_UNSET, 0 }; + do { + int cond = next; + next = ssi_eval_expr_step(t, &v2); + switch (next) { + case TK_AND: case TK_OR: case 0: + break; + case TK_EQ: case TK_NE: + case TK_GT: case TK_GE: + case TK_LT: case TK_LE: + next = ssi_eval_expr_loop_cmp(t, &v2, next); + if (-1 == next) continue; + break; + case TK_RPARAN: + break; + default: + continue; + } + v1->bo = ssi_eval_expr_cmp_bool(v1, &v2, cond); + v1->type = SSI_TYPE_BOOL; + } while (next == TK_AND || next == TK_OR); + buffer_free_ptr(&v2.str); + return next; +} + +static int ssi_eval_expr(handler_ctx *p, const char *expr) { + ssi_tokenizer_t t; + t.input = expr; + t.offset = 0; + t.size = strlen(expr); + t.in_brace = 0; + t.depth = 0; + t.p = p; + + ssi_val_t v = { { NULL, 0, 0 }, SSI_TYPE_UNSET, 0 }; + int rc = ssi_eval_expr_loop(&t, &v); + rc = (0 == rc && 0 == t.in_brace && 0 == t.depth) + ? ssi_val_tobool(&v) + : -1; + buffer_free_ptr(&v.str); + + return rc; +} + + + + static int ssi_env_add(void *venv, const char *key, size_t klen, const char *val, size_t vlen) { array_set_key_value((array *)venv, key, klen, val, vlen); return 0; diff --git a/src/mod_ssi.h b/src/mod_ssi.h deleted file mode 100644 index 49581d39..00000000 --- a/src/mod_ssi.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef _MOD_SSI_H_ -#define _MOD_SSI_H_ -#include "first.h" - -#include "base_decls.h" -#include "buffer.h" -#include "array.h" -#include "chunk.h" - -#include "plugin.h" - -typedef struct { - const array *ssi_extension; - const buffer *content_type; - unsigned short conditional_requests; - unsigned short ssi_exec; - unsigned short ssi_recursion_max; -} plugin_config; - -typedef struct { - PLUGIN_DATA; - plugin_config defaults; - plugin_config conf; - array *ssi_vars; - array *ssi_cgi_env; - buffer stat_fn; - buffer timefmt; -} plugin_data; - -typedef struct { - array *ssi_vars; - array *ssi_cgi_env; - buffer *stat_fn; - buffer *timefmt; - int sizefmt; - - int if_level, if_is_false_level, if_is_false, if_is_false_endif; - unsigned short ssi_recursion_depth; - - chunkqueue wq; - log_error_st *errh; - plugin_config conf; -} handler_ctx; - -int ssi_eval_expr(handler_ctx *p, const char *expr); - -#endif diff --git a/src/mod_ssi_expr.c b/src/mod_ssi_expr.c deleted file mode 100644 index a72825cd..00000000 --- a/src/mod_ssi_expr.c +++ /dev/null @@ -1,335 +0,0 @@ -#include "first.h" - -#include "buffer.h" -#include "log.h" -#include "mod_ssi.h" - -#include <ctype.h> -#include <stdlib.h> -#include <string.h> - -#define TK_AND 1 -#define TK_OR 2 -#define TK_EQ 3 -#define TK_NE 4 -#define TK_GT 5 -#define TK_GE 6 -#define TK_LT 7 -#define TK_LE 8 -#define TK_NOT 9 -#define TK_LPARAN 10 -#define TK_RPARAN 11 -#define TK_VALUE 12 - -typedef struct { - const char *input; - size_t offset; - size_t size; - - int in_brace; - int depth; - handler_ctx *p; -} ssi_tokenizer_t; - -typedef struct { - enum { SSI_TYPE_UNSET, SSI_TYPE_BOOL, SSI_TYPE_STRING } type; - - buffer *str; - int bo; -} ssi_val_t; - -__attribute_pure__ -static int ssi_val_tobool(const ssi_val_t *B) { - return B->type == SSI_TYPE_BOOL ? B->bo : !buffer_is_blank(B->str); -} - -__attribute_pure__ -static int ssi_eval_expr_cmp(const ssi_val_t * const v1, const ssi_val_t * const v2, const int cond) { - int cmp = (v1->type != SSI_TYPE_BOOL && v2->type != SSI_TYPE_BOOL) - ? strcmp(v1->str->ptr ? v1->str->ptr : "", - v2->str->ptr ? v2->str->ptr : "") - : ssi_val_tobool(v1) - ssi_val_tobool(v2); - switch (cond) { - case TK_EQ: return (cmp == 0); - case TK_NE: return (cmp != 0); - case TK_GE: return (cmp >= 0); - case TK_GT: return (cmp > 0); - case TK_LE: return (cmp <= 0); - case TK_LT: return (cmp < 0); - default: return 0;/*(should not happen)*/ - } -} - -__attribute_pure__ -static int ssi_eval_expr_cmp_bool(const ssi_val_t * const v1, const ssi_val_t * const v2, const int cond) { - return (cond == TK_OR) - ? ssi_val_tobool(v1) || ssi_val_tobool(v2) /* TK_OR */ - : ssi_val_tobool(v1) && ssi_val_tobool(v2); /* TK_AND */ -} - -static void ssi_eval_expr_append_val(buffer * const b, const char *s, const size_t slen) { - if (buffer_is_blank(b)) - buffer_append_string_len(b, s, slen); - else - buffer_append_str2(b, CONST_STR_LEN(""), s, slen); -} - -static int ssi_expr_tokenizer(ssi_tokenizer_t * const t, buffer * const token) { - size_t i; - - while (t->offset < t->size - && (t->input[t->offset] == ' ' || t->input[t->offset] == '\t')) { - ++t->offset; - } - if (t->offset >= t->size) - return 0; - if (t->input[t->offset] == '\0') { - log_error(t->p->errh, __FILE__, __LINE__, - "pos: %zu foobar", t->offset+1); - return -1; - } - - switch (t->input[t->offset]) { - case '=': - #if 0 /*(maybe accept "==", too)*/ - if (t->input[t->offset + 1] == '=') - ++t->offset; - #endif - t->offset++; - return TK_EQ; - case '>': - if (t->input[t->offset + 1] == '=') { - t->offset += 2; - return TK_GE; - } else { - t->offset += 1; - return TK_GT; - } - case '<': - if (t->input[t->offset + 1] == '=') { - t->offset += 2; - return TK_LE; - } else { - t->offset += 1; - return TK_LT; - } - case '!': - if (t->input[t->offset + 1] == '=') { - t->offset += 2; - return TK_NE; - } else { - t->offset += 1; - return TK_NOT; - } - case '&': - if (t->input[t->offset + 1] == '&') { - t->offset += 2; - return TK_AND; - } else { - log_error(t->p->errh, __FILE__, __LINE__, - "pos: %zu missing second &", t->offset+1); - return -1; - } - case '|': - if (t->input[t->offset + 1] == '|') { - t->offset += 2; - return TK_OR; - } else { - log_error(t->p->errh, __FILE__, __LINE__, - "pos: %zu missing second |", t->offset+1); - return -1; - } - case '(': - t->offset++; - t->in_brace++; - return TK_LPARAN; - case ')': - t->offset++; - t->in_brace--; - return TK_RPARAN; - case '\'': - /* search for the terminating "'" */ - for (i = 1; t->input[t->offset + i] && t->input[t->offset + i] != '\''; i++); - - if (t->input[t->offset + i]) { - ssi_eval_expr_append_val(token, t->input + t->offset + 1, i-1); - t->offset += i + 1; - return TK_VALUE; - } else { - log_error(t->p->errh, __FILE__, __LINE__, - "pos: %zu missing closing quote", t->offset+1); - return -1; - } - case '$': { - const char *var; - size_t varlen; - if (t->input[t->offset + 1] == '{') { - for (i = 2; t->input[t->offset + i] && t->input[t->offset + i] != '}'; i++); - - if (t->input[t->offset + i] != '}') { - log_error(t->p->errh, __FILE__, __LINE__, - "pos: %zu missing closing curly-brace", t->offset+1); - return -1; - } - ++i; /* step past '}' */ - var = t->input + t->offset + 2; - varlen = i-3; - } else { - for (i = 1; isalpha(((unsigned char *)t->input)[t->offset + i]) || - t->input[t->offset + i] == '_' || - ((i > 1) && isdigit(((unsigned char *)t->input)[t->offset + i])); i++); - var = t->input + t->offset + 1; - varlen = i-1; - } - - const data_string *ds; - if (NULL != (ds = (const data_string *)array_get_element_klen(t->p->ssi_cgi_env, var, varlen)) - || NULL != (ds = (const data_string *)array_get_element_klen(t->p->ssi_vars, var, varlen))) - ssi_eval_expr_append_val(token, BUF_PTR_LEN(&ds->value)); - t->offset += i; - return TK_VALUE; - } - default: - for (i = 0; isgraph(((unsigned char *)t->input)[t->offset + i]); i++) { - char d = t->input[t->offset + i]; - switch(d) { - default: continue; - case ' ': - case '\t': - case ')': - case '(': - case '\'': - case '=': - case '!': - case '<': - case '>': - case '&': - case '|': - break; - } - break; - } - ssi_eval_expr_append_val(token, t->input + t->offset, i); - t->offset += i; - return TK_VALUE; - } -} - -static int ssi_eval_expr_loop(ssi_tokenizer_t * const t, ssi_val_t * const v); - -static int ssi_eval_expr_step(ssi_tokenizer_t * const t, ssi_val_t * const v) { - buffer_clear(v->str); - v->type = SSI_TYPE_UNSET; /*(not SSI_TYPE_BOOL)*/ - int next; - const int level = t->in_brace; - switch ((next = ssi_expr_tokenizer(t, v->str))) { - case TK_VALUE: - do { next=ssi_expr_tokenizer(t, v->str); } while (next == TK_VALUE); - return next; - case TK_LPARAN: - if (t->in_brace > 16) return -1; /*(arbitrary limit)*/ - next = ssi_eval_expr_loop(t, v); - if (next == TK_RPARAN && level == t->in_brace) { - int result = ssi_val_tobool(v); - next = ssi_eval_expr_step(t, v); /*(resets v)*/ - v->bo = result; - v->type = SSI_TYPE_BOOL; - return (next==TK_AND || next==TK_OR || next==TK_RPARAN || 0==next) - ? next - : -1; - } - else - return -1; - case TK_RPARAN: - return t->in_brace >= 0 ? TK_RPARAN : -1; - case TK_NOT: - if (++t->depth > 16) return -1; /*(arbitrary limit)*/ - next = ssi_eval_expr_step(t, v); - --t->depth; - if (-1 == next) return next; - v->bo = !ssi_val_tobool(v); - v->type = SSI_TYPE_BOOL; - return next; - default: - return next; - } -} - -static int ssi_eval_expr_loop_cmp(ssi_tokenizer_t * const t, ssi_val_t * const v1, int cond) { - ssi_val_t v2 = { SSI_TYPE_UNSET, NULL, 0 }; - v2.str = buffer_init(); - int next = ssi_eval_expr_step(t, &v2); - if (-1 != next) { - v1->bo = ssi_eval_expr_cmp(v1, &v2, cond); - v1->type = SSI_TYPE_BOOL; - } - buffer_free(v2.str); - return next; -} - -static int ssi_eval_expr_loop(ssi_tokenizer_t * const t, ssi_val_t * const v1) { - int next = ssi_eval_expr_step(t, v1); - switch (next) { - case TK_AND: case TK_OR: - break; - case TK_EQ: case TK_NE: - case TK_GT: case TK_GE: - case TK_LT: case TK_LE: - next = ssi_eval_expr_loop_cmp(t, v1, next); - if (next == TK_RPARAN || 0 == next) return next; - if (next != TK_AND && next != TK_OR) { - log_error(t->p->errh, __FILE__, __LINE__, - "pos: %zu parser failed somehow near here", t->offset+1); - return -1; - } - break; - default: - return next; - } - - /*(Note: '&&' and '||' evaluations are not short-circuited)*/ - ssi_val_t v2 = { SSI_TYPE_UNSET, NULL, 0 }; - v2.str = buffer_init(); - do { - int cond = next; - next = ssi_eval_expr_step(t, &v2); - switch (next) { - case TK_AND: case TK_OR: case 0: - break; - case TK_EQ: case TK_NE: - case TK_GT: case TK_GE: - case TK_LT: case TK_LE: - next = ssi_eval_expr_loop_cmp(t, &v2, next); - if (-1 != next) - break; - __attribute_fallthrough__ - default: - buffer_free(v2.str); - return next; - } - v1->bo = ssi_eval_expr_cmp_bool(v1, &v2, cond); - v1->type = SSI_TYPE_BOOL; - } while (next == TK_AND || next == TK_OR); - buffer_free(v2.str); - return next; -} - -int ssi_eval_expr(handler_ctx *p, const char *expr) { - ssi_tokenizer_t t; - t.input = expr; - t.offset = 0; - t.size = strlen(expr); - t.in_brace = 0; - t.depth = 0; - t.p = p; - - ssi_val_t v = { SSI_TYPE_UNSET, NULL, 0 }; - v.str = buffer_init(); - int rc = ssi_eval_expr_loop(&t, &v); - rc = (0 == rc && 0 == t.in_brace && 0 == t.depth) - ? ssi_val_tobool(&v) - : -1; - buffer_free(v.str); - - return rc; -} diff --git a/src/t/test_mod_ssi.c b/src/t/test_mod_ssi.c index 75904a72..7c64dd02 100644 --- a/src/t/test_mod_ssi.c +++ b/src/t/test_mod_ssi.c @@ -8,7 +8,6 @@ #include <unistd.h> #include "mod_ssi.c" -#include "mod_ssi_expr.c" #include "fdlog.h" static void test_mod_ssi_reset (request_st * const r, handler_ctx * const hctx) |