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