[mod_cgi] fix pipe_cloexec() when no O_CLOEXEC
[lighttpd.git] / src / mod_ssi_expr.c
blob60e97cc3cac0ec3442deb5623d5f3cd9da85fd0b
1 #include "first.h"
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"
9 #include <ctype.h>
10 #include <string.h>
12 typedef struct {
13 const char *input;
14 size_t offset;
15 size_t size;
17 int line_pos;
19 int in_key;
20 int in_brace;
21 int in_cond;
22 } ssi_tokenizer_t;
24 ssi_val_t *ssi_val_init(void) {
25 ssi_val_t *s;
27 s = calloc(1, sizeof(*s));
29 return s;
32 void ssi_val_free(ssi_val_t *s) {
33 if (s->str) buffer_free(s->str);
35 free(s);
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;
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;
51 UNUSED(con);
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;
57 switch (c) {
58 case '=':
59 tid = TK_EQ;
61 t->offset++;
62 t->line_pos++;
64 buffer_copy_string_len(token, CONST_STR_LEN("(=)"));
66 break;
67 case '>':
68 if (t->input[t->offset + 1] == '=') {
69 t->offset += 2;
70 t->line_pos += 2;
72 tid = TK_GE;
74 buffer_copy_string_len(token, CONST_STR_LEN("(>=)"));
75 } else {
76 t->offset += 1;
77 t->line_pos += 1;
79 tid = TK_GT;
81 buffer_copy_string_len(token, CONST_STR_LEN("(>)"));
84 break;
85 case '<':
86 if (t->input[t->offset + 1] == '=') {
87 t->offset += 2;
88 t->line_pos += 2;
90 tid = TK_LE;
92 buffer_copy_string_len(token, CONST_STR_LEN("(<=)"));
93 } else {
94 t->offset += 1;
95 t->line_pos += 1;
97 tid = TK_LT;
99 buffer_copy_string_len(token, CONST_STR_LEN("(<)"));
102 break;
104 case '!':
105 if (t->input[t->offset + 1] == '=') {
106 t->offset += 2;
107 t->line_pos += 2;
109 tid = TK_NE;
111 buffer_copy_string_len(token, CONST_STR_LEN("(!=)"));
112 } else {
113 t->offset += 1;
114 t->line_pos += 1;
116 tid = TK_NOT;
118 buffer_copy_string_len(token, CONST_STR_LEN("(!)"));
121 break;
122 case '&':
123 if (t->input[t->offset + 1] == '&') {
124 t->offset += 2;
125 t->line_pos += 2;
127 tid = TK_AND;
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;
137 break;
138 case '|':
139 if (t->input[t->offset + 1] == '|') {
140 t->offset += 2;
141 t->line_pos += 2;
143 tid = TK_OR;
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;
153 break;
154 case '\t':
155 case ' ':
156 t->offset++;
157 t->line_pos++;
158 break;
160 case '\'':
161 /* search for the terminating " */
162 for (i = 1; t->input[t->offset + i] && t->input[t->offset + i] != '\''; i++);
164 if (t->input[t->offset + i]) {
165 tid = TK_VALUE;
167 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
169 t->offset += i + 1;
170 t->line_pos += i + 1;
171 } else {
172 /* ERROR */
174 log_error_write(srv, __FILE__, __LINE__, "sds",
175 "pos:", t->line_pos,
176 "missing closing quote");
178 return -1;
181 break;
182 case '(':
183 t->offset++;
184 t->in_brace++;
186 tid = TK_LPARAN;
188 buffer_copy_string_len(token, CONST_STR_LEN("("));
189 break;
190 case ')':
191 t->offset++;
192 t->in_brace--;
194 tid = TK_RPARAN;
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++);
202 if (t->input[t->offset + i] != '}') {
203 log_error_write(srv, __FILE__, __LINE__, "sds",
204 "pos:", t->line_pos,
205 "missing closing quote");
207 return -1;
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++);
216 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
219 tid = TK_VALUE;
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(""));
229 t->offset += i;
230 t->line_pos += i;
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;
252 tid = TK_VALUE;
254 buffer_copy_string_len(token, t->input + t->offset, i);
256 t->offset += i;
257 t->line_pos += i;
259 break;
263 if (tid) {
264 *token_id = tid;
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");
272 return 0;
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;
283 t.input = expr;
284 t.offset = 0;
285 t.size = strlen(expr);
286 t.line_pos = 1;
288 t.in_key = 1;
289 t.in_brace = 0;
290 t.in_cond = 0;
292 context.ok = 1;
293 context.srv = srv;
295 /* default context */
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);
303 token = buffer_init();
305 ssiexprparser(pParser, 0, token, &context);
306 ssiexprparserFree(pParser, free );
308 buffer_free(token);
310 if (ret == -1) {
311 log_error_write(srv, __FILE__, __LINE__, "s",
312 "expr parser failed");
313 return -1;
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;
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;