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