Annotation of embedaddon/lighttpd/src/mod_ssi_expr.c, revision 1.1.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>