File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lighttpd / src / mod_ssi_expr.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:35:00 2016 UTC (7 years, 7 months ago) by misho
Branches: lighttpd, MAIN
CVS tags: v1_4_41p8, HEAD
lighttpd 1.4.41

    1: #include "first.h"
    2: 
    3: #include "buffer.h"
    4: #include "log.h"
    5: #include "mod_ssi.h"
    6: #include "mod_ssi_expr.h"
    7: #include "mod_ssi_exprparser.h"
    8: 
    9: #include <ctype.h>
   10: #include <string.h>
   11: 
   12: typedef struct {
   13: 	const char *input;
   14: 	size_t offset;
   15: 	size_t size;
   16: 
   17: 	int line_pos;
   18: 
   19: 	int in_key;
   20: 	int in_brace;
   21: 	int in_cond;
   22: } ssi_tokenizer_t;
   23: 
   24: ssi_val_t *ssi_val_init(void) {
   25: 	ssi_val_t *s;
   26: 
   27: 	s = calloc(1, sizeof(*s));
   28: 
   29: 	return s;
   30: }
   31: 
   32: void ssi_val_free(ssi_val_t *s) {
   33: 	if (s->str) buffer_free(s->str);
   34: 
   35: 	free(s);
   36: }
   37: 
   38: int ssi_val_tobool(ssi_val_t *B) {
   39: 	if (B->type == SSI_TYPE_STRING) {
   40: 		return !buffer_string_is_empty(B->str);
   41: 	} else {
   42: 		return B->bo;
   43: 	}
   44: }
   45: 
   46: static int ssi_expr_tokenizer(server *srv, connection *con, plugin_data *p,
   47: 			      ssi_tokenizer_t *t, int *token_id, buffer *token) {
   48: 	int tid = 0;
   49: 	size_t i;
   50: 
   51: 	UNUSED(con);
   52: 
   53: 	for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
   54: 		char c = t->input[t->offset];
   55: 		data_string *ds;
   56: 
   57: 		switch (c) {
   58: 		case '=':
   59: 			tid = TK_EQ;
   60: 
   61: 			t->offset++;
   62: 			t->line_pos++;
   63: 
   64: 			buffer_copy_string_len(token, CONST_STR_LEN("(=)"));
   65: 
   66: 			break;
   67: 		case '>':
   68: 			if (t->input[t->offset + 1] == '=') {
   69: 				t->offset += 2;
   70: 				t->line_pos += 2;
   71: 
   72: 				tid = TK_GE;
   73: 
   74: 				buffer_copy_string_len(token, CONST_STR_LEN("(>=)"));
   75: 			} else {
   76: 				t->offset += 1;
   77: 				t->line_pos += 1;
   78: 
   79: 				tid = TK_GT;
   80: 
   81: 				buffer_copy_string_len(token, CONST_STR_LEN("(>)"));
   82: 			}
   83: 
   84: 			break;
   85: 		case '<':
   86: 			if (t->input[t->offset + 1] == '=') {
   87: 				t->offset += 2;
   88: 				t->line_pos += 2;
   89: 
   90: 				tid = TK_LE;
   91: 
   92: 				buffer_copy_string_len(token, CONST_STR_LEN("(<=)"));
   93: 			} else {
   94: 				t->offset += 1;
   95: 				t->line_pos += 1;
   96: 
   97: 				tid = TK_LT;
   98: 
   99: 				buffer_copy_string_len(token, CONST_STR_LEN("(<)"));
  100: 			}
  101: 
  102: 			break;
  103: 
  104: 		case '!':
  105: 			if (t->input[t->offset + 1] == '=') {
  106: 				t->offset += 2;
  107: 				t->line_pos += 2;
  108: 
  109: 				tid = TK_NE;
  110: 
  111: 				buffer_copy_string_len(token, CONST_STR_LEN("(!=)"));
  112: 			} else {
  113: 				t->offset += 1;
  114: 				t->line_pos += 1;
  115: 
  116: 				tid = TK_NOT;
  117: 
  118: 				buffer_copy_string_len(token, CONST_STR_LEN("(!)"));
  119: 			}
  120: 
  121: 			break;
  122: 		case '&':
  123: 			if (t->input[t->offset + 1] == '&') {
  124: 				t->offset += 2;
  125: 				t->line_pos += 2;
  126: 
  127: 				tid = TK_AND;
  128: 
  129: 				buffer_copy_string_len(token, CONST_STR_LEN("(&&)"));
  130: 			} else {
  131: 				log_error_write(srv, __FILE__, __LINE__, "sds",
  132: 						"pos:", t->line_pos,
  133: 						"missing second &");
  134: 				return -1;
  135: 			}
  136: 
  137: 			break;
  138: 		case '|':
  139: 			if (t->input[t->offset + 1] == '|') {
  140: 				t->offset += 2;
  141: 				t->line_pos += 2;
  142: 
  143: 				tid = TK_OR;
  144: 
  145: 				buffer_copy_string_len(token, CONST_STR_LEN("(||)"));
  146: 			} else {
  147: 				log_error_write(srv, __FILE__, __LINE__, "sds",
  148: 						"pos:", t->line_pos,
  149: 						"missing second |");
  150: 				return -1;
  151: 			}
  152: 
  153: 			break;
  154: 		case '\t':
  155: 		case ' ':
  156: 			t->offset++;
  157: 			t->line_pos++;
  158: 			break;
  159: 
  160: 		case '\'':
  161: 			/* search for the terminating " */
  162: 			for (i = 1; t->input[t->offset + i] && t->input[t->offset + i] != '\'';  i++);
  163: 
  164: 			if (t->input[t->offset + i]) {
  165: 				tid = TK_VALUE;
  166: 
  167: 				buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
  168: 
  169: 				t->offset += i + 1;
  170: 				t->line_pos += i + 1;
  171: 			} else {
  172: 				/* ERROR */
  173: 
  174: 				log_error_write(srv, __FILE__, __LINE__, "sds",
  175: 						"pos:", t->line_pos,
  176: 						"missing closing quote");
  177: 
  178: 				return -1;
  179: 			}
  180: 
  181: 			break;
  182: 		case '(':
  183: 			t->offset++;
  184: 			t->in_brace++;
  185: 
  186: 			tid = TK_LPARAN;
  187: 
  188: 			buffer_copy_string_len(token, CONST_STR_LEN("("));
  189: 			break;
  190: 		case ')':
  191: 			t->offset++;
  192: 			t->in_brace--;
  193: 
  194: 			tid = TK_RPARAN;
  195: 
  196: 			buffer_copy_string_len(token, CONST_STR_LEN(")"));
  197: 			break;
  198: 		case '$':
  199: 			if (t->input[t->offset + 1] == '{') {
  200: 				for (i = 2; t->input[t->offset + i] && t->input[t->offset + i] != '}';  i++);
  201: 
  202: 				if (t->input[t->offset + i] != '}') {
  203: 					log_error_write(srv, __FILE__, __LINE__, "sds",
  204: 							"pos:", t->line_pos,
  205: 							"missing closing quote");
  206: 
  207: 					return -1;
  208: 				}
  209: 
  210: 				buffer_copy_string_len(token, t->input + t->offset + 2, i-3);
  211: 			} else {
  212: 				for (i = 1; isalpha(t->input[t->offset + i]) ||
  213: 					    t->input[t->offset + i] == '_' ||
  214: 					    ((i > 1) && isdigit(t->input[t->offset + i]));  i++);
  215: 
  216: 				buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
  217: 			}
  218: 
  219: 			tid = TK_VALUE;
  220: 
  221: 			if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, token->ptr))) {
  222: 				buffer_copy_buffer(token, ds->value);
  223: 			} else if (NULL != (ds = (data_string *)array_get_element(p->ssi_vars, token->ptr))) {
  224: 				buffer_copy_buffer(token, ds->value);
  225: 			} else {
  226: 				buffer_copy_string_len(token, CONST_STR_LEN(""));
  227: 			}
  228: 
  229: 			t->offset += i;
  230: 			t->line_pos += i;
  231: 
  232: 			break;
  233: 		default:
  234: 			for (i = 0; isgraph(t->input[t->offset + i]);  i++) {
  235: 				char d = t->input[t->offset + i];
  236: 				switch(d) {
  237: 				case ' ':
  238: 				case '\t':
  239: 				case ')':
  240: 				case '(':
  241: 				case '\'':
  242: 				case '=':
  243: 				case '!':
  244: 				case '<':
  245: 				case '>':
  246: 				case '&':
  247: 				case '|':
  248: 					break;
  249: 				}
  250: 			}
  251: 
  252: 			tid = TK_VALUE;
  253: 
  254: 			buffer_copy_string_len(token, t->input + t->offset, i);
  255: 
  256: 			t->offset += i;
  257: 			t->line_pos += i;
  258: 
  259: 			break;
  260: 		}
  261: 	}
  262: 
  263: 	if (tid) {
  264: 		*token_id = tid;
  265: 
  266: 		return 1;
  267: 	} else if (t->offset < t->size) {
  268: 		log_error_write(srv, __FILE__, __LINE__, "sds",
  269: 				"pos:", t->line_pos,
  270: 				"foobar");
  271: 	}
  272: 	return 0;
  273: }
  274: 
  275: int ssi_eval_expr(server *srv, connection *con, plugin_data *p, const char *expr) {
  276: 	ssi_tokenizer_t t;
  277: 	void *pParser;
  278: 	int token_id;
  279: 	buffer *token;
  280: 	ssi_ctx_t context;
  281: 	int ret;
  282: 
  283: 	t.input = expr;
  284: 	t.offset = 0;
  285: 	t.size = strlen(expr);
  286: 	t.line_pos = 1;
  287: 
  288: 	t.in_key = 1;
  289: 	t.in_brace = 0;
  290: 	t.in_cond = 0;
  291: 
  292: 	context.ok = 1;
  293: 	context.srv = srv;
  294: 
  295: 	/* default context */
  296: 
  297: 	pParser = ssiexprparserAlloc( malloc );
  298: 	force_assert(pParser);
  299: 	token = buffer_init();
  300: 	while((1 == (ret = ssi_expr_tokenizer(srv, con, p, &t, &token_id, token))) && context.ok) {
  301: 		ssiexprparser(pParser, token_id, token, &context);
  302: 
  303: 		token = buffer_init();
  304: 	}
  305: 	ssiexprparser(pParser, 0, token, &context);
  306: 	ssiexprparserFree(pParser, free );
  307: 
  308: 	buffer_free(token);
  309: 
  310: 	if (ret == -1) {
  311: 		log_error_write(srv, __FILE__, __LINE__, "s",
  312: 				"expr parser failed");
  313: 		return -1;
  314: 	}
  315: 
  316: 	if (context.ok == 0) {
  317: 		log_error_write(srv, __FILE__, __LINE__, "sds",
  318: 				"pos:", t.line_pos,
  319: 				"parser failed somehow near here");
  320: 		return -1;
  321: 	}
  322: #if 0
  323: 	log_error_write(srv, __FILE__, __LINE__, "ssd",
  324: 			"expr: ",
  325: 			expr,
  326: 			context.val.bo);
  327: #endif
  328: 	return context.val.bo;
  329: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>