1 | /* Generated by re2c 0.13.5 */ |
2 | /* |
3 | +----------------------------------------------------------------------+ |
4 | | PHP Version 5 | |
5 | +----------------------------------------------------------------------+ |
6 | | Copyright (c) 1997-2015 The PHP Group | |
7 | +----------------------------------------------------------------------+ |
8 | | This source file is subject to version 3.01 of the PHP license, | |
9 | | that is bundled with this package in the file LICENSE, and is | |
10 | | available through the world-wide-web at the following url: | |
11 | | http://www.php.net/license/3_01.txt | |
12 | | If you did not receive a copy of the PHP license and are unable to | |
13 | | obtain it through the world-wide-web, please send a note to | |
14 | | license@php.net so we can mail you a copy immediately. | |
15 | +----------------------------------------------------------------------+ |
16 | | Author: Sascha Schumann <sascha@schumann.cx> | |
17 | +----------------------------------------------------------------------+ |
18 | */ |
19 | |
20 | /* $Id$ */ |
21 | |
22 | #include "php.h" |
23 | |
24 | #ifdef HAVE_UNISTD_H |
25 | #include <unistd.h> |
26 | #endif |
27 | #ifdef HAVE_LIMITS_H |
28 | #include <limits.h> |
29 | #endif |
30 | |
31 | #include <stdio.h> |
32 | #include <stdlib.h> |
33 | #include <string.h> |
34 | |
35 | #include "php_ini.h" |
36 | #include "php_globals.h" |
37 | #define STATE_TAG SOME_OTHER_STATE_TAG |
38 | #include "basic_functions.h" |
39 | #include "url.h" |
40 | #undef STATE_TAG |
41 | |
42 | #define url_scanner url_scanner_ex |
43 | |
44 | #include "php_smart_str.h" |
45 | |
46 | static PHP_INI_MH(OnUpdateTags) |
47 | { |
48 | url_adapt_state_ex_t *ctx; |
49 | char *key; |
50 | char *lasts; |
51 | char *tmp; |
52 | |
53 | ctx = &BG(url_adapt_state_ex); |
54 | |
55 | tmp = estrndup(new_value, new_value_length); |
56 | |
57 | if (ctx->tags) |
58 | zend_hash_destroy(ctx->tags); |
59 | else { |
60 | ctx->tags = malloc(sizeof(HashTable)); |
61 | if (!ctx->tags) { |
62 | return FAILURE; |
63 | } |
64 | } |
65 | |
66 | zend_hash_init(ctx->tags, 0, NULL, NULL, 1); |
67 | |
68 | for (key = php_strtok_r(tmp, "," , &lasts); |
69 | key; |
70 | key = php_strtok_r(NULL, "," , &lasts)) { |
71 | char *val; |
72 | |
73 | val = strchr(key, '='); |
74 | if (val) { |
75 | char *q; |
76 | int keylen; |
77 | |
78 | *val++ = '\0'; |
79 | for (q = key; *q; q++) |
80 | *q = tolower(*q); |
81 | keylen = q - key; |
82 | /* key is stored withOUT NUL |
83 | val is stored WITH NUL */ |
84 | zend_hash_add(ctx->tags, key, keylen, val, strlen(val)+1, NULL); |
85 | } |
86 | } |
87 | |
88 | efree(tmp); |
89 | |
90 | return SUCCESS; |
91 | } |
92 | |
93 | PHP_INI_BEGIN() |
94 | STD_PHP_INI_ENTRY("url_rewriter.tags" , "a=href,area=href,frame=src,form=,fieldset=" , PHP_INI_ALL, OnUpdateTags, url_adapt_state_ex, php_basic_globals, basic_globals) |
95 | PHP_INI_END() |
96 | |
97 | |
98 | |
99 | #define YYFILL(n) goto done |
100 | #define YYCTYPE unsigned char |
101 | #define YYCURSOR p |
102 | #define YYLIMIT q |
103 | #define YYMARKER r |
104 | |
105 | static inline void append_modified_url(smart_str *url, smart_str *dest, smart_str *url_app, const char *separator) |
106 | { |
107 | register const char *p, *q; |
108 | const char *bash = NULL; |
109 | const char *sep = "?" ; |
110 | |
111 | q = (p = url->c) + url->len; |
112 | |
113 | scan: |
114 | |
115 | { |
116 | YYCTYPE yych; |
117 | static const unsigned char yybm[] = { |
118 | 128, 128, 128, 128, 128, 128, 128, 128, |
119 | 128, 128, 128, 128, 128, 128, 128, 128, |
120 | 128, 128, 128, 128, 128, 128, 128, 128, |
121 | 128, 128, 128, 128, 128, 128, 128, 128, |
122 | 128, 128, 128, 0, 128, 128, 128, 128, |
123 | 128, 128, 128, 128, 128, 128, 128, 128, |
124 | 128, 128, 128, 128, 128, 128, 128, 128, |
125 | 128, 128, 0, 128, 128, 128, 128, 0, |
126 | 128, 128, 128, 128, 128, 128, 128, 128, |
127 | 128, 128, 128, 128, 128, 128, 128, 128, |
128 | 128, 128, 128, 128, 128, 128, 128, 128, |
129 | 128, 128, 128, 128, 128, 128, 128, 128, |
130 | 128, 128, 128, 128, 128, 128, 128, 128, |
131 | 128, 128, 128, 128, 128, 128, 128, 128, |
132 | 128, 128, 128, 128, 128, 128, 128, 128, |
133 | 128, 128, 128, 128, 128, 128, 128, 128, |
134 | 128, 128, 128, 128, 128, 128, 128, 128, |
135 | 128, 128, 128, 128, 128, 128, 128, 128, |
136 | 128, 128, 128, 128, 128, 128, 128, 128, |
137 | 128, 128, 128, 128, 128, 128, 128, 128, |
138 | 128, 128, 128, 128, 128, 128, 128, 128, |
139 | 128, 128, 128, 128, 128, 128, 128, 128, |
140 | 128, 128, 128, 128, 128, 128, 128, 128, |
141 | 128, 128, 128, 128, 128, 128, 128, 128, |
142 | 128, 128, 128, 128, 128, 128, 128, 128, |
143 | 128, 128, 128, 128, 128, 128, 128, 128, |
144 | 128, 128, 128, 128, 128, 128, 128, 128, |
145 | 128, 128, 128, 128, 128, 128, 128, 128, |
146 | 128, 128, 128, 128, 128, 128, 128, 128, |
147 | 128, 128, 128, 128, 128, 128, 128, 128, |
148 | 128, 128, 128, 128, 128, 128, 128, 128, |
149 | 128, 128, 128, 128, 128, 128, 128, 128, |
150 | }; |
151 | |
152 | if (YYLIMIT <= YYCURSOR) YYFILL(1); |
153 | yych = *YYCURSOR; |
154 | if (yybm[0+yych] & 128) { |
155 | goto yy8; |
156 | } |
157 | if (yych <= '9') goto yy6; |
158 | if (yych >= ';') goto yy4; |
159 | ++YYCURSOR; |
160 | { smart_str_append(dest, url); return; } |
161 | yy4: |
162 | ++YYCURSOR; |
163 | { sep = separator; goto scan; } |
164 | yy6: |
165 | ++YYCURSOR; |
166 | { bash = p - 1; goto done; } |
167 | yy8: |
168 | ++YYCURSOR; |
169 | if (YYLIMIT <= YYCURSOR) YYFILL(1); |
170 | yych = *YYCURSOR; |
171 | if (yybm[0+yych] & 128) { |
172 | goto yy8; |
173 | } |
174 | { goto scan; } |
175 | } |
176 | |
177 | done: |
178 | |
179 | /* Don't modify URLs of the format "#mark" */ |
180 | if (bash && bash - url->c == 0) { |
181 | smart_str_append(dest, url); |
182 | return; |
183 | } |
184 | |
185 | if (bash) |
186 | smart_str_appendl(dest, url->c, bash - url->c); |
187 | else |
188 | smart_str_append(dest, url); |
189 | |
190 | smart_str_appends(dest, sep); |
191 | smart_str_append(dest, url_app); |
192 | |
193 | if (bash) |
194 | smart_str_appendl(dest, bash, q - bash); |
195 | } |
196 | |
197 | |
198 | #undef YYFILL |
199 | #undef YYCTYPE |
200 | #undef YYCURSOR |
201 | #undef YYLIMIT |
202 | #undef YYMARKER |
203 | |
204 | static inline void tag_arg(url_adapt_state_ex_t *ctx, char quotes, char type TSRMLS_DC) |
205 | { |
206 | char f = 0; |
207 | |
208 | if (strncasecmp(ctx->arg.c, ctx->lookup_data, ctx->arg.len) == 0) |
209 | f = 1; |
210 | |
211 | if (quotes) |
212 | smart_str_appendc(&ctx->result, type); |
213 | if (f) { |
214 | append_modified_url(&ctx->val, &ctx->result, &ctx->url_app, PG(arg_separator).output); |
215 | } else { |
216 | smart_str_append(&ctx->result, &ctx->val); |
217 | } |
218 | if (quotes) |
219 | smart_str_appendc(&ctx->result, type); |
220 | } |
221 | |
222 | enum { |
223 | STATE_PLAIN = 0, |
224 | STATE_TAG, |
225 | STATE_NEXT_ARG, |
226 | STATE_ARG, |
227 | STATE_BEFORE_VAL, |
228 | STATE_VAL |
229 | }; |
230 | |
231 | #define YYFILL(n) goto stop |
232 | #define YYCTYPE unsigned char |
233 | #define YYCURSOR xp |
234 | #define YYLIMIT end |
235 | #define YYMARKER q |
236 | #define STATE ctx->state |
237 | |
238 | #define STD_PARA url_adapt_state_ex_t *ctx, char *start, char *YYCURSOR TSRMLS_DC |
239 | #define STD_ARGS ctx, start, xp TSRMLS_CC |
240 | |
241 | #if SCANNER_DEBUG |
242 | #define scdebug(x) printf x |
243 | #else |
244 | #define scdebug(x) |
245 | #endif |
246 | |
247 | static inline void passthru(STD_PARA) |
248 | { |
249 | scdebug(("appending %d chars, starting with %c\n" , YYCURSOR-start, *start)); |
250 | smart_str_appendl(&ctx->result, start, YYCURSOR - start); |
251 | } |
252 | |
253 | /* |
254 | * This function appends a hidden input field after a <form> or |
255 | * <fieldset>. The latter is important for XHTML. |
256 | */ |
257 | |
258 | static void handle_form(STD_PARA) |
259 | { |
260 | int doit = 0; |
261 | |
262 | if (ctx->form_app.len > 0) { |
263 | switch (ctx->tag.len) { |
264 | case sizeof("form" ) - 1: |
265 | if (!strncasecmp(ctx->tag.c, "form" , sizeof("form" ) - 1)) { |
266 | doit = 1; |
267 | } |
268 | if (doit && ctx->val.c && ctx->lookup_data && *ctx->lookup_data) { |
269 | char *e, *p = zend_memnstr(ctx->val.c, "://" , sizeof("://" ) - 1, ctx->val.c + ctx->val.len); |
270 | if (p) { |
271 | e = memchr(p, '/', (ctx->val.c + ctx->val.len) - p); |
272 | if (!e) { |
273 | e = ctx->val.c + ctx->val.len; |
274 | } |
275 | if ((e - p) && strncasecmp(p, ctx->lookup_data, (e - p))) { |
276 | doit = 0; |
277 | } |
278 | } |
279 | } |
280 | break; |
281 | |
282 | case sizeof("fieldset" ) - 1: |
283 | if (!strncasecmp(ctx->tag.c, "fieldset" , sizeof("fieldset" ) - 1)) { |
284 | doit = 1; |
285 | } |
286 | break; |
287 | } |
288 | |
289 | if (doit) |
290 | smart_str_append(&ctx->result, &ctx->form_app); |
291 | } |
292 | } |
293 | |
294 | /* |
295 | * HANDLE_TAG copies the HTML Tag and checks whether we |
296 | * have that tag in our table. If we might modify it, |
297 | * we continue to scan the tag, otherwise we simply copy the complete |
298 | * HTML stuff to the result buffer. |
299 | */ |
300 | |
301 | static inline void handle_tag(STD_PARA) |
302 | { |
303 | int ok = 0; |
304 | unsigned int i; |
305 | |
306 | ctx->tag.len = 0; |
307 | smart_str_appendl(&ctx->tag, start, YYCURSOR - start); |
308 | for (i = 0; i < ctx->tag.len; i++) |
309 | ctx->tag.c[i] = tolower((int)(unsigned char)ctx->tag.c[i]); |
310 | if (zend_hash_find(ctx->tags, ctx->tag.c, ctx->tag.len, (void **) &ctx->lookup_data) == SUCCESS) |
311 | ok = 1; |
312 | STATE = ok ? STATE_NEXT_ARG : STATE_PLAIN; |
313 | } |
314 | |
315 | static inline void handle_arg(STD_PARA) |
316 | { |
317 | ctx->arg.len = 0; |
318 | smart_str_appendl(&ctx->arg, start, YYCURSOR - start); |
319 | } |
320 | |
321 | static inline void handle_val(STD_PARA, char quotes, char type) |
322 | { |
323 | smart_str_setl(&ctx->val, start + quotes, YYCURSOR - start - quotes * 2); |
324 | tag_arg(ctx, quotes, type TSRMLS_CC); |
325 | } |
326 | |
327 | static inline void xx_mainloop(url_adapt_state_ex_t *ctx, const char *newdata, size_t newlen TSRMLS_DC) |
328 | { |
329 | char *end, *q; |
330 | char *xp; |
331 | char *start; |
332 | int rest; |
333 | |
334 | smart_str_appendl(&ctx->buf, newdata, newlen); |
335 | |
336 | YYCURSOR = ctx->buf.c; |
337 | YYLIMIT = ctx->buf.c + ctx->buf.len; |
338 | |
339 | switch (STATE) { |
340 | case STATE_PLAIN: goto state_plain; |
341 | case STATE_TAG: goto state_tag; |
342 | case STATE_NEXT_ARG: goto state_next_arg; |
343 | case STATE_ARG: goto state_arg; |
344 | case STATE_BEFORE_VAL: goto state_before_val; |
345 | case STATE_VAL: goto state_val; |
346 | } |
347 | |
348 | |
349 | state_plain_begin: |
350 | STATE = STATE_PLAIN; |
351 | |
352 | state_plain: |
353 | start = YYCURSOR; |
354 | |
355 | { |
356 | YYCTYPE yych; |
357 | static const unsigned char yybm[] = { |
358 | 128, 128, 128, 128, 128, 128, 128, 128, |
359 | 128, 128, 128, 128, 128, 128, 128, 128, |
360 | 128, 128, 128, 128, 128, 128, 128, 128, |
361 | 128, 128, 128, 128, 128, 128, 128, 128, |
362 | 128, 128, 128, 128, 128, 128, 128, 128, |
363 | 128, 128, 128, 128, 128, 128, 128, 128, |
364 | 128, 128, 128, 128, 128, 128, 128, 128, |
365 | 128, 128, 128, 128, 0, 128, 128, 128, |
366 | 128, 128, 128, 128, 128, 128, 128, 128, |
367 | 128, 128, 128, 128, 128, 128, 128, 128, |
368 | 128, 128, 128, 128, 128, 128, 128, 128, |
369 | 128, 128, 128, 128, 128, 128, 128, 128, |
370 | 128, 128, 128, 128, 128, 128, 128, 128, |
371 | 128, 128, 128, 128, 128, 128, 128, 128, |
372 | 128, 128, 128, 128, 128, 128, 128, 128, |
373 | 128, 128, 128, 128, 128, 128, 128, 128, |
374 | 128, 128, 128, 128, 128, 128, 128, 128, |
375 | 128, 128, 128, 128, 128, 128, 128, 128, |
376 | 128, 128, 128, 128, 128, 128, 128, 128, |
377 | 128, 128, 128, 128, 128, 128, 128, 128, |
378 | 128, 128, 128, 128, 128, 128, 128, 128, |
379 | 128, 128, 128, 128, 128, 128, 128, 128, |
380 | 128, 128, 128, 128, 128, 128, 128, 128, |
381 | 128, 128, 128, 128, 128, 128, 128, 128, |
382 | 128, 128, 128, 128, 128, 128, 128, 128, |
383 | 128, 128, 128, 128, 128, 128, 128, 128, |
384 | 128, 128, 128, 128, 128, 128, 128, 128, |
385 | 128, 128, 128, 128, 128, 128, 128, 128, |
386 | 128, 128, 128, 128, 128, 128, 128, 128, |
387 | 128, 128, 128, 128, 128, 128, 128, 128, |
388 | 128, 128, 128, 128, 128, 128, 128, 128, |
389 | 128, 128, 128, 128, 128, 128, 128, 128, |
390 | }; |
391 | if (YYLIMIT <= YYCURSOR) YYFILL(1); |
392 | yych = *YYCURSOR; |
393 | if (yybm[0+yych] & 128) { |
394 | goto yy15; |
395 | } |
396 | ++YYCURSOR; |
397 | { passthru(STD_ARGS); STATE = STATE_TAG; goto state_tag; } |
398 | yy15: |
399 | ++YYCURSOR; |
400 | if (YYLIMIT <= YYCURSOR) YYFILL(1); |
401 | yych = *YYCURSOR; |
402 | if (yybm[0+yych] & 128) { |
403 | goto yy15; |
404 | } |
405 | { passthru(STD_ARGS); goto state_plain; } |
406 | } |
407 | |
408 | |
409 | state_tag: |
410 | start = YYCURSOR; |
411 | |
412 | { |
413 | YYCTYPE yych; |
414 | static const unsigned char yybm[] = { |
415 | 0, 0, 0, 0, 0, 0, 0, 0, |
416 | 0, 0, 0, 0, 0, 0, 0, 0, |
417 | 0, 0, 0, 0, 0, 0, 0, 0, |
418 | 0, 0, 0, 0, 0, 0, 0, 0, |
419 | 0, 0, 0, 0, 0, 0, 0, 0, |
420 | 0, 0, 0, 0, 0, 0, 0, 0, |
421 | 0, 0, 0, 0, 0, 0, 0, 0, |
422 | 0, 0, 128, 0, 0, 0, 0, 0, |
423 | 0, 128, 128, 128, 128, 128, 128, 128, |
424 | 128, 128, 128, 128, 128, 128, 128, 128, |
425 | 128, 128, 128, 128, 128, 128, 128, 128, |
426 | 128, 128, 128, 0, 0, 0, 0, 0, |
427 | 0, 128, 128, 128, 128, 128, 128, 128, |
428 | 128, 128, 128, 128, 128, 128, 128, 128, |
429 | 128, 128, 128, 128, 128, 128, 128, 128, |
430 | 128, 128, 128, 0, 0, 0, 0, 0, |
431 | 0, 0, 0, 0, 0, 0, 0, 0, |
432 | 0, 0, 0, 0, 0, 0, 0, 0, |
433 | 0, 0, 0, 0, 0, 0, 0, 0, |
434 | 0, 0, 0, 0, 0, 0, 0, 0, |
435 | 0, 0, 0, 0, 0, 0, 0, 0, |
436 | 0, 0, 0, 0, 0, 0, 0, 0, |
437 | 0, 0, 0, 0, 0, 0, 0, 0, |
438 | 0, 0, 0, 0, 0, 0, 0, 0, |
439 | 0, 0, 0, 0, 0, 0, 0, 0, |
440 | 0, 0, 0, 0, 0, 0, 0, 0, |
441 | 0, 0, 0, 0, 0, 0, 0, 0, |
442 | 0, 0, 0, 0, 0, 0, 0, 0, |
443 | 0, 0, 0, 0, 0, 0, 0, 0, |
444 | 0, 0, 0, 0, 0, 0, 0, 0, |
445 | 0, 0, 0, 0, 0, 0, 0, 0, |
446 | 0, 0, 0, 0, 0, 0, 0, 0, |
447 | }; |
448 | if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); |
449 | yych = *YYCURSOR; |
450 | if (yych <= '@') { |
451 | if (yych != ':') goto yy22; |
452 | } else { |
453 | if (yych <= 'Z') goto yy20; |
454 | if (yych <= '`') goto yy22; |
455 | if (yych >= '{') goto yy22; |
456 | } |
457 | yy20: |
458 | ++YYCURSOR; |
459 | yych = *YYCURSOR; |
460 | goto yy25; |
461 | yy21: |
462 | { handle_tag(STD_ARGS); /* Sets STATE */; passthru(STD_ARGS); if (STATE == STATE_PLAIN) goto state_plain; else goto state_next_arg; } |
463 | yy22: |
464 | ++YYCURSOR; |
465 | { passthru(STD_ARGS); goto state_plain_begin; } |
466 | yy24: |
467 | ++YYCURSOR; |
468 | if (YYLIMIT <= YYCURSOR) YYFILL(1); |
469 | yych = *YYCURSOR; |
470 | yy25: |
471 | if (yybm[0+yych] & 128) { |
472 | goto yy24; |
473 | } |
474 | goto yy21; |
475 | } |
476 | |
477 | |
478 | state_next_arg_begin: |
479 | STATE = STATE_NEXT_ARG; |
480 | |
481 | state_next_arg: |
482 | start = YYCURSOR; |
483 | |
484 | { |
485 | YYCTYPE yych; |
486 | static const unsigned char yybm[] = { |
487 | 0, 0, 0, 0, 0, 0, 0, 0, |
488 | 0, 128, 128, 128, 0, 128, 0, 0, |
489 | 0, 0, 0, 0, 0, 0, 0, 0, |
490 | 0, 0, 0, 0, 0, 0, 0, 0, |
491 | 128, 0, 0, 0, 0, 0, 0, 0, |
492 | 0, 0, 0, 0, 0, 0, 0, 0, |
493 | 0, 0, 0, 0, 0, 0, 0, 0, |
494 | 0, 0, 0, 0, 0, 0, 0, 0, |
495 | 0, 0, 0, 0, 0, 0, 0, 0, |
496 | 0, 0, 0, 0, 0, 0, 0, 0, |
497 | 0, 0, 0, 0, 0, 0, 0, 0, |
498 | 0, 0, 0, 0, 0, 0, 0, 0, |
499 | 0, 0, 0, 0, 0, 0, 0, 0, |
500 | 0, 0, 0, 0, 0, 0, 0, 0, |
501 | 0, 0, 0, 0, 0, 0, 0, 0, |
502 | 0, 0, 0, 0, 0, 0, 0, 0, |
503 | 0, 0, 0, 0, 0, 0, 0, 0, |
504 | 0, 0, 0, 0, 0, 0, 0, 0, |
505 | 0, 0, 0, 0, 0, 0, 0, 0, |
506 | 0, 0, 0, 0, 0, 0, 0, 0, |
507 | 0, 0, 0, 0, 0, 0, 0, 0, |
508 | 0, 0, 0, 0, 0, 0, 0, 0, |
509 | 0, 0, 0, 0, 0, 0, 0, 0, |
510 | 0, 0, 0, 0, 0, 0, 0, 0, |
511 | 0, 0, 0, 0, 0, 0, 0, 0, |
512 | 0, 0, 0, 0, 0, 0, 0, 0, |
513 | 0, 0, 0, 0, 0, 0, 0, 0, |
514 | 0, 0, 0, 0, 0, 0, 0, 0, |
515 | 0, 0, 0, 0, 0, 0, 0, 0, |
516 | 0, 0, 0, 0, 0, 0, 0, 0, |
517 | 0, 0, 0, 0, 0, 0, 0, 0, |
518 | 0, 0, 0, 0, 0, 0, 0, 0, |
519 | }; |
520 | if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); |
521 | yych = *YYCURSOR; |
522 | if (yych <= '.') { |
523 | if (yych <= '\f') { |
524 | if (yych <= 0x08) goto yy36; |
525 | if (yych <= '\v') goto yy32; |
526 | goto yy36; |
527 | } else { |
528 | if (yych <= '\r') goto yy32; |
529 | if (yych == ' ') goto yy32; |
530 | goto yy36; |
531 | } |
532 | } else { |
533 | if (yych <= '@') { |
534 | if (yych <= '/') goto yy28; |
535 | if (yych == '>') goto yy30; |
536 | goto yy36; |
537 | } else { |
538 | if (yych <= 'Z') goto yy34; |
539 | if (yych <= '`') goto yy36; |
540 | if (yych <= 'z') goto yy34; |
541 | goto yy36; |
542 | } |
543 | } |
544 | yy28: |
545 | ++YYCURSOR; |
546 | if ((yych = *YYCURSOR) == '>') goto yy39; |
547 | yy29: |
548 | { passthru(STD_ARGS); goto state_plain_begin; } |
549 | yy30: |
550 | ++YYCURSOR; |
551 | yy31: |
552 | { passthru(STD_ARGS); handle_form(STD_ARGS); goto state_plain_begin; } |
553 | yy32: |
554 | ++YYCURSOR; |
555 | yych = *YYCURSOR; |
556 | goto yy38; |
557 | yy33: |
558 | { passthru(STD_ARGS); goto state_next_arg; } |
559 | yy34: |
560 | ++YYCURSOR; |
561 | { --YYCURSOR; STATE = STATE_ARG; goto state_arg; } |
562 | yy36: |
563 | yych = *++YYCURSOR; |
564 | goto yy29; |
565 | yy37: |
566 | ++YYCURSOR; |
567 | if (YYLIMIT <= YYCURSOR) YYFILL(1); |
568 | yych = *YYCURSOR; |
569 | yy38: |
570 | if (yybm[0+yych] & 128) { |
571 | goto yy37; |
572 | } |
573 | goto yy33; |
574 | yy39: |
575 | ++YYCURSOR; |
576 | yych = *YYCURSOR; |
577 | goto yy31; |
578 | } |
579 | |
580 | |
581 | state_arg: |
582 | start = YYCURSOR; |
583 | |
584 | { |
585 | YYCTYPE yych; |
586 | static const unsigned char yybm[] = { |
587 | 0, 0, 0, 0, 0, 0, 0, 0, |
588 | 0, 0, 0, 0, 0, 0, 0, 0, |
589 | 0, 0, 0, 0, 0, 0, 0, 0, |
590 | 0, 0, 0, 0, 0, 0, 0, 0, |
591 | 0, 0, 0, 0, 0, 0, 0, 0, |
592 | 0, 0, 0, 0, 0, 128, 0, 0, |
593 | 0, 0, 0, 0, 0, 0, 0, 0, |
594 | 0, 0, 0, 0, 0, 0, 0, 0, |
595 | 0, 128, 128, 128, 128, 128, 128, 128, |
596 | 128, 128, 128, 128, 128, 128, 128, 128, |
597 | 128, 128, 128, 128, 128, 128, 128, 128, |
598 | 128, 128, 128, 0, 0, 0, 0, 0, |
599 | 0, 128, 128, 128, 128, 128, 128, 128, |
600 | 128, 128, 128, 128, 128, 128, 128, 128, |
601 | 128, 128, 128, 128, 128, 128, 128, 128, |
602 | 128, 128, 128, 0, 0, 0, 0, 0, |
603 | 0, 0, 0, 0, 0, 0, 0, 0, |
604 | 0, 0, 0, 0, 0, 0, 0, 0, |
605 | 0, 0, 0, 0, 0, 0, 0, 0, |
606 | 0, 0, 0, 0, 0, 0, 0, 0, |
607 | 0, 0, 0, 0, 0, 0, 0, 0, |
608 | 0, 0, 0, 0, 0, 0, 0, 0, |
609 | 0, 0, 0, 0, 0, 0, 0, 0, |
610 | 0, 0, 0, 0, 0, 0, 0, 0, |
611 | 0, 0, 0, 0, 0, 0, 0, 0, |
612 | 0, 0, 0, 0, 0, 0, 0, 0, |
613 | 0, 0, 0, 0, 0, 0, 0, 0, |
614 | 0, 0, 0, 0, 0, 0, 0, 0, |
615 | 0, 0, 0, 0, 0, 0, 0, 0, |
616 | 0, 0, 0, 0, 0, 0, 0, 0, |
617 | 0, 0, 0, 0, 0, 0, 0, 0, |
618 | 0, 0, 0, 0, 0, 0, 0, 0, |
619 | }; |
620 | if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); |
621 | yych = *YYCURSOR; |
622 | if (yych <= '@') goto yy44; |
623 | if (yych <= 'Z') goto yy42; |
624 | if (yych <= '`') goto yy44; |
625 | if (yych >= '{') goto yy44; |
626 | yy42: |
627 | ++YYCURSOR; |
628 | yych = *YYCURSOR; |
629 | goto yy47; |
630 | yy43: |
631 | { passthru(STD_ARGS); handle_arg(STD_ARGS); STATE = STATE_BEFORE_VAL; goto state_before_val; } |
632 | yy44: |
633 | ++YYCURSOR; |
634 | { passthru(STD_ARGS); STATE = STATE_NEXT_ARG; goto state_next_arg; } |
635 | yy46: |
636 | ++YYCURSOR; |
637 | if (YYLIMIT <= YYCURSOR) YYFILL(1); |
638 | yych = *YYCURSOR; |
639 | yy47: |
640 | if (yybm[0+yych] & 128) { |
641 | goto yy46; |
642 | } |
643 | goto yy43; |
644 | } |
645 | |
646 | |
647 | state_before_val: |
648 | start = YYCURSOR; |
649 | |
650 | { |
651 | YYCTYPE yych; |
652 | static const unsigned char yybm[] = { |
653 | 0, 0, 0, 0, 0, 0, 0, 0, |
654 | 0, 0, 0, 0, 0, 0, 0, 0, |
655 | 0, 0, 0, 0, 0, 0, 0, 0, |
656 | 0, 0, 0, 0, 0, 0, 0, 0, |
657 | 128, 0, 0, 0, 0, 0, 0, 0, |
658 | 0, 0, 0, 0, 0, 0, 0, 0, |
659 | 0, 0, 0, 0, 0, 0, 0, 0, |
660 | 0, 0, 0, 0, 0, 0, 0, 0, |
661 | 0, 0, 0, 0, 0, 0, 0, 0, |
662 | 0, 0, 0, 0, 0, 0, 0, 0, |
663 | 0, 0, 0, 0, 0, 0, 0, 0, |
664 | 0, 0, 0, 0, 0, 0, 0, 0, |
665 | 0, 0, 0, 0, 0, 0, 0, 0, |
666 | 0, 0, 0, 0, 0, 0, 0, 0, |
667 | 0, 0, 0, 0, 0, 0, 0, 0, |
668 | 0, 0, 0, 0, 0, 0, 0, 0, |
669 | 0, 0, 0, 0, 0, 0, 0, 0, |
670 | 0, 0, 0, 0, 0, 0, 0, 0, |
671 | 0, 0, 0, 0, 0, 0, 0, 0, |
672 | 0, 0, 0, 0, 0, 0, 0, 0, |
673 | 0, 0, 0, 0, 0, 0, 0, 0, |
674 | 0, 0, 0, 0, 0, 0, 0, 0, |
675 | 0, 0, 0, 0, 0, 0, 0, 0, |
676 | 0, 0, 0, 0, 0, 0, 0, 0, |
677 | 0, 0, 0, 0, 0, 0, 0, 0, |
678 | 0, 0, 0, 0, 0, 0, 0, 0, |
679 | 0, 0, 0, 0, 0, 0, 0, 0, |
680 | 0, 0, 0, 0, 0, 0, 0, 0, |
681 | 0, 0, 0, 0, 0, 0, 0, 0, |
682 | 0, 0, 0, 0, 0, 0, 0, 0, |
683 | 0, 0, 0, 0, 0, 0, 0, 0, |
684 | 0, 0, 0, 0, 0, 0, 0, 0, |
685 | }; |
686 | if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); |
687 | yych = *YYCURSOR; |
688 | if (yych == ' ') goto yy50; |
689 | if (yych == '=') goto yy52; |
690 | goto yy54; |
691 | yy50: |
692 | yych = *(YYMARKER = ++YYCURSOR); |
693 | if (yych == ' ') goto yy57; |
694 | if (yych == '=') goto yy55; |
695 | yy51: |
696 | { --YYCURSOR; goto state_next_arg_begin; } |
697 | yy52: |
698 | ++YYCURSOR; |
699 | yych = *YYCURSOR; |
700 | goto yy56; |
701 | yy53: |
702 | { passthru(STD_ARGS); STATE = STATE_VAL; goto state_val; } |
703 | yy54: |
704 | yych = *++YYCURSOR; |
705 | goto yy51; |
706 | yy55: |
707 | ++YYCURSOR; |
708 | if (YYLIMIT <= YYCURSOR) YYFILL(1); |
709 | yych = *YYCURSOR; |
710 | yy56: |
711 | if (yybm[0+yych] & 128) { |
712 | goto yy55; |
713 | } |
714 | goto yy53; |
715 | yy57: |
716 | ++YYCURSOR; |
717 | if (YYLIMIT <= YYCURSOR) YYFILL(1); |
718 | yych = *YYCURSOR; |
719 | if (yych == ' ') goto yy57; |
720 | if (yych == '=') goto yy55; |
721 | YYCURSOR = YYMARKER; |
722 | goto yy51; |
723 | } |
724 | |
725 | |
726 | |
727 | state_val: |
728 | start = YYCURSOR; |
729 | |
730 | { |
731 | YYCTYPE yych; |
732 | static const unsigned char yybm[] = { |
733 | 224, 224, 224, 224, 224, 224, 224, 224, |
734 | 224, 192, 192, 224, 224, 192, 224, 224, |
735 | 224, 224, 224, 224, 224, 224, 224, 224, |
736 | 224, 224, 224, 224, 224, 224, 224, 224, |
737 | 192, 224, 64, 224, 224, 224, 224, 128, |
738 | 224, 224, 224, 224, 224, 224, 224, 224, |
739 | 224, 224, 224, 224, 224, 224, 224, 224, |
740 | 224, 224, 224, 224, 224, 224, 0, 224, |
741 | 224, 224, 224, 224, 224, 224, 224, 224, |
742 | 224, 224, 224, 224, 224, 224, 224, 224, |
743 | 224, 224, 224, 224, 224, 224, 224, 224, |
744 | 224, 224, 224, 224, 224, 224, 224, 224, |
745 | 224, 224, 224, 224, 224, 224, 224, 224, |
746 | 224, 224, 224, 224, 224, 224, 224, 224, |
747 | 224, 224, 224, 224, 224, 224, 224, 224, |
748 | 224, 224, 224, 224, 224, 224, 224, 224, |
749 | 224, 224, 224, 224, 224, 224, 224, 224, |
750 | 224, 224, 224, 224, 224, 224, 224, 224, |
751 | 224, 224, 224, 224, 224, 224, 224, 224, |
752 | 224, 224, 224, 224, 224, 224, 224, 224, |
753 | 224, 224, 224, 224, 224, 224, 224, 224, |
754 | 224, 224, 224, 224, 224, 224, 224, 224, |
755 | 224, 224, 224, 224, 224, 224, 224, 224, |
756 | 224, 224, 224, 224, 224, 224, 224, 224, |
757 | 224, 224, 224, 224, 224, 224, 224, 224, |
758 | 224, 224, 224, 224, 224, 224, 224, 224, |
759 | 224, 224, 224, 224, 224, 224, 224, 224, |
760 | 224, 224, 224, 224, 224, 224, 224, 224, |
761 | 224, 224, 224, 224, 224, 224, 224, 224, |
762 | 224, 224, 224, 224, 224, 224, 224, 224, |
763 | 224, 224, 224, 224, 224, 224, 224, 224, |
764 | 224, 224, 224, 224, 224, 224, 224, 224, |
765 | }; |
766 | if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); |
767 | yych = *YYCURSOR; |
768 | if (yych <= ' ') { |
769 | if (yych <= '\f') { |
770 | if (yych <= 0x08) goto yy65; |
771 | if (yych <= '\n') goto yy67; |
772 | goto yy65; |
773 | } else { |
774 | if (yych <= '\r') goto yy67; |
775 | if (yych <= 0x1F) goto yy65; |
776 | goto yy67; |
777 | } |
778 | } else { |
779 | if (yych <= '&') { |
780 | if (yych != '"') goto yy65; |
781 | } else { |
782 | if (yych <= '\'') goto yy64; |
783 | if (yych == '>') goto yy67; |
784 | goto yy65; |
785 | } |
786 | } |
787 | yych = *(YYMARKER = ++YYCURSOR); |
788 | if (yych != '>') goto yy76; |
789 | yy63: |
790 | { passthru(STD_ARGS); goto state_next_arg_begin; } |
791 | yy64: |
792 | yych = *(YYMARKER = ++YYCURSOR); |
793 | if (yych == '>') goto yy63; |
794 | goto yy71; |
795 | yy65: |
796 | ++YYCURSOR; |
797 | yych = *YYCURSOR; |
798 | goto yy69; |
799 | yy66: |
800 | { handle_val(STD_ARGS, 0, ' '); goto state_next_arg_begin; } |
801 | yy67: |
802 | yych = *++YYCURSOR; |
803 | goto yy63; |
804 | yy68: |
805 | ++YYCURSOR; |
806 | if (YYLIMIT <= YYCURSOR) YYFILL(1); |
807 | yych = *YYCURSOR; |
808 | yy69: |
809 | if (yybm[0+yych] & 32) { |
810 | goto yy68; |
811 | } |
812 | goto yy66; |
813 | yy70: |
814 | ++YYCURSOR; |
815 | if (YYLIMIT <= YYCURSOR) YYFILL(1); |
816 | yych = *YYCURSOR; |
817 | yy71: |
818 | if (yybm[0+yych] & 64) { |
819 | goto yy70; |
820 | } |
821 | if (yych <= '=') goto yy73; |
822 | yy72: |
823 | YYCURSOR = YYMARKER; |
824 | goto yy63; |
825 | yy73: |
826 | ++YYCURSOR; |
827 | { handle_val(STD_ARGS, 1, '\''); goto state_next_arg_begin; } |
828 | yy75: |
829 | ++YYCURSOR; |
830 | if (YYLIMIT <= YYCURSOR) YYFILL(1); |
831 | yych = *YYCURSOR; |
832 | yy76: |
833 | if (yybm[0+yych] & 128) { |
834 | goto yy75; |
835 | } |
836 | if (yych >= '>') goto yy72; |
837 | ++YYCURSOR; |
838 | { handle_val(STD_ARGS, 1, '"'); goto state_next_arg_begin; } |
839 | } |
840 | |
841 | |
842 | stop: |
843 | rest = YYLIMIT - start; |
844 | scdebug(("stopped in state %d at pos %d (%d:%c) %d\n" , STATE, YYCURSOR - ctx->buf.c, *YYCURSOR, *YYCURSOR, rest)); |
845 | /* XXX: Crash avoidance. Need to work with reporter to figure out what goes wrong */ |
846 | if (rest < 0) rest = 0; |
847 | |
848 | if (rest) memmove(ctx->buf.c, start, rest); |
849 | ctx->buf.len = rest; |
850 | } |
851 | |
852 | char *php_url_scanner_adapt_single_url(const char *url, size_t urllen, const char *name, const char *value, size_t *newlen TSRMLS_DC) |
853 | { |
854 | smart_str surl = {0}; |
855 | smart_str buf = {0}; |
856 | smart_str url_app = {0}; |
857 | |
858 | smart_str_setl(&surl, url, urllen); |
859 | |
860 | smart_str_appends(&url_app, name); |
861 | smart_str_appendc(&url_app, '='); |
862 | smart_str_appends(&url_app, value); |
863 | |
864 | append_modified_url(&surl, &buf, &url_app, PG(arg_separator).output); |
865 | |
866 | smart_str_0(&buf); |
867 | if (newlen) *newlen = buf.len; |
868 | |
869 | smart_str_free(&url_app); |
870 | |
871 | return buf.c; |
872 | } |
873 | |
874 | |
875 | static char *url_adapt_ext(const char *src, size_t srclen, size_t *newlen, zend_bool do_flush TSRMLS_DC) |
876 | { |
877 | url_adapt_state_ex_t *ctx; |
878 | char *retval; |
879 | |
880 | ctx = &BG(url_adapt_state_ex); |
881 | |
882 | xx_mainloop(ctx, src, srclen TSRMLS_CC); |
883 | |
884 | *newlen = ctx->result.len; |
885 | if (!ctx->result.c) { |
886 | smart_str_appendl(&ctx->result, "" , 0); |
887 | } |
888 | smart_str_0(&ctx->result); |
889 | if (do_flush) { |
890 | smart_str_appendl(&ctx->result, ctx->buf.c, ctx->buf.len); |
891 | *newlen += ctx->buf.len; |
892 | smart_str_free(&ctx->buf); |
893 | } |
894 | retval = ctx->result.c; |
895 | ctx->result.c = NULL; |
896 | ctx->result.len = 0; |
897 | return retval; |
898 | } |
899 | |
900 | static int php_url_scanner_ex_activate(TSRMLS_D) |
901 | { |
902 | url_adapt_state_ex_t *ctx; |
903 | |
904 | ctx = &BG(url_adapt_state_ex); |
905 | |
906 | memset(ctx, 0, ((size_t) &((url_adapt_state_ex_t *)0)->tags)); |
907 | |
908 | return SUCCESS; |
909 | } |
910 | |
911 | static int php_url_scanner_ex_deactivate(TSRMLS_D) |
912 | { |
913 | url_adapt_state_ex_t *ctx; |
914 | |
915 | ctx = &BG(url_adapt_state_ex); |
916 | |
917 | smart_str_free(&ctx->result); |
918 | smart_str_free(&ctx->buf); |
919 | smart_str_free(&ctx->tag); |
920 | smart_str_free(&ctx->arg); |
921 | |
922 | return SUCCESS; |
923 | } |
924 | |
925 | static void php_url_scanner_output_handler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC) |
926 | { |
927 | size_t len; |
928 | |
929 | if (BG(url_adapt_state_ex).url_app.len != 0) { |
930 | *handled_output = url_adapt_ext(output, output_len, &len, (zend_bool) (mode & (PHP_OUTPUT_HANDLER_END | PHP_OUTPUT_HANDLER_CONT | PHP_OUTPUT_HANDLER_FLUSH | PHP_OUTPUT_HANDLER_FINAL) ? 1 : 0) TSRMLS_CC); |
931 | if (sizeof(uint) < sizeof(size_t)) { |
932 | if (len > UINT_MAX) |
933 | len = UINT_MAX; |
934 | } |
935 | *handled_output_len = len; |
936 | } else if (BG(url_adapt_state_ex).url_app.len == 0) { |
937 | url_adapt_state_ex_t *ctx = &BG(url_adapt_state_ex); |
938 | if (ctx->buf.len) { |
939 | smart_str_appendl(&ctx->result, ctx->buf.c, ctx->buf.len); |
940 | smart_str_appendl(&ctx->result, output, output_len); |
941 | |
942 | *handled_output = ctx->result.c; |
943 | *handled_output_len = ctx->buf.len + output_len; |
944 | |
945 | ctx->result.c = NULL; |
946 | ctx->result.len = 0; |
947 | smart_str_free(&ctx->buf); |
948 | } else { |
949 | *handled_output = estrndup(output, *handled_output_len = output_len); |
950 | } |
951 | } else { |
952 | *handled_output = NULL; |
953 | } |
954 | } |
955 | |
956 | PHPAPI int php_url_scanner_add_var(char *name, int name_len, char *value, int value_len, int urlencode TSRMLS_DC) |
957 | { |
958 | char *encoded = NULL; |
959 | int encoded_len; |
960 | smart_str val; |
961 | |
962 | if (! BG(url_adapt_state_ex).active) { |
963 | php_url_scanner_ex_activate(TSRMLS_C); |
964 | php_output_start_internal(ZEND_STRL("URL-Rewriter" ), php_url_scanner_output_handler, 0, PHP_OUTPUT_HANDLER_STDFLAGS TSRMLS_CC); |
965 | BG(url_adapt_state_ex).active = 1; |
966 | } |
967 | |
968 | |
969 | if (BG(url_adapt_state_ex).url_app.len != 0) { |
970 | smart_str_appends(&BG(url_adapt_state_ex).url_app, PG(arg_separator).output); |
971 | } |
972 | |
973 | if (urlencode) { |
974 | encoded = php_url_encode(value, value_len, &encoded_len); |
975 | smart_str_setl(&val, encoded, encoded_len); |
976 | } else { |
977 | smart_str_setl(&val, value, value_len); |
978 | } |
979 | |
980 | smart_str_appendl(&BG(url_adapt_state_ex).url_app, name, name_len); |
981 | smart_str_appendc(&BG(url_adapt_state_ex).url_app, '='); |
982 | smart_str_append(&BG(url_adapt_state_ex).url_app, &val); |
983 | |
984 | smart_str_appends(&BG(url_adapt_state_ex).form_app, "<input type=\"hidden\" name=\"" ); |
985 | smart_str_appendl(&BG(url_adapt_state_ex).form_app, name, name_len); |
986 | smart_str_appends(&BG(url_adapt_state_ex).form_app, "\" value=\"" ); |
987 | smart_str_append(&BG(url_adapt_state_ex).form_app, &val); |
988 | smart_str_appends(&BG(url_adapt_state_ex).form_app, "\" />" ); |
989 | |
990 | if (urlencode) |
991 | efree(encoded); |
992 | |
993 | return SUCCESS; |
994 | } |
995 | |
996 | PHPAPI int php_url_scanner_reset_vars(TSRMLS_D) |
997 | { |
998 | BG(url_adapt_state_ex).form_app.len = 0; |
999 | BG(url_adapt_state_ex).url_app.len = 0; |
1000 | |
1001 | return SUCCESS; |
1002 | } |
1003 | |
1004 | PHP_MINIT_FUNCTION(url_scanner) |
1005 | { |
1006 | BG(url_adapt_state_ex).tags = NULL; |
1007 | |
1008 | BG(url_adapt_state_ex).form_app.c = BG(url_adapt_state_ex).url_app.c = 0; |
1009 | BG(url_adapt_state_ex).form_app.len = BG(url_adapt_state_ex).url_app.len = 0; |
1010 | |
1011 | REGISTER_INI_ENTRIES(); |
1012 | return SUCCESS; |
1013 | } |
1014 | |
1015 | PHP_MSHUTDOWN_FUNCTION(url_scanner) |
1016 | { |
1017 | UNREGISTER_INI_ENTRIES(); |
1018 | |
1019 | return SUCCESS; |
1020 | } |
1021 | |
1022 | PHP_RINIT_FUNCTION(url_scanner) |
1023 | { |
1024 | BG(url_adapt_state_ex).active = 0; |
1025 | |
1026 | return SUCCESS; |
1027 | } |
1028 | |
1029 | PHP_RSHUTDOWN_FUNCTION(url_scanner) |
1030 | { |
1031 | if (BG(url_adapt_state_ex).active) { |
1032 | php_url_scanner_ex_deactivate(TSRMLS_C); |
1033 | BG(url_adapt_state_ex).active = 0; |
1034 | } |
1035 | |
1036 | smart_str_free(&BG(url_adapt_state_ex).form_app); |
1037 | smart_str_free(&BG(url_adapt_state_ex).url_app); |
1038 | |
1039 | return SUCCESS; |
1040 | } |
1041 | |