Annotation of embedaddon/lighttpd/src/mod_ssi_expr.c, revision 1.1.1.2
1.1.1.2 ! misho 1: #include "first.h"
! 2:
1.1 misho 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) {
1.1.1.2 ! misho 40: return !buffer_string_is_empty(B->str);
1.1 misho 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 {
1.1.1.2 ! misho 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++);
1.1 misho 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))) {
1.1.1.2 ! misho 222: buffer_copy_buffer(token, ds->value);
1.1 misho 223: } else if (NULL != (ds = (data_string *)array_get_element(p->ssi_vars, token->ptr))) {
1.1.1.2 ! misho 224: buffer_copy_buffer(token, ds->value);
1.1 misho 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 );
1.1.1.2 ! misho 298: force_assert(pParser);
1.1 misho 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>