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
46static 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
93PHP_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)
95PHP_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
105static 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
113scan:
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; }
161yy4:
162 ++YYCURSOR;
163 { sep = separator; goto scan; }
164yy6:
165 ++YYCURSOR;
166 { bash = p - 1; goto done; }
167yy8:
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
177done:
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
204static 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
222enum {
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
247static 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
258static 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
301static 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
315static inline void handle_arg(STD_PARA)
316{
317 ctx->arg.len = 0;
318 smart_str_appendl(&ctx->arg, start, YYCURSOR - start);
319}
320
321static 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
327static 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
349state_plain_begin:
350 STATE = STATE_PLAIN;
351
352state_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; }
398yy15:
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
409state_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 }
457yy20:
458 ++YYCURSOR;
459 yych = *YYCURSOR;
460 goto yy25;
461yy21:
462 { handle_tag(STD_ARGS); /* Sets STATE */; passthru(STD_ARGS); if (STATE == STATE_PLAIN) goto state_plain; else goto state_next_arg; }
463yy22:
464 ++YYCURSOR;
465 { passthru(STD_ARGS); goto state_plain_begin; }
466yy24:
467 ++YYCURSOR;
468 if (YYLIMIT <= YYCURSOR) YYFILL(1);
469 yych = *YYCURSOR;
470yy25:
471 if (yybm[0+yych] & 128) {
472 goto yy24;
473 }
474 goto yy21;
475}
476
477
478state_next_arg_begin:
479 STATE = STATE_NEXT_ARG;
480
481state_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 }
544yy28:
545 ++YYCURSOR;
546 if ((yych = *YYCURSOR) == '>') goto yy39;
547yy29:
548 { passthru(STD_ARGS); goto state_plain_begin; }
549yy30:
550 ++YYCURSOR;
551yy31:
552 { passthru(STD_ARGS); handle_form(STD_ARGS); goto state_plain_begin; }
553yy32:
554 ++YYCURSOR;
555 yych = *YYCURSOR;
556 goto yy38;
557yy33:
558 { passthru(STD_ARGS); goto state_next_arg; }
559yy34:
560 ++YYCURSOR;
561 { --YYCURSOR; STATE = STATE_ARG; goto state_arg; }
562yy36:
563 yych = *++YYCURSOR;
564 goto yy29;
565yy37:
566 ++YYCURSOR;
567 if (YYLIMIT <= YYCURSOR) YYFILL(1);
568 yych = *YYCURSOR;
569yy38:
570 if (yybm[0+yych] & 128) {
571 goto yy37;
572 }
573 goto yy33;
574yy39:
575 ++YYCURSOR;
576 yych = *YYCURSOR;
577 goto yy31;
578}
579
580
581state_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;
626yy42:
627 ++YYCURSOR;
628 yych = *YYCURSOR;
629 goto yy47;
630yy43:
631 { passthru(STD_ARGS); handle_arg(STD_ARGS); STATE = STATE_BEFORE_VAL; goto state_before_val; }
632yy44:
633 ++YYCURSOR;
634 { passthru(STD_ARGS); STATE = STATE_NEXT_ARG; goto state_next_arg; }
635yy46:
636 ++YYCURSOR;
637 if (YYLIMIT <= YYCURSOR) YYFILL(1);
638 yych = *YYCURSOR;
639yy47:
640 if (yybm[0+yych] & 128) {
641 goto yy46;
642 }
643 goto yy43;
644}
645
646
647state_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;
691yy50:
692 yych = *(YYMARKER = ++YYCURSOR);
693 if (yych == ' ') goto yy57;
694 if (yych == '=') goto yy55;
695yy51:
696 { --YYCURSOR; goto state_next_arg_begin; }
697yy52:
698 ++YYCURSOR;
699 yych = *YYCURSOR;
700 goto yy56;
701yy53:
702 { passthru(STD_ARGS); STATE = STATE_VAL; goto state_val; }
703yy54:
704 yych = *++YYCURSOR;
705 goto yy51;
706yy55:
707 ++YYCURSOR;
708 if (YYLIMIT <= YYCURSOR) YYFILL(1);
709 yych = *YYCURSOR;
710yy56:
711 if (yybm[0+yych] & 128) {
712 goto yy55;
713 }
714 goto yy53;
715yy57:
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
727state_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;
789yy63:
790 { passthru(STD_ARGS); goto state_next_arg_begin; }
791yy64:
792 yych = *(YYMARKER = ++YYCURSOR);
793 if (yych == '>') goto yy63;
794 goto yy71;
795yy65:
796 ++YYCURSOR;
797 yych = *YYCURSOR;
798 goto yy69;
799yy66:
800 { handle_val(STD_ARGS, 0, ' '); goto state_next_arg_begin; }
801yy67:
802 yych = *++YYCURSOR;
803 goto yy63;
804yy68:
805 ++YYCURSOR;
806 if (YYLIMIT <= YYCURSOR) YYFILL(1);
807 yych = *YYCURSOR;
808yy69:
809 if (yybm[0+yych] & 32) {
810 goto yy68;
811 }
812 goto yy66;
813yy70:
814 ++YYCURSOR;
815 if (YYLIMIT <= YYCURSOR) YYFILL(1);
816 yych = *YYCURSOR;
817yy71:
818 if (yybm[0+yych] & 64) {
819 goto yy70;
820 }
821 if (yych <= '=') goto yy73;
822yy72:
823 YYCURSOR = YYMARKER;
824 goto yy63;
825yy73:
826 ++YYCURSOR;
827 { handle_val(STD_ARGS, 1, '\''); goto state_next_arg_begin; }
828yy75:
829 ++YYCURSOR;
830 if (YYLIMIT <= YYCURSOR) YYFILL(1);
831 yych = *YYCURSOR;
832yy76:
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
842stop:
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
852char *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
875static 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
900static 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
911static 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
925static 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
956PHPAPI 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
996PHPAPI 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
1004PHP_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
1015PHP_MSHUTDOWN_FUNCTION(url_scanner)
1016{
1017 UNREGISTER_INI_ENTRIES();
1018
1019 return SUCCESS;
1020}
1021
1022PHP_RINIT_FUNCTION(url_scanner)
1023{
1024 BG(url_adapt_state_ex).active = 0;
1025
1026 return SUCCESS;
1027}
1028
1029PHP_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