This source file includes following definitions.
- tag_dtor
- PHP_INI_MH
- append_modified_url
- tag_arg
- passthru
- handle_form
- handle_tag
- handle_arg
- handle_val
- xx_mainloop
- php_url_scanner_adapt_single_url
- url_adapt_ext
- php_url_scanner_ex_activate
- php_url_scanner_ex_deactivate
- php_url_scanner_output_handler
- php_url_scanner_add_var
- php_url_scanner_reset_vars
- PHP_MINIT_FUNCTION
- PHP_MSHUTDOWN_FUNCTION
- PHP_RINIT_FUNCTION
- PHP_RSHUTDOWN_FUNCTION
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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 "zend_smart_str.h"
45
46 static void tag_dtor(zval *zv)
47 {
48 free(Z_PTR_P(zv));
49 }
50
51 static PHP_INI_MH(OnUpdateTags)
52 {
53 url_adapt_state_ex_t *ctx;
54 char *key;
55 char *tmp;
56 char *lasts = NULL;
57
58 ctx = &BG(url_adapt_state_ex);
59
60 tmp = estrndup(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
61
62 if (ctx->tags)
63 zend_hash_destroy(ctx->tags);
64 else {
65 ctx->tags = malloc(sizeof(HashTable));
66 if (!ctx->tags) {
67 return FAILURE;
68 }
69 }
70
71 zend_hash_init(ctx->tags, 0, NULL, tag_dtor, 1);
72
73 for (key = php_strtok_r(tmp, ",", &lasts);
74 key;
75 key = php_strtok_r(NULL, ",", &lasts)) {
76 char *val;
77
78 val = strchr(key, '=');
79 if (val) {
80 char *q;
81 size_t keylen;
82
83 *val++ = '\0';
84 for (q = key; *q; q++)
85 *q = tolower(*q);
86 keylen = q - key;
87
88
89 zend_hash_str_add_mem(ctx->tags, key, keylen, val, strlen(val)+1);
90 }
91 }
92
93 efree(tmp);
94
95 return SUCCESS;
96 }
97
98 PHP_INI_BEGIN()
99 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)
100 PHP_INI_END()
101
102
103
104 #define YYFILL(n) goto done
105 #define YYCTYPE unsigned char
106 #define YYCURSOR p
107 #define YYLIMIT q
108 #define YYMARKER r
109
110 static inline void append_modified_url(smart_str *url, smart_str *dest, smart_str *url_app, const char *separator)
111 {
112 register const char *p, *q;
113 const char *bash = NULL;
114 const char *sep = "?";
115
116 q = (p = ZSTR_VAL(url->s)) + ZSTR_LEN(url->s);
117
118 scan:
119
120 {
121 YYCTYPE yych;
122 static const unsigned char yybm[] = {
123 128, 128, 128, 128, 128, 128, 128, 128,
124 128, 128, 128, 128, 128, 128, 128, 128,
125 128, 128, 128, 128, 128, 128, 128, 128,
126 128, 128, 128, 128, 128, 128, 128, 128,
127 128, 128, 128, 0, 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, 0, 128, 128, 128, 128, 0,
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 128, 128, 128, 128, 128, 128, 128, 128,
151 128, 128, 128, 128, 128, 128, 128, 128,
152 128, 128, 128, 128, 128, 128, 128, 128,
153 128, 128, 128, 128, 128, 128, 128, 128,
154 128, 128, 128, 128, 128, 128, 128, 128,
155 };
156
157 if (YYLIMIT <= YYCURSOR) YYFILL(1);
158 yych = *YYCURSOR;
159 if (yybm[0+yych] & 128) {
160 goto yy8;
161 }
162 if (yych <= '9') goto yy6;
163 if (yych >= ';') goto yy4;
164 ++YYCURSOR;
165 { smart_str_append_smart_str(dest, url); return; }
166 yy4:
167 ++YYCURSOR;
168 { sep = separator; goto scan; }
169 yy6:
170 ++YYCURSOR;
171 { bash = p - 1; goto done; }
172 yy8:
173 ++YYCURSOR;
174 if (YYLIMIT <= YYCURSOR) YYFILL(1);
175 yych = *YYCURSOR;
176 if (yybm[0+yych] & 128) {
177 goto yy8;
178 }
179 { goto scan; }
180 }
181
182 done:
183
184
185 if (bash && bash - ZSTR_VAL(url->s) == 0) {
186 smart_str_append_smart_str(dest, url);
187 return;
188 }
189
190 if (bash)
191 smart_str_appendl(dest, ZSTR_VAL(url->s), bash - ZSTR_VAL(url->s));
192 else
193 smart_str_append_smart_str(dest, url);
194
195 smart_str_appends(dest, sep);
196 smart_str_append_smart_str(dest, url_app);
197
198 if (bash)
199 smart_str_appendl(dest, bash, q - bash);
200 }
201
202
203 #undef YYFILL
204 #undef YYCTYPE
205 #undef YYCURSOR
206 #undef YYLIMIT
207 #undef YYMARKER
208
209 static inline void tag_arg(url_adapt_state_ex_t *ctx, char quotes, char type)
210 {
211 char f = 0;
212
213 if (strncasecmp(ZSTR_VAL(ctx->arg.s), ctx->lookup_data, ZSTR_LEN(ctx->arg.s)) == 0)
214 f = 1;
215
216 if (quotes)
217 smart_str_appendc(&ctx->result, type);
218 if (f) {
219 append_modified_url(&ctx->val, &ctx->result, &ctx->url_app, PG(arg_separator).output);
220 } else {
221 smart_str_append_smart_str(&ctx->result, &ctx->val);
222 }
223 if (quotes)
224 smart_str_appendc(&ctx->result, type);
225 }
226
227 enum {
228 STATE_PLAIN = 0,
229 STATE_TAG,
230 STATE_NEXT_ARG,
231 STATE_ARG,
232 STATE_BEFORE_VAL,
233 STATE_VAL
234 };
235
236 #define YYFILL(n) goto stop
237 #define YYCTYPE unsigned char
238 #define YYCURSOR xp
239 #define YYLIMIT end
240 #define YYMARKER q
241 #define STATE ctx->state
242
243 #define STD_PARA url_adapt_state_ex_t *ctx, char *start, char *YYCURSOR
244 #define STD_ARGS ctx, start, xp
245
246 #if SCANNER_DEBUG
247 #define scdebug(x) printf x
248 #else
249 #define scdebug(x)
250 #endif
251
252 static inline void passthru(STD_PARA)
253 {
254 scdebug(("appending %d chars, starting with %c\n", YYCURSOR-start, *start));
255 smart_str_appendl(&ctx->result, start, YYCURSOR - start);
256 }
257
258
259
260
261
262
263 static void handle_form(STD_PARA)
264 {
265 int doit = 0;
266
267 if (ZSTR_LEN(ctx->form_app.s) > 0) {
268 switch (ZSTR_LEN(ctx->tag.s)) {
269 case sizeof("form") - 1:
270 if (!strncasecmp(ZSTR_VAL(ctx->tag.s), "form", sizeof("form") - 1)) {
271 doit = 1;
272 }
273 if (doit && ctx->val.s && ctx->lookup_data && *ctx->lookup_data) {
274 char *e, *p = (char *)zend_memnstr(ZSTR_VAL(ctx->val.s), "://", sizeof("://") - 1, ZSTR_VAL(ctx->val.s) + ZSTR_LEN(ctx->val.s));
275 if (p) {
276 e = memchr(p, '/', (ZSTR_VAL(ctx->val.s) + ZSTR_LEN(ctx->val.s)) - p);
277 if (!e) {
278 e = ZSTR_VAL(ctx->val.s) + ZSTR_LEN(ctx->val.s);
279 }
280 if ((e - p) && strncasecmp(p, ctx->lookup_data, (e - p))) {
281 doit = 0;
282 }
283 }
284 }
285 break;
286
287 case sizeof("fieldset") - 1:
288 if (!strncasecmp(ZSTR_VAL(ctx->tag.s), "fieldset", sizeof("fieldset") - 1)) {
289 doit = 1;
290 }
291 break;
292 }
293
294 if (doit)
295 smart_str_append_smart_str(&ctx->result, &ctx->form_app);
296 }
297 }
298
299
300
301
302
303
304
305
306 static inline void handle_tag(STD_PARA)
307 {
308 int ok = 0;
309 unsigned int i;
310
311 if (ctx->tag.s) {
312 ZSTR_LEN(ctx->tag.s) = 0;
313 }
314 smart_str_appendl(&ctx->tag, start, YYCURSOR - start);
315 for (i = 0; i < ZSTR_LEN(ctx->tag.s); i++)
316 ZSTR_VAL(ctx->tag.s)[i] = tolower((int)(unsigned char)ZSTR_VAL(ctx->tag.s)[i]);
317
318 if ((ctx->lookup_data = zend_hash_str_find_ptr(ctx->tags, ZSTR_VAL(ctx->tag.s), ZSTR_LEN(ctx->tag.s))) != NULL)
319 ok = 1;
320 STATE = ok ? STATE_NEXT_ARG : STATE_PLAIN;
321 }
322
323 static inline void handle_arg(STD_PARA)
324 {
325 if (ctx->arg.s) {
326 ZSTR_LEN(ctx->arg.s) = 0;
327 }
328 smart_str_appendl(&ctx->arg, start, YYCURSOR - start);
329 }
330
331 static inline void handle_val(STD_PARA, char quotes, char type)
332 {
333 smart_str_setl(&ctx->val, start + quotes, YYCURSOR - start - quotes * 2);
334 tag_arg(ctx, quotes, type);
335 }
336
337 static inline void xx_mainloop(url_adapt_state_ex_t *ctx, const char *newdata, size_t newlen)
338 {
339 char *end, *q;
340 char *xp;
341 char *start;
342 size_t rest;
343
344 smart_str_appendl(&ctx->buf, newdata, newlen);
345
346 YYCURSOR = ZSTR_VAL(ctx->buf.s);
347 YYLIMIT = ZSTR_VAL(ctx->buf.s) + ZSTR_LEN(ctx->buf.s);
348
349 switch (STATE) {
350 case STATE_PLAIN: goto state_plain;
351 case STATE_TAG: goto state_tag;
352 case STATE_NEXT_ARG: goto state_next_arg;
353 case STATE_ARG: goto state_arg;
354 case STATE_BEFORE_VAL: goto state_before_val;
355 case STATE_VAL: goto state_val;
356 }
357
358
359 state_plain_begin:
360 STATE = STATE_PLAIN;
361
362 state_plain:
363 start = YYCURSOR;
364
365 {
366 YYCTYPE yych;
367 static const unsigned char yybm[] = {
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, 0, 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 128, 128, 128, 128, 128, 128, 128, 128,
391 128, 128, 128, 128, 128, 128, 128, 128,
392 128, 128, 128, 128, 128, 128, 128, 128,
393 128, 128, 128, 128, 128, 128, 128, 128,
394 128, 128, 128, 128, 128, 128, 128, 128,
395 128, 128, 128, 128, 128, 128, 128, 128,
396 128, 128, 128, 128, 128, 128, 128, 128,
397 128, 128, 128, 128, 128, 128, 128, 128,
398 128, 128, 128, 128, 128, 128, 128, 128,
399 128, 128, 128, 128, 128, 128, 128, 128,
400 };
401 if (YYLIMIT <= YYCURSOR) YYFILL(1);
402 yych = *YYCURSOR;
403 if (yybm[0+yych] & 128) {
404 goto yy15;
405 }
406 ++YYCURSOR;
407 { passthru(STD_ARGS); STATE = STATE_TAG; goto state_tag; }
408 yy15:
409 ++YYCURSOR;
410 if (YYLIMIT <= YYCURSOR) YYFILL(1);
411 yych = *YYCURSOR;
412 if (yybm[0+yych] & 128) {
413 goto yy15;
414 }
415 { passthru(STD_ARGS); goto state_plain; }
416 }
417
418
419 state_tag:
420 start = YYCURSOR;
421
422 {
423 YYCTYPE yych;
424 static const unsigned char yybm[] = {
425 0, 0, 0, 0, 0, 0, 0, 0,
426 0, 0, 0, 0, 0, 0, 0, 0,
427 0, 0, 0, 0, 0, 0, 0, 0,
428 0, 0, 0, 0, 0, 0, 0, 0,
429 0, 0, 0, 0, 0, 0, 0, 0,
430 0, 0, 0, 0, 0, 0, 0, 0,
431 0, 0, 0, 0, 0, 0, 0, 0,
432 0, 0, 128, 0, 0, 0, 0, 0,
433 0, 128, 128, 128, 128, 128, 128, 128,
434 128, 128, 128, 128, 128, 128, 128, 128,
435 128, 128, 128, 128, 128, 128, 128, 128,
436 128, 128, 128, 0, 0, 0, 0, 0,
437 0, 128, 128, 128, 128, 128, 128, 128,
438 128, 128, 128, 128, 128, 128, 128, 128,
439 128, 128, 128, 128, 128, 128, 128, 128,
440 128, 128, 128, 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 0, 0, 0, 0, 0, 0, 0, 0,
448 0, 0, 0, 0, 0, 0, 0, 0,
449 0, 0, 0, 0, 0, 0, 0, 0,
450 0, 0, 0, 0, 0, 0, 0, 0,
451 0, 0, 0, 0, 0, 0, 0, 0,
452 0, 0, 0, 0, 0, 0, 0, 0,
453 0, 0, 0, 0, 0, 0, 0, 0,
454 0, 0, 0, 0, 0, 0, 0, 0,
455 0, 0, 0, 0, 0, 0, 0, 0,
456 0, 0, 0, 0, 0, 0, 0, 0,
457 };
458 if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
459 yych = *YYCURSOR;
460 if (yych <= '@') {
461 if (yych != ':') goto yy22;
462 } else {
463 if (yych <= 'Z') goto yy20;
464 if (yych <= '`') goto yy22;
465 if (yych >= '{') goto yy22;
466 }
467 yy20:
468 ++YYCURSOR;
469 yych = *YYCURSOR;
470 goto yy25;
471 yy21:
472 { handle_tag(STD_ARGS); ; passthru(STD_ARGS); if (STATE == STATE_PLAIN) goto state_plain; else goto state_next_arg; }
473 yy22:
474 ++YYCURSOR;
475 { passthru(STD_ARGS); goto state_plain_begin; }
476 yy24:
477 ++YYCURSOR;
478 if (YYLIMIT <= YYCURSOR) YYFILL(1);
479 yych = *YYCURSOR;
480 yy25:
481 if (yybm[0+yych] & 128) {
482 goto yy24;
483 }
484 goto yy21;
485 }
486
487
488 state_next_arg_begin:
489 STATE = STATE_NEXT_ARG;
490
491 state_next_arg:
492 start = YYCURSOR;
493
494 {
495 YYCTYPE yych;
496 static const unsigned char yybm[] = {
497 0, 0, 0, 0, 0, 0, 0, 0,
498 0, 128, 128, 128, 0, 128, 0, 0,
499 0, 0, 0, 0, 0, 0, 0, 0,
500 0, 0, 0, 0, 0, 0, 0, 0,
501 128, 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 0, 0, 0, 0, 0, 0, 0, 0,
520 0, 0, 0, 0, 0, 0, 0, 0,
521 0, 0, 0, 0, 0, 0, 0, 0,
522 0, 0, 0, 0, 0, 0, 0, 0,
523 0, 0, 0, 0, 0, 0, 0, 0,
524 0, 0, 0, 0, 0, 0, 0, 0,
525 0, 0, 0, 0, 0, 0, 0, 0,
526 0, 0, 0, 0, 0, 0, 0, 0,
527 0, 0, 0, 0, 0, 0, 0, 0,
528 0, 0, 0, 0, 0, 0, 0, 0,
529 };
530 if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
531 yych = *YYCURSOR;
532 if (yych <= '.') {
533 if (yych <= '\f') {
534 if (yych <= 0x08) goto yy36;
535 if (yych <= '\v') goto yy32;
536 goto yy36;
537 } else {
538 if (yych <= '\r') goto yy32;
539 if (yych == ' ') goto yy32;
540 goto yy36;
541 }
542 } else {
543 if (yych <= '@') {
544 if (yych <= '/') goto yy28;
545 if (yych == '>') goto yy30;
546 goto yy36;
547 } else {
548 if (yych <= 'Z') goto yy34;
549 if (yych <= '`') goto yy36;
550 if (yych <= 'z') goto yy34;
551 goto yy36;
552 }
553 }
554 yy28:
555 ++YYCURSOR;
556 if ((yych = *YYCURSOR) == '>') goto yy39;
557 yy29:
558 { passthru(STD_ARGS); goto state_plain_begin; }
559 yy30:
560 ++YYCURSOR;
561 yy31:
562 { passthru(STD_ARGS); handle_form(STD_ARGS); goto state_plain_begin; }
563 yy32:
564 ++YYCURSOR;
565 yych = *YYCURSOR;
566 goto yy38;
567 yy33:
568 { passthru(STD_ARGS); goto state_next_arg; }
569 yy34:
570 ++YYCURSOR;
571 { --YYCURSOR; STATE = STATE_ARG; goto state_arg; }
572 yy36:
573 yych = *++YYCURSOR;
574 goto yy29;
575 yy37:
576 ++YYCURSOR;
577 if (YYLIMIT <= YYCURSOR) YYFILL(1);
578 yych = *YYCURSOR;
579 yy38:
580 if (yybm[0+yych] & 128) {
581 goto yy37;
582 }
583 goto yy33;
584 yy39:
585 ++YYCURSOR;
586 yych = *YYCURSOR;
587 goto yy31;
588 }
589
590
591 state_arg:
592 start = YYCURSOR;
593
594 {
595 YYCTYPE yych;
596 static const unsigned char yybm[] = {
597 0, 0, 0, 0, 0, 0, 0, 0,
598 0, 0, 0, 0, 0, 0, 0, 0,
599 0, 0, 0, 0, 0, 0, 0, 0,
600 0, 0, 0, 0, 0, 0, 0, 0,
601 0, 0, 0, 0, 0, 0, 0, 0,
602 0, 0, 0, 0, 0, 128, 0, 0,
603 0, 0, 0, 0, 0, 0, 0, 0,
604 0, 0, 0, 0, 0, 0, 0, 0,
605 0, 128, 128, 128, 128, 128, 128, 128,
606 128, 128, 128, 128, 128, 128, 128, 128,
607 128, 128, 128, 128, 128, 128, 128, 128,
608 128, 128, 128, 0, 0, 0, 0, 0,
609 0, 128, 128, 128, 128, 128, 128, 128,
610 128, 128, 128, 128, 128, 128, 128, 128,
611 128, 128, 128, 128, 128, 128, 128, 128,
612 128, 128, 128, 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 0, 0, 0, 0, 0, 0, 0, 0,
620 0, 0, 0, 0, 0, 0, 0, 0,
621 0, 0, 0, 0, 0, 0, 0, 0,
622 0, 0, 0, 0, 0, 0, 0, 0,
623 0, 0, 0, 0, 0, 0, 0, 0,
624 0, 0, 0, 0, 0, 0, 0, 0,
625 0, 0, 0, 0, 0, 0, 0, 0,
626 0, 0, 0, 0, 0, 0, 0, 0,
627 0, 0, 0, 0, 0, 0, 0, 0,
628 0, 0, 0, 0, 0, 0, 0, 0,
629 };
630 if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
631 yych = *YYCURSOR;
632 if (yych <= '@') goto yy44;
633 if (yych <= 'Z') goto yy42;
634 if (yych <= '`') goto yy44;
635 if (yych >= '{') goto yy44;
636 yy42:
637 ++YYCURSOR;
638 yych = *YYCURSOR;
639 goto yy47;
640 yy43:
641 { passthru(STD_ARGS); handle_arg(STD_ARGS); STATE = STATE_BEFORE_VAL; goto state_before_val; }
642 yy44:
643 ++YYCURSOR;
644 { passthru(STD_ARGS); STATE = STATE_NEXT_ARG; goto state_next_arg; }
645 yy46:
646 ++YYCURSOR;
647 if (YYLIMIT <= YYCURSOR) YYFILL(1);
648 yych = *YYCURSOR;
649 yy47:
650 if (yybm[0+yych] & 128) {
651 goto yy46;
652 }
653 goto yy43;
654 }
655
656
657 state_before_val:
658 start = YYCURSOR;
659
660 {
661 YYCTYPE yych;
662 static const unsigned char yybm[] = {
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 128, 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 0, 0, 0, 0, 0, 0, 0, 0,
686 0, 0, 0, 0, 0, 0, 0, 0,
687 0, 0, 0, 0, 0, 0, 0, 0,
688 0, 0, 0, 0, 0, 0, 0, 0,
689 0, 0, 0, 0, 0, 0, 0, 0,
690 0, 0, 0, 0, 0, 0, 0, 0,
691 0, 0, 0, 0, 0, 0, 0, 0,
692 0, 0, 0, 0, 0, 0, 0, 0,
693 0, 0, 0, 0, 0, 0, 0, 0,
694 0, 0, 0, 0, 0, 0, 0, 0,
695 };
696 if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
697 yych = *YYCURSOR;
698 if (yych == ' ') goto yy50;
699 if (yych == '=') goto yy52;
700 goto yy54;
701 yy50:
702 yych = *(YYMARKER = ++YYCURSOR);
703 if (yych == ' ') goto yy57;
704 if (yych == '=') goto yy55;
705 yy51:
706 { --YYCURSOR; goto state_next_arg_begin; }
707 yy52:
708 ++YYCURSOR;
709 yych = *YYCURSOR;
710 goto yy56;
711 yy53:
712 { passthru(STD_ARGS); STATE = STATE_VAL; goto state_val; }
713 yy54:
714 yych = *++YYCURSOR;
715 goto yy51;
716 yy55:
717 ++YYCURSOR;
718 if (YYLIMIT <= YYCURSOR) YYFILL(1);
719 yych = *YYCURSOR;
720 yy56:
721 if (yybm[0+yych] & 128) {
722 goto yy55;
723 }
724 goto yy53;
725 yy57:
726 ++YYCURSOR;
727 if (YYLIMIT <= YYCURSOR) YYFILL(1);
728 yych = *YYCURSOR;
729 if (yych == ' ') goto yy57;
730 if (yych == '=') goto yy55;
731 YYCURSOR = YYMARKER;
732 goto yy51;
733 }
734
735
736
737 state_val:
738 start = YYCURSOR;
739
740 {
741 YYCTYPE yych;
742 static const unsigned char yybm[] = {
743 224, 224, 224, 224, 224, 224, 224, 224,
744 224, 192, 192, 224, 224, 192, 224, 224,
745 224, 224, 224, 224, 224, 224, 224, 224,
746 224, 224, 224, 224, 224, 224, 224, 224,
747 192, 224, 64, 224, 224, 224, 224, 128,
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, 0, 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 224, 224, 224, 224, 224, 224, 224, 224,
766 224, 224, 224, 224, 224, 224, 224, 224,
767 224, 224, 224, 224, 224, 224, 224, 224,
768 224, 224, 224, 224, 224, 224, 224, 224,
769 224, 224, 224, 224, 224, 224, 224, 224,
770 224, 224, 224, 224, 224, 224, 224, 224,
771 224, 224, 224, 224, 224, 224, 224, 224,
772 224, 224, 224, 224, 224, 224, 224, 224,
773 224, 224, 224, 224, 224, 224, 224, 224,
774 224, 224, 224, 224, 224, 224, 224, 224,
775 };
776 if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
777 yych = *YYCURSOR;
778 if (yych <= ' ') {
779 if (yych <= '\f') {
780 if (yych <= 0x08) goto yy65;
781 if (yych <= '\n') goto yy67;
782 goto yy65;
783 } else {
784 if (yych <= '\r') goto yy67;
785 if (yych <= 0x1F) goto yy65;
786 goto yy67;
787 }
788 } else {
789 if (yych <= '&') {
790 if (yych != '"') goto yy65;
791 } else {
792 if (yych <= '\'') goto yy64;
793 if (yych == '>') goto yy67;
794 goto yy65;
795 }
796 }
797 yych = *(YYMARKER = ++YYCURSOR);
798 if (yych != '>') goto yy76;
799 yy63:
800 { passthru(STD_ARGS); goto state_next_arg_begin; }
801 yy64:
802 yych = *(YYMARKER = ++YYCURSOR);
803 if (yych == '>') goto yy63;
804 goto yy71;
805 yy65:
806 ++YYCURSOR;
807 yych = *YYCURSOR;
808 goto yy69;
809 yy66:
810 { handle_val(STD_ARGS, 0, ' '); goto state_next_arg_begin; }
811 yy67:
812 yych = *++YYCURSOR;
813 goto yy63;
814 yy68:
815 ++YYCURSOR;
816 if (YYLIMIT <= YYCURSOR) YYFILL(1);
817 yych = *YYCURSOR;
818 yy69:
819 if (yybm[0+yych] & 32) {
820 goto yy68;
821 }
822 goto yy66;
823 yy70:
824 ++YYCURSOR;
825 if (YYLIMIT <= YYCURSOR) YYFILL(1);
826 yych = *YYCURSOR;
827 yy71:
828 if (yybm[0+yych] & 64) {
829 goto yy70;
830 }
831 if (yych <= '=') goto yy73;
832 yy72:
833 YYCURSOR = YYMARKER;
834 goto yy63;
835 yy73:
836 ++YYCURSOR;
837 { handle_val(STD_ARGS, 1, '\''); goto state_next_arg_begin; }
838 yy75:
839 ++YYCURSOR;
840 if (YYLIMIT <= YYCURSOR) YYFILL(1);
841 yych = *YYCURSOR;
842 yy76:
843 if (yybm[0+yych] & 128) {
844 goto yy75;
845 }
846 if (yych >= '>') goto yy72;
847 ++YYCURSOR;
848 { handle_val(STD_ARGS, 1, '"'); goto state_next_arg_begin; }
849 }
850
851
852 stop:
853 if (YYLIMIT < start) {
854
855 rest = 0;
856 } else {
857 rest = YYLIMIT - start;
858 scdebug(("stopped in state %d at pos %d (%d:%c) %d\n", STATE, YYCURSOR - ctx->buf.c, *YYCURSOR, *YYCURSOR, rest));
859 }
860
861 if (rest) memmove(ZSTR_VAL(ctx->buf.s), start, rest);
862 ZSTR_LEN(ctx->buf.s) = rest;
863 }
864
865
866 PHPAPI char *php_url_scanner_adapt_single_url(const char *url, size_t urllen, const char *name, const char *value, size_t *newlen, int urlencode)
867 {
868 char *result;
869 smart_str surl = {0};
870 smart_str buf = {0};
871 smart_str url_app = {0};
872 zend_string *encoded;
873
874 smart_str_appendl(&surl, url, urllen);
875
876 if (urlencode) {
877 encoded = php_raw_url_encode(name, strlen(name));
878 smart_str_appendl(&url_app, ZSTR_VAL(encoded), ZSTR_LEN(encoded));
879 zend_string_free(encoded);
880 } else {
881 smart_str_appends(&url_app, name);
882 }
883 smart_str_appendc(&url_app, '=');
884 if (urlencode) {
885 encoded = php_raw_url_encode(value, strlen(value));
886 smart_str_appendl(&url_app, ZSTR_VAL(encoded), ZSTR_LEN(encoded));
887 zend_string_free(encoded);
888 } else {
889 smart_str_appends(&url_app, value);
890 }
891
892 append_modified_url(&surl, &buf, &url_app, PG(arg_separator).output);
893
894 smart_str_0(&buf);
895 if (newlen) *newlen = ZSTR_LEN(buf.s);
896 result = estrndup(ZSTR_VAL(buf.s), ZSTR_LEN(buf.s));
897
898 smart_str_free(&url_app);
899 smart_str_free(&buf);
900
901 return result;
902 }
903
904
905 static char *url_adapt_ext(const char *src, size_t srclen, size_t *newlen, zend_bool do_flush)
906 {
907 url_adapt_state_ex_t *ctx;
908 char *retval;
909
910 ctx = &BG(url_adapt_state_ex);
911
912 xx_mainloop(ctx, src, srclen);
913
914 if (!ctx->result.s) {
915 smart_str_appendl(&ctx->result, "", 0);
916 *newlen = 0;
917 } else {
918 *newlen = ZSTR_LEN(ctx->result.s);
919 }
920 smart_str_0(&ctx->result);
921 if (do_flush) {
922 smart_str_append(&ctx->result, ctx->buf.s);
923 *newlen += ZSTR_LEN(ctx->buf.s);
924 smart_str_free(&ctx->buf);
925 smart_str_free(&ctx->val);
926 }
927 retval = estrndup(ZSTR_VAL(ctx->result.s), ZSTR_LEN(ctx->result.s));
928 smart_str_free(&ctx->result);
929 return retval;
930 }
931
932 static int php_url_scanner_ex_activate(void)
933 {
934 url_adapt_state_ex_t *ctx;
935
936 ctx = &BG(url_adapt_state_ex);
937
938 memset(ctx, 0, ((size_t) &((url_adapt_state_ex_t *)0)->tags));
939
940 return SUCCESS;
941 }
942
943 static int php_url_scanner_ex_deactivate(void)
944 {
945 url_adapt_state_ex_t *ctx;
946
947 ctx = &BG(url_adapt_state_ex);
948
949 smart_str_free(&ctx->result);
950 smart_str_free(&ctx->buf);
951 smart_str_free(&ctx->tag);
952 smart_str_free(&ctx->arg);
953
954 return SUCCESS;
955 }
956
957 static void php_url_scanner_output_handler(char *output, size_t output_len, char **handled_output, size_t *handled_output_len, int mode)
958 {
959 size_t len;
960
961 if (ZSTR_LEN(BG(url_adapt_state_ex).url_app.s) != 0) {
962 *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));
963 if (sizeof(uint) < sizeof(size_t)) {
964 if (len > UINT_MAX)
965 len = UINT_MAX;
966 }
967 *handled_output_len = len;
968 } else if (ZSTR_LEN(BG(url_adapt_state_ex).url_app.s) == 0) {
969 url_adapt_state_ex_t *ctx = &BG(url_adapt_state_ex);
970 if (ctx->buf.s && ZSTR_LEN(ctx->buf.s)) {
971 smart_str_append(&ctx->result, ctx->buf.s);
972 smart_str_appendl(&ctx->result, output, output_len);
973
974 *handled_output = estrndup(ZSTR_VAL(ctx->result.s), ZSTR_LEN(ctx->result.s));
975 *handled_output_len = ZSTR_LEN(ctx->buf.s) + output_len;
976
977 smart_str_free(&ctx->buf);
978 smart_str_free(&ctx->result);
979 } else {
980 *handled_output = estrndup(output, *handled_output_len = output_len);
981 }
982 } else {
983 *handled_output = NULL;
984 }
985 }
986
987 PHPAPI int php_url_scanner_add_var(char *name, size_t name_len, char *value, size_t value_len, int urlencode)
988 {
989 smart_str sname = {0};
990 smart_str svalue = {0};
991 zend_string *encoded;
992
993 if (!BG(url_adapt_state_ex).active) {
994 php_url_scanner_ex_activate();
995 php_output_start_internal(ZEND_STRL("URL-Rewriter"), php_url_scanner_output_handler, 0, PHP_OUTPUT_HANDLER_STDFLAGS);
996 BG(url_adapt_state_ex).active = 1;
997 }
998
999 if (BG(url_adapt_state_ex).url_app.s && ZSTR_LEN(BG(url_adapt_state_ex).url_app.s) != 0) {
1000 smart_str_appends(&BG(url_adapt_state_ex).url_app, PG(arg_separator).output);
1001 }
1002
1003 if (urlencode) {
1004 encoded = php_raw_url_encode(name, name_len);
1005 smart_str_appendl(&sname, ZSTR_VAL(encoded), ZSTR_LEN(encoded));
1006 zend_string_free(encoded);
1007 encoded = php_raw_url_encode(value, value_len);
1008 smart_str_appendl(&svalue, ZSTR_VAL(encoded), ZSTR_LEN(encoded));
1009 zend_string_free(encoded);
1010 } else {
1011 smart_str_appendl(&sname, name, name_len);
1012 smart_str_appendl(&svalue, value, value_len);
1013 }
1014
1015 smart_str_append_smart_str(&BG(url_adapt_state_ex).url_app, &sname);
1016 smart_str_appendc(&BG(url_adapt_state_ex).url_app, '=');
1017 smart_str_append_smart_str(&BG(url_adapt_state_ex).url_app, &svalue);
1018
1019 smart_str_appends(&BG(url_adapt_state_ex).form_app, "<input type=\"hidden\" name=\"");
1020 smart_str_append_smart_str(&BG(url_adapt_state_ex).form_app, &sname);
1021 smart_str_appends(&BG(url_adapt_state_ex).form_app, "\" value=\"");
1022 smart_str_append_smart_str(&BG(url_adapt_state_ex).form_app, &svalue);
1023 smart_str_appends(&BG(url_adapt_state_ex).form_app, "\" />");
1024
1025 smart_str_free(&sname);
1026 smart_str_free(&svalue);
1027
1028 return SUCCESS;
1029 }
1030
1031 PHPAPI int php_url_scanner_reset_vars(void)
1032 {
1033 if (BG(url_adapt_state_ex).form_app.s) {
1034 ZSTR_LEN(BG(url_adapt_state_ex).form_app.s) = 0;
1035 }
1036 if (BG(url_adapt_state_ex).url_app.s) {
1037 ZSTR_LEN(BG(url_adapt_state_ex).url_app.s) = 0;
1038 }
1039
1040 return SUCCESS;
1041 }
1042
1043 PHP_MINIT_FUNCTION(url_scanner)
1044 {
1045 BG(url_adapt_state_ex).tags = NULL;
1046
1047 BG(url_adapt_state_ex).form_app.s = BG(url_adapt_state_ex).url_app.s = NULL;
1048
1049 REGISTER_INI_ENTRIES();
1050 return SUCCESS;
1051 }
1052
1053 PHP_MSHUTDOWN_FUNCTION(url_scanner)
1054 {
1055 UNREGISTER_INI_ENTRIES();
1056
1057 return SUCCESS;
1058 }
1059
1060 PHP_RINIT_FUNCTION(url_scanner)
1061 {
1062 BG(url_adapt_state_ex).active = 0;
1063
1064 return SUCCESS;
1065 }
1066
1067 PHP_RSHUTDOWN_FUNCTION(url_scanner)
1068 {
1069 if (BG(url_adapt_state_ex).active) {
1070 php_url_scanner_ex_deactivate();
1071 BG(url_adapt_state_ex).active = 0;
1072 }
1073
1074 smart_str_free(&BG(url_adapt_state_ex).form_app);
1075 smart_str_free(&BG(url_adapt_state_ex).url_app);
1076
1077 return SUCCESS;
1078 }