diff options
Diffstat (limited to 'data/lighttpd/lighttpd-1.4.53/src/mod_ssi_expr.c')
-rw-r--r-- | data/lighttpd/lighttpd-1.4.53/src/mod_ssi_expr.c | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/data/lighttpd/lighttpd-1.4.53/src/mod_ssi_expr.c b/data/lighttpd/lighttpd-1.4.53/src/mod_ssi_expr.c new file mode 100644 index 000000000..04e388988 --- /dev/null +++ b/data/lighttpd/lighttpd-1.4.53/src/mod_ssi_expr.c @@ -0,0 +1,330 @@ +#include "first.h" + +#include "buffer.h" +#include "log.h" +#include "mod_ssi.h" +#include "mod_ssi_expr.h" +#include "mod_ssi_exprparser.h" + +#include <ctype.h> +#include <stdlib.h> +#include <string.h> + +typedef struct { + const char *input; + size_t offset; + size_t size; + + int line_pos; + + int in_key; + int in_brace; + int in_cond; +} ssi_tokenizer_t; + +ssi_val_t *ssi_val_init(void) { + ssi_val_t *s; + + s = calloc(1, sizeof(*s)); + + return s; +} + +void ssi_val_free(ssi_val_t *s) { + if (s->str) buffer_free(s->str); + + free(s); +} + +int ssi_val_tobool(ssi_val_t *B) { + if (B->type == SSI_TYPE_STRING) { + return !buffer_string_is_empty(B->str); + } else { + return B->bo; + } +} + +static int ssi_expr_tokenizer(server *srv, connection *con, handler_ctx *p, + ssi_tokenizer_t *t, int *token_id, buffer *token) { + int tid = 0; + size_t i; + + UNUSED(con); + + for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) { + char c = t->input[t->offset]; + data_string *ds; + + switch (c) { + case '=': + tid = TK_EQ; + + t->offset++; + t->line_pos++; + + buffer_copy_string_len(token, CONST_STR_LEN("(=)")); + + break; + case '>': + if (t->input[t->offset + 1] == '=') { + t->offset += 2; + t->line_pos += 2; + + tid = TK_GE; + + buffer_copy_string_len(token, CONST_STR_LEN("(>=)")); + } else { + t->offset += 1; + t->line_pos += 1; + + tid = TK_GT; + + buffer_copy_string_len(token, CONST_STR_LEN("(>)")); + } + + break; + case '<': + if (t->input[t->offset + 1] == '=') { + t->offset += 2; + t->line_pos += 2; + + tid = TK_LE; + + buffer_copy_string_len(token, CONST_STR_LEN("(<=)")); + } else { + t->offset += 1; + t->line_pos += 1; + + tid = TK_LT; + + buffer_copy_string_len(token, CONST_STR_LEN("(<)")); + } + + break; + + case '!': + if (t->input[t->offset + 1] == '=') { + t->offset += 2; + t->line_pos += 2; + + tid = TK_NE; + + buffer_copy_string_len(token, CONST_STR_LEN("(!=)")); + } else { + t->offset += 1; + t->line_pos += 1; + + tid = TK_NOT; + + buffer_copy_string_len(token, CONST_STR_LEN("(!)")); + } + + break; + case '&': + if (t->input[t->offset + 1] == '&') { + t->offset += 2; + t->line_pos += 2; + + tid = TK_AND; + + buffer_copy_string_len(token, CONST_STR_LEN("(&&)")); + } else { + log_error_write(srv, __FILE__, __LINE__, "sds", + "pos:", t->line_pos, + "missing second &"); + return -1; + } + + break; + case '|': + if (t->input[t->offset + 1] == '|') { + t->offset += 2; + t->line_pos += 2; + + tid = TK_OR; + + buffer_copy_string_len(token, CONST_STR_LEN("(||)")); + } else { + log_error_write(srv, __FILE__, __LINE__, "sds", + "pos:", t->line_pos, + "missing second |"); + return -1; + } + + break; + case '\t': + case ' ': + t->offset++; + t->line_pos++; + break; + + 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]) { + tid = TK_VALUE; + + buffer_copy_string_len(token, t->input + t->offset + 1, i-1); + + t->offset += i + 1; + t->line_pos += i + 1; + } else { + /* ERROR */ + + log_error_write(srv, __FILE__, __LINE__, "sds", + "pos:", t->line_pos, + "missing closing quote"); + + return -1; + } + + break; + case '(': + t->offset++; + t->in_brace++; + + tid = TK_LPARAN; + + buffer_copy_string_len(token, CONST_STR_LEN("(")); + break; + case ')': + t->offset++; + t->in_brace--; + + tid = TK_RPARAN; + + buffer_copy_string_len(token, CONST_STR_LEN(")")); + break; + case '$': + 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_write(srv, __FILE__, __LINE__, "sds", + "pos:", t->line_pos, + "missing closing quote"); + + return -1; + } + + buffer_copy_string_len(token, t->input + t->offset + 2, i-3); + } else { + for (i = 1; isalpha(t->input[t->offset + i]) || + t->input[t->offset + i] == '_' || + ((i > 1) && isdigit(t->input[t->offset + i])); i++); + + buffer_copy_string_len(token, t->input + t->offset + 1, i-1); + } + + tid = TK_VALUE; + + if (NULL != (ds = (data_string *)array_get_element_klen(p->ssi_cgi_env, CONST_BUF_LEN(token)))) { + buffer_copy_buffer(token, ds->value); + } else if (NULL != (ds = (data_string *)array_get_element_klen(p->ssi_vars, CONST_BUF_LEN(token)))) { + buffer_copy_buffer(token, ds->value); + } else { + buffer_copy_string_len(token, CONST_STR_LEN("")); + } + + t->offset += i; + t->line_pos += i; + + break; + default: + for (i = 0; isgraph(t->input[t->offset + i]); i++) { + char d = t->input[t->offset + i]; + switch(d) { + case ' ': + case '\t': + case ')': + case '(': + case '\'': + case '=': + case '!': + case '<': + case '>': + case '&': + case '|': + break; + } + } + + tid = TK_VALUE; + + buffer_copy_string_len(token, t->input + t->offset, i); + + t->offset += i; + t->line_pos += i; + + break; + } + } + + if (tid) { + *token_id = tid; + + return 1; + } else if (t->offset < t->size) { + log_error_write(srv, __FILE__, __LINE__, "sds", + "pos:", t->line_pos, + "foobar"); + } + return 0; +} + +int ssi_eval_expr(server *srv, connection *con, handler_ctx *p, const char *expr) { + ssi_tokenizer_t t; + void *pParser; + int token_id; + buffer *token; + ssi_ctx_t context; + int ret; + + t.input = expr; + t.offset = 0; + t.size = strlen(expr); + t.line_pos = 1; + + t.in_key = 1; + t.in_brace = 0; + t.in_cond = 0; + + context.ok = 1; + context.srv = srv; + + /* default context */ + + pParser = ssiexprparserAlloc( malloc ); + force_assert(pParser); + token = buffer_init(); + while((1 == (ret = ssi_expr_tokenizer(srv, con, p, &t, &token_id, token))) && context.ok) { + ssiexprparser(pParser, token_id, token, &context); + + token = buffer_init(); + } + ssiexprparser(pParser, 0, token, &context); + ssiexprparserFree(pParser, free ); + + buffer_free(token); + + if (ret == -1) { + log_error_write(srv, __FILE__, __LINE__, "s", + "expr parser failed"); + return -1; + } + + if (context.ok == 0) { + log_error_write(srv, __FILE__, __LINE__, "sds", + "pos:", t.line_pos, + "parser failed somehow near here"); + return -1; + } +#if 0 + log_error_write(srv, __FILE__, __LINE__, "ssd", + "expr: ", + expr, + context.val.bo); +#endif + return context.val.bo; +} |