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