• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/lighttpd-1.4.39/src/
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
10typedef 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
22ssi_val_t *ssi_val_init(void) {
23	ssi_val_t *s;
24
25	s = calloc(1, sizeof(*s));
26
27	return s;
28}
29
30void ssi_val_free(ssi_val_t *s) {
31	if (s->str) buffer_free(s->str);
32
33	free(s);
34}
35
36int ssi_val_tobool(ssi_val_t *B) {
37	if (B->type == SSI_TYPE_STRING) {
38		return !buffer_string_is_empty(B->str);
39	} else {
40		return B->bo;
41	}
42}
43
44static 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_buffer(token, ds->value);
219			} else if (NULL != (ds = (data_string *)array_get_element(p->ssi_vars, token->ptr))) {
220				buffer_copy_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
271int 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	force_assert(pParser);
295	token = buffer_init();
296	while((1 == (ret = ssi_expr_tokenizer(srv, con, p, &t, &token_id, token))) && context.ok) {
297		ssiexprparser(pParser, token_id, token, &context);
298
299		token = buffer_init();
300	}
301	ssiexprparser(pParser, 0, token, &context);
302	ssiexprparserFree(pParser, free );
303
304	buffer_free(token);
305
306	if (ret == -1) {
307		log_error_write(srv, __FILE__, __LINE__, "s",
308				"expr parser failed");
309		return -1;
310	}
311
312	if (context.ok == 0) {
313		log_error_write(srv, __FILE__, __LINE__, "sds",
314				"pos:", t.line_pos,
315				"parser failed somehow near here");
316		return -1;
317	}
318#if 0
319	log_error_write(srv, __FILE__, __LINE__, "ssd",
320			"expr: ",
321			expr,
322			context.val.bo);
323#endif
324	return context.val.bo;
325}
326