summaryrefslogtreecommitdiff
path: root/data/lighttpd/lighttpd-1.4.53/src/mod_ssi_expr.c
diff options
context:
space:
mode:
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.c330
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;
+}