[mod_auth] require digest uri= match original URI
[lighttpd.git] / src / mod_ssi_expr.c
blob04e38898880bc03623f560333dbc83e0d4dfe191
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 <stdlib.h>
11 #include <string.h>
13 typedef struct {
14 const char *input;
15 size_t offset;
16 size_t size;
18 int line_pos;
20 int in_key;
21 int in_brace;
22 int in_cond;
23 } ssi_tokenizer_t;
25 ssi_val_t *ssi_val_init(void) {
26 ssi_val_t *s;
28 s = calloc(1, sizeof(*s));
30 return s;
33 void ssi_val_free(ssi_val_t *s) {
34 if (s->str) buffer_free(s->str);
36 free(s);
39 int ssi_val_tobool(ssi_val_t *B) {
40 if (B->type == SSI_TYPE_STRING) {
41 return !buffer_string_is_empty(B->str);
42 } else {
43 return B->bo;
47 static int ssi_expr_tokenizer(server *srv, connection *con, handler_ctx *p,
48 ssi_tokenizer_t *t, int *token_id, buffer *token) {
49 int tid = 0;
50 size_t i;
52 UNUSED(con);
54 for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
55 char c = t->input[t->offset];
56 data_string *ds;
58 switch (c) {
59 case '=':
60 tid = TK_EQ;
62 t->offset++;
63 t->line_pos++;
65 buffer_copy_string_len(token, CONST_STR_LEN("(=)"));
67 break;
68 case '>':
69 if (t->input[t->offset + 1] == '=') {
70 t->offset += 2;
71 t->line_pos += 2;
73 tid = TK_GE;
75 buffer_copy_string_len(token, CONST_STR_LEN("(>=)"));
76 } else {
77 t->offset += 1;
78 t->line_pos += 1;
80 tid = TK_GT;
82 buffer_copy_string_len(token, CONST_STR_LEN("(>)"));
85 break;
86 case '<':
87 if (t->input[t->offset + 1] == '=') {
88 t->offset += 2;
89 t->line_pos += 2;
91 tid = TK_LE;
93 buffer_copy_string_len(token, CONST_STR_LEN("(<=)"));
94 } else {
95 t->offset += 1;
96 t->line_pos += 1;
98 tid = TK_LT;
100 buffer_copy_string_len(token, CONST_STR_LEN("(<)"));
103 break;
105 case '!':
106 if (t->input[t->offset + 1] == '=') {
107 t->offset += 2;
108 t->line_pos += 2;
110 tid = TK_NE;
112 buffer_copy_string_len(token, CONST_STR_LEN("(!=)"));
113 } else {
114 t->offset += 1;
115 t->line_pos += 1;
117 tid = TK_NOT;
119 buffer_copy_string_len(token, CONST_STR_LEN("(!)"));
122 break;
123 case '&':
124 if (t->input[t->offset + 1] == '&') {
125 t->offset += 2;
126 t->line_pos += 2;
128 tid = TK_AND;
130 buffer_copy_string_len(token, CONST_STR_LEN("(&&)"));
131 } else {
132 log_error_write(srv, __FILE__, __LINE__, "sds",
133 "pos:", t->line_pos,
134 "missing second &");
135 return -1;
138 break;
139 case '|':
140 if (t->input[t->offset + 1] == '|') {
141 t->offset += 2;
142 t->line_pos += 2;
144 tid = TK_OR;
146 buffer_copy_string_len(token, CONST_STR_LEN("(||)"));
147 } else {
148 log_error_write(srv, __FILE__, __LINE__, "sds",
149 "pos:", t->line_pos,
150 "missing second |");
151 return -1;
154 break;
155 case '\t':
156 case ' ':
157 t->offset++;
158 t->line_pos++;
159 break;
161 case '\'':
162 /* search for the terminating " */
163 for (i = 1; t->input[t->offset + i] && t->input[t->offset + i] != '\''; i++);
165 if (t->input[t->offset + i]) {
166 tid = TK_VALUE;
168 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
170 t->offset += i + 1;
171 t->line_pos += i + 1;
172 } else {
173 /* ERROR */
175 log_error_write(srv, __FILE__, __LINE__, "sds",
176 "pos:", t->line_pos,
177 "missing closing quote");
179 return -1;
182 break;
183 case '(':
184 t->offset++;
185 t->in_brace++;
187 tid = TK_LPARAN;
189 buffer_copy_string_len(token, CONST_STR_LEN("("));
190 break;
191 case ')':
192 t->offset++;
193 t->in_brace--;
195 tid = TK_RPARAN;
197 buffer_copy_string_len(token, CONST_STR_LEN(")"));
198 break;
199 case '$':
200 if (t->input[t->offset + 1] == '{') {
201 for (i = 2; t->input[t->offset + i] && t->input[t->offset + i] != '}'; i++);
203 if (t->input[t->offset + i] != '}') {
204 log_error_write(srv, __FILE__, __LINE__, "sds",
205 "pos:", t->line_pos,
206 "missing closing quote");
208 return -1;
211 buffer_copy_string_len(token, t->input + t->offset + 2, i-3);
212 } else {
213 for (i = 1; isalpha(t->input[t->offset + i]) ||
214 t->input[t->offset + i] == '_' ||
215 ((i > 1) && isdigit(t->input[t->offset + i])); i++);
217 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
220 tid = TK_VALUE;
222 if (NULL != (ds = (data_string *)array_get_element_klen(p->ssi_cgi_env, CONST_BUF_LEN(token)))) {
223 buffer_copy_buffer(token, ds->value);
224 } else if (NULL != (ds = (data_string *)array_get_element_klen(p->ssi_vars, CONST_BUF_LEN(token)))) {
225 buffer_copy_buffer(token, ds->value);
226 } else {
227 buffer_copy_string_len(token, CONST_STR_LEN(""));
230 t->offset += i;
231 t->line_pos += i;
233 break;
234 default:
235 for (i = 0; isgraph(t->input[t->offset + i]); i++) {
236 char d = t->input[t->offset + i];
237 switch(d) {
238 case ' ':
239 case '\t':
240 case ')':
241 case '(':
242 case '\'':
243 case '=':
244 case '!':
245 case '<':
246 case '>':
247 case '&':
248 case '|':
249 break;
253 tid = TK_VALUE;
255 buffer_copy_string_len(token, t->input + t->offset, i);
257 t->offset += i;
258 t->line_pos += i;
260 break;
264 if (tid) {
265 *token_id = tid;
267 return 1;
268 } else if (t->offset < t->size) {
269 log_error_write(srv, __FILE__, __LINE__, "sds",
270 "pos:", t->line_pos,
271 "foobar");
273 return 0;
276 int ssi_eval_expr(server *srv, connection *con, handler_ctx *p, const char *expr) {
277 ssi_tokenizer_t t;
278 void *pParser;
279 int token_id;
280 buffer *token;
281 ssi_ctx_t context;
282 int ret;
284 t.input = expr;
285 t.offset = 0;
286 t.size = strlen(expr);
287 t.line_pos = 1;
289 t.in_key = 1;
290 t.in_brace = 0;
291 t.in_cond = 0;
293 context.ok = 1;
294 context.srv = srv;
296 /* default context */
298 pParser = ssiexprparserAlloc( malloc );
299 force_assert(pParser);
300 token = buffer_init();
301 while((1 == (ret = ssi_expr_tokenizer(srv, con, p, &t, &token_id, token))) && context.ok) {
302 ssiexprparser(pParser, token_id, token, &context);
304 token = buffer_init();
306 ssiexprparser(pParser, 0, token, &context);
307 ssiexprparserFree(pParser, free );
309 buffer_free(token);
311 if (ret == -1) {
312 log_error_write(srv, __FILE__, __LINE__, "s",
313 "expr parser failed");
314 return -1;
317 if (context.ok == 0) {
318 log_error_write(srv, __FILE__, __LINE__, "sds",
319 "pos:", t.line_pos,
320 "parser failed somehow near here");
321 return -1;
323 #if 0
324 log_error_write(srv, __FILE__, __LINE__, "ssd",
325 "expr: ",
326 expr,
327 context.val.bo);
328 #endif
329 return context.val.bo;