xref: /PHP-5.5/ext/standard/url_scanner_ex.c (revision 73c1be26)
1 /* Generated by re2c 0.13.5 */
2 #line 1 "ext/standard/url_scanner_ex.re"
3 /*
4   +----------------------------------------------------------------------+
5   | PHP Version 5                                                        |
6   +----------------------------------------------------------------------+
7   | Copyright (c) 1997-2015 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 #define STATE_TAG SOME_OTHER_STATE_TAG
39 #include "basic_functions.h"
40 #include "url.h"
41 #undef STATE_TAG
42 
43 #define url_scanner url_scanner_ex
44 
45 #include "php_smart_str.h"
46 
PHP_INI_MH(OnUpdateTags)47 static PHP_INI_MH(OnUpdateTags)
48 {
49 	url_adapt_state_ex_t *ctx;
50 	char *key;
51 	char *lasts;
52 	char *tmp;
53 
54 	ctx = &BG(url_adapt_state_ex);
55 
56 	tmp = estrndup(new_value, new_value_length);
57 
58 	if (ctx->tags)
59 		zend_hash_destroy(ctx->tags);
60 	else {
61 		ctx->tags = malloc(sizeof(HashTable));
62 		if (!ctx->tags) {
63 			return FAILURE;
64 		}
65 	}
66 
67 	zend_hash_init(ctx->tags, 0, NULL, NULL, 1);
68 
69 	for (key = php_strtok_r(tmp, ",", &lasts);
70 			key;
71 			key = php_strtok_r(NULL, ",", &lasts)) {
72 		char *val;
73 
74 		val = strchr(key, '=');
75 		if (val) {
76 			char *q;
77 			int keylen;
78 
79 			*val++ = '\0';
80 			for (q = key; *q; q++)
81 				*q = tolower(*q);
82 			keylen = q - key;
83 			/* key is stored withOUT NUL
84 			   val is stored WITH    NUL */
85 			zend_hash_add(ctx->tags, key, keylen, val, strlen(val)+1, NULL);
86 		}
87 	}
88 
89 	efree(tmp);
90 
91 	return SUCCESS;
92 }
93 
94 PHP_INI_BEGIN()
95 	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()96 PHP_INI_END()
97 
98 #line 102 "ext/standard/url_scanner_ex.re"
99 
100 
101 #define YYFILL(n) goto done
102 #define YYCTYPE unsigned char
103 #define YYCURSOR p
104 #define YYLIMIT q
105 #define YYMARKER r
106 
107 static inline void append_modified_url(smart_str *url, smart_str *dest, smart_str *url_app, const char *separator)
108 {
109 	register const char *p, *q;
110 	const char *bash = NULL;
111 	const char *sep = "?";
112 
113 	q = (p = url->c) + url->len;
114 
115 scan:
116 
117 #line 118 "ext/standard/url_scanner_ex.c"
118 {
119 	YYCTYPE yych;
120 	static const unsigned char yybm[] = {
121 		128, 128, 128, 128, 128, 128, 128, 128,
122 		128, 128, 128, 128, 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, 128,   0, 128, 128, 128, 128,
126 		128, 128, 128, 128, 128, 128, 128, 128,
127 		128, 128, 128, 128, 128, 128, 128, 128,
128 		128, 128,   0, 128, 128, 128, 128,   0,
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 		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 	};
154 
155 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
156 	yych = *YYCURSOR;
157 	if (yybm[0+yych] & 128) {
158 		goto yy8;
159 	}
160 	if (yych <= '9') goto yy6;
161 	if (yych >= ';') goto yy4;
162 	++YYCURSOR;
163 #line 120 "ext/standard/url_scanner_ex.re"
164 	{ smart_str_append(dest, url); return; }
165 #line 166 "ext/standard/url_scanner_ex.c"
166 yy4:
167 	++YYCURSOR;
168 #line 121 "ext/standard/url_scanner_ex.re"
169 	{ sep = separator; goto scan; }
170 #line 171 "ext/standard/url_scanner_ex.c"
171 yy6:
172 	++YYCURSOR;
173 #line 122 "ext/standard/url_scanner_ex.re"
174 	{ bash = p - 1; goto done; }
175 #line 176 "ext/standard/url_scanner_ex.c"
176 yy8:
177 	++YYCURSOR;
178 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
179 	yych = *YYCURSOR;
180 	if (yybm[0+yych] & 128) {
181 		goto yy8;
182 	}
183 #line 123 "ext/standard/url_scanner_ex.re"
184 	{ goto scan; }
185 #line 186 "ext/standard/url_scanner_ex.c"
186 }
187 #line 124 "ext/standard/url_scanner_ex.re"
188 
189 done:
190 
191 	/* Don't modify URLs of the format "#mark" */
192 	if (bash && bash - url->c == 0) {
193 		smart_str_append(dest, url);
194 		return;
195 	}
196 
197 	if (bash)
198 		smart_str_appendl(dest, url->c, bash - url->c);
199 	else
200 		smart_str_append(dest, url);
201 
202 	smart_str_appends(dest, sep);
203 	smart_str_append(dest, url_app);
204 
205 	if (bash)
206 		smart_str_appendl(dest, bash, q - bash);
207 }
208 
209 
210 #undef YYFILL
211 #undef YYCTYPE
212 #undef YYCURSOR
213 #undef YYLIMIT
214 #undef YYMARKER
215 
tag_arg(url_adapt_state_ex_t * ctx,char quotes,char type TSRMLS_DC)216 static inline void tag_arg(url_adapt_state_ex_t *ctx, char quotes, char type TSRMLS_DC)
217 {
218 	char f = 0;
219 
220 	if (strncasecmp(ctx->arg.c, ctx->lookup_data, ctx->arg.len) == 0)
221 		f = 1;
222 
223 	if (quotes)
224 		smart_str_appendc(&ctx->result, type);
225 	if (f) {
226 		append_modified_url(&ctx->val, &ctx->result, &ctx->url_app, PG(arg_separator).output);
227 	} else {
228 		smart_str_append(&ctx->result, &ctx->val);
229 	}
230 	if (quotes)
231 		smart_str_appendc(&ctx->result, type);
232 }
233 
234 enum {
235 	STATE_PLAIN = 0,
236 	STATE_TAG,
237 	STATE_NEXT_ARG,
238 	STATE_ARG,
239 	STATE_BEFORE_VAL,
240 	STATE_VAL
241 };
242 
243 #define YYFILL(n) goto stop
244 #define YYCTYPE unsigned char
245 #define YYCURSOR xp
246 #define YYLIMIT end
247 #define YYMARKER q
248 #define STATE ctx->state
249 
250 #define STD_PARA url_adapt_state_ex_t *ctx, char *start, char *YYCURSOR TSRMLS_DC
251 #define STD_ARGS ctx, start, xp TSRMLS_CC
252 
253 #if SCANNER_DEBUG
254 #define scdebug(x) printf x
255 #else
256 #define scdebug(x)
257 #endif
258 
passthru(STD_PARA)259 static inline void passthru(STD_PARA)
260 {
261 	scdebug(("appending %d chars, starting with %c\n", YYCURSOR-start, *start));
262 	smart_str_appendl(&ctx->result, start, YYCURSOR - start);
263 }
264 
265 /*
266  * This function appends a hidden input field after a <form> or
267  * <fieldset>.  The latter is important for XHTML.
268  */
269 
handle_form(STD_PARA)270 static void handle_form(STD_PARA)
271 {
272 	int doit = 0;
273 
274 	if (ctx->form_app.len > 0) {
275 		switch (ctx->tag.len) {
276 			case sizeof("form") - 1:
277 				if (!strncasecmp(ctx->tag.c, "form", sizeof("form") - 1)) {
278 					doit = 1;
279 				}
280 				if (doit && ctx->val.c && ctx->lookup_data && *ctx->lookup_data) {
281 					char *e, *p = zend_memnstr(ctx->val.c, "://", sizeof("://") - 1, ctx->val.c + ctx->val.len);
282 					if (p) {
283 						e = memchr(p, '/', (ctx->val.c + ctx->val.len) - p);
284 						if (!e) {
285 							e = ctx->val.c + ctx->val.len;
286 						}
287 						if ((e - p) && strncasecmp(p, ctx->lookup_data, (e - p))) {
288 							doit = 0;
289 						}
290 					}
291 				}
292 				break;
293 
294 			case sizeof("fieldset") - 1:
295 				if (!strncasecmp(ctx->tag.c, "fieldset", sizeof("fieldset") - 1)) {
296 					doit = 1;
297 				}
298 				break;
299 		}
300 
301 		if (doit)
302 			smart_str_append(&ctx->result, &ctx->form_app);
303 	}
304 }
305 
306 /*
307  *  HANDLE_TAG copies the HTML Tag and checks whether we
308  *  have that tag in our table. If we might modify it,
309  *  we continue to scan the tag, otherwise we simply copy the complete
310  *  HTML stuff to the result buffer.
311  */
312 
handle_tag(STD_PARA)313 static inline void handle_tag(STD_PARA)
314 {
315 	int ok = 0;
316 	unsigned int i;
317 
318 	ctx->tag.len = 0;
319 	smart_str_appendl(&ctx->tag, start, YYCURSOR - start);
320 	for (i = 0; i < ctx->tag.len; i++)
321 		ctx->tag.c[i] = tolower((int)(unsigned char)ctx->tag.c[i]);
322 	if (zend_hash_find(ctx->tags, ctx->tag.c, ctx->tag.len, (void **) &ctx->lookup_data) == SUCCESS)
323 		ok = 1;
324 	STATE = ok ? STATE_NEXT_ARG : STATE_PLAIN;
325 }
326 
handle_arg(STD_PARA)327 static inline void handle_arg(STD_PARA)
328 {
329 	ctx->arg.len = 0;
330 	smart_str_appendl(&ctx->arg, start, YYCURSOR - start);
331 }
332 
handle_val(STD_PARA,char quotes,char type)333 static inline void handle_val(STD_PARA, char quotes, char type)
334 {
335 	smart_str_setl(&ctx->val, start + quotes, YYCURSOR - start - quotes * 2);
336 	tag_arg(ctx, quotes, type TSRMLS_CC);
337 }
338 
xx_mainloop(url_adapt_state_ex_t * ctx,const char * newdata,size_t newlen TSRMLS_DC)339 static inline void xx_mainloop(url_adapt_state_ex_t *ctx, const char *newdata, size_t newlen TSRMLS_DC)
340 {
341 	char *end, *q;
342 	char *xp;
343 	char *start;
344 	int rest;
345 
346 	smart_str_appendl(&ctx->buf, newdata, newlen);
347 
348 	YYCURSOR = ctx->buf.c;
349 	YYLIMIT = ctx->buf.c + ctx->buf.len;
350 
351 	switch (STATE) {
352 		case STATE_PLAIN: goto state_plain;
353 		case STATE_TAG: goto state_tag;
354 		case STATE_NEXT_ARG: goto state_next_arg;
355 		case STATE_ARG: goto state_arg;
356 		case STATE_BEFORE_VAL: goto state_before_val;
357 		case STATE_VAL: goto state_val;
358 	}
359 
360 
361 state_plain_begin:
362 	STATE = STATE_PLAIN;
363 
364 state_plain:
365 	start = YYCURSOR;
366 
367 #line 368 "ext/standard/url_scanner_ex.c"
368 {
369 	YYCTYPE yych;
370 	static const unsigned char yybm[] = {
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,   0, 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 		128, 128, 128, 128, 128, 128, 128, 128,
401 		128, 128, 128, 128, 128, 128, 128, 128,
402 		128, 128, 128, 128, 128, 128, 128, 128,
403 	};
404 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
405 	yych = *YYCURSOR;
406 	if (yybm[0+yych] & 128) {
407 		goto yy15;
408 	}
409 	++YYCURSOR;
410 #line 303 "ext/standard/url_scanner_ex.re"
411 	{ passthru(STD_ARGS); STATE = STATE_TAG; goto state_tag; }
412 #line 413 "ext/standard/url_scanner_ex.c"
413 yy15:
414 	++YYCURSOR;
415 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
416 	yych = *YYCURSOR;
417 	if (yybm[0+yych] & 128) {
418 		goto yy15;
419 	}
420 #line 304 "ext/standard/url_scanner_ex.re"
421 	{ passthru(STD_ARGS); goto state_plain; }
422 #line 423 "ext/standard/url_scanner_ex.c"
423 }
424 #line 305 "ext/standard/url_scanner_ex.re"
425 
426 
427 state_tag:
428 	start = YYCURSOR;
429 
430 #line 431 "ext/standard/url_scanner_ex.c"
431 {
432 	YYCTYPE yych;
433 	static const unsigned char yybm[] = {
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, 128,   0,   0,   0,   0,   0,
442 		  0, 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 		128, 128, 128,   0,   0,   0,   0,   0,
446 		  0, 128, 128, 128, 128, 128, 128, 128,
447 		128, 128, 128, 128, 128, 128, 128, 128,
448 		128, 128, 128, 128, 128, 128, 128, 128,
449 		128, 128, 128,   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 		  0,   0,   0,   0,   0,   0,   0,   0,
458 		  0,   0,   0,   0,   0,   0,   0,   0,
459 		  0,   0,   0,   0,   0,   0,   0,   0,
460 		  0,   0,   0,   0,   0,   0,   0,   0,
461 		  0,   0,   0,   0,   0,   0,   0,   0,
462 		  0,   0,   0,   0,   0,   0,   0,   0,
463 		  0,   0,   0,   0,   0,   0,   0,   0,
464 		  0,   0,   0,   0,   0,   0,   0,   0,
465 		  0,   0,   0,   0,   0,   0,   0,   0,
466 	};
467 	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
468 	yych = *YYCURSOR;
469 	if (yych <= '@') {
470 		if (yych != ':') goto yy22;
471 	} else {
472 		if (yych <= 'Z') goto yy20;
473 		if (yych <= '`') goto yy22;
474 		if (yych >= '{') goto yy22;
475 	}
476 yy20:
477 	++YYCURSOR;
478 	yych = *YYCURSOR;
479 	goto yy25;
480 yy21:
481 #line 310 "ext/standard/url_scanner_ex.re"
482 	{ handle_tag(STD_ARGS); /* Sets STATE */; passthru(STD_ARGS); if (STATE == STATE_PLAIN) goto state_plain; else goto state_next_arg; }
483 #line 484 "ext/standard/url_scanner_ex.c"
484 yy22:
485 	++YYCURSOR;
486 #line 311 "ext/standard/url_scanner_ex.re"
487 	{ passthru(STD_ARGS); goto state_plain_begin; }
488 #line 489 "ext/standard/url_scanner_ex.c"
489 yy24:
490 	++YYCURSOR;
491 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
492 	yych = *YYCURSOR;
493 yy25:
494 	if (yybm[0+yych] & 128) {
495 		goto yy24;
496 	}
497 	goto yy21;
498 }
499 #line 312 "ext/standard/url_scanner_ex.re"
500 
501 
502 state_next_arg_begin:
503 	STATE = STATE_NEXT_ARG;
504 
505 state_next_arg:
506 	start = YYCURSOR;
507 
508 #line 509 "ext/standard/url_scanner_ex.c"
509 {
510 	YYCTYPE yych;
511 	static const unsigned char yybm[] = {
512 		  0,   0,   0,   0,   0,   0,   0,   0,
513 		  0, 128, 128, 128,   0, 128,   0,   0,
514 		  0,   0,   0,   0,   0,   0,   0,   0,
515 		  0,   0,   0,   0,   0,   0,   0,   0,
516 		128,   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 		  0,   0,   0,   0,   0,   0,   0,   0,
530 		  0,   0,   0,   0,   0,   0,   0,   0,
531 		  0,   0,   0,   0,   0,   0,   0,   0,
532 		  0,   0,   0,   0,   0,   0,   0,   0,
533 		  0,   0,   0,   0,   0,   0,   0,   0,
534 		  0,   0,   0,   0,   0,   0,   0,   0,
535 		  0,   0,   0,   0,   0,   0,   0,   0,
536 		  0,   0,   0,   0,   0,   0,   0,   0,
537 		  0,   0,   0,   0,   0,   0,   0,   0,
538 		  0,   0,   0,   0,   0,   0,   0,   0,
539 		  0,   0,   0,   0,   0,   0,   0,   0,
540 		  0,   0,   0,   0,   0,   0,   0,   0,
541 		  0,   0,   0,   0,   0,   0,   0,   0,
542 		  0,   0,   0,   0,   0,   0,   0,   0,
543 		  0,   0,   0,   0,   0,   0,   0,   0,
544 	};
545 	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
546 	yych = *YYCURSOR;
547 	if (yych <= '.') {
548 		if (yych <= '\f') {
549 			if (yych <= 0x08) goto yy36;
550 			if (yych <= '\v') goto yy32;
551 			goto yy36;
552 		} else {
553 			if (yych <= '\r') goto yy32;
554 			if (yych == ' ') goto yy32;
555 			goto yy36;
556 		}
557 	} else {
558 		if (yych <= '@') {
559 			if (yych <= '/') goto yy28;
560 			if (yych == '>') goto yy30;
561 			goto yy36;
562 		} else {
563 			if (yych <= 'Z') goto yy34;
564 			if (yych <= '`') goto yy36;
565 			if (yych <= 'z') goto yy34;
566 			goto yy36;
567 		}
568 	}
569 yy28:
570 	++YYCURSOR;
571 	if ((yych = *YYCURSOR) == '>') goto yy39;
572 yy29:
573 #line 323 "ext/standard/url_scanner_ex.re"
574 	{ passthru(STD_ARGS); goto state_plain_begin; }
575 #line 576 "ext/standard/url_scanner_ex.c"
576 yy30:
577 	++YYCURSOR;
578 yy31:
579 #line 320 "ext/standard/url_scanner_ex.re"
580 	{ passthru(STD_ARGS); handle_form(STD_ARGS); goto state_plain_begin; }
581 #line 582 "ext/standard/url_scanner_ex.c"
582 yy32:
583 	++YYCURSOR;
584 	yych = *YYCURSOR;
585 	goto yy38;
586 yy33:
587 #line 321 "ext/standard/url_scanner_ex.re"
588 	{ passthru(STD_ARGS); goto state_next_arg; }
589 #line 590 "ext/standard/url_scanner_ex.c"
590 yy34:
591 	++YYCURSOR;
592 #line 322 "ext/standard/url_scanner_ex.re"
593 	{ --YYCURSOR; STATE = STATE_ARG; goto state_arg; }
594 #line 595 "ext/standard/url_scanner_ex.c"
595 yy36:
596 	yych = *++YYCURSOR;
597 	goto yy29;
598 yy37:
599 	++YYCURSOR;
600 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
601 	yych = *YYCURSOR;
602 yy38:
603 	if (yybm[0+yych] & 128) {
604 		goto yy37;
605 	}
606 	goto yy33;
607 yy39:
608 	++YYCURSOR;
609 	yych = *YYCURSOR;
610 	goto yy31;
611 }
612 #line 324 "ext/standard/url_scanner_ex.re"
613 
614 
615 state_arg:
616 	start = YYCURSOR;
617 
618 #line 619 "ext/standard/url_scanner_ex.c"
619 {
620 	YYCTYPE yych;
621 	static const unsigned char yybm[] = {
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, 128,   0,   0,
628 		  0,   0,   0,   0,   0,   0,   0,   0,
629 		  0,   0,   0,   0,   0,   0,   0,   0,
630 		  0, 128, 128, 128, 128, 128, 128, 128,
631 		128, 128, 128, 128, 128, 128, 128, 128,
632 		128, 128, 128, 128, 128, 128, 128, 128,
633 		128, 128, 128,   0,   0,   0,   0,   0,
634 		  0, 128, 128, 128, 128, 128, 128, 128,
635 		128, 128, 128, 128, 128, 128, 128, 128,
636 		128, 128, 128, 128, 128, 128, 128, 128,
637 		128, 128, 128,   0,   0,   0,   0,   0,
638 		  0,   0,   0,   0,   0,   0,   0,   0,
639 		  0,   0,   0,   0,   0,   0,   0,   0,
640 		  0,   0,   0,   0,   0,   0,   0,   0,
641 		  0,   0,   0,   0,   0,   0,   0,   0,
642 		  0,   0,   0,   0,   0,   0,   0,   0,
643 		  0,   0,   0,   0,   0,   0,   0,   0,
644 		  0,   0,   0,   0,   0,   0,   0,   0,
645 		  0,   0,   0,   0,   0,   0,   0,   0,
646 		  0,   0,   0,   0,   0,   0,   0,   0,
647 		  0,   0,   0,   0,   0,   0,   0,   0,
648 		  0,   0,   0,   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 	};
655 	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
656 	yych = *YYCURSOR;
657 	if (yych <= '@') goto yy44;
658 	if (yych <= 'Z') goto yy42;
659 	if (yych <= '`') goto yy44;
660 	if (yych >= '{') goto yy44;
661 yy42:
662 	++YYCURSOR;
663 	yych = *YYCURSOR;
664 	goto yy47;
665 yy43:
666 #line 329 "ext/standard/url_scanner_ex.re"
667 	{ passthru(STD_ARGS); handle_arg(STD_ARGS); STATE = STATE_BEFORE_VAL; goto state_before_val; }
668 #line 669 "ext/standard/url_scanner_ex.c"
669 yy44:
670 	++YYCURSOR;
671 #line 330 "ext/standard/url_scanner_ex.re"
672 	{ passthru(STD_ARGS); STATE = STATE_NEXT_ARG; goto state_next_arg; }
673 #line 674 "ext/standard/url_scanner_ex.c"
674 yy46:
675 	++YYCURSOR;
676 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
677 	yych = *YYCURSOR;
678 yy47:
679 	if (yybm[0+yych] & 128) {
680 		goto yy46;
681 	}
682 	goto yy43;
683 }
684 #line 331 "ext/standard/url_scanner_ex.re"
685 
686 
687 state_before_val:
688 	start = YYCURSOR;
689 
690 #line 691 "ext/standard/url_scanner_ex.c"
691 {
692 	YYCTYPE yych;
693 	static const unsigned char yybm[] = {
694 		  0,   0,   0,   0,   0,   0,   0,   0,
695 		  0,   0,   0,   0,   0,   0,   0,   0,
696 		  0,   0,   0,   0,   0,   0,   0,   0,
697 		  0,   0,   0,   0,   0,   0,   0,   0,
698 		128,   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 		  0,   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 	};
727 	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
728 	yych = *YYCURSOR;
729 	if (yych == ' ') goto yy50;
730 	if (yych == '=') goto yy52;
731 	goto yy54;
732 yy50:
733 	yych = *(YYMARKER = ++YYCURSOR);
734 	if (yych == ' ') goto yy57;
735 	if (yych == '=') goto yy55;
736 yy51:
737 #line 337 "ext/standard/url_scanner_ex.re"
738 	{ --YYCURSOR; goto state_next_arg_begin; }
739 #line 740 "ext/standard/url_scanner_ex.c"
740 yy52:
741 	++YYCURSOR;
742 	yych = *YYCURSOR;
743 	goto yy56;
744 yy53:
745 #line 336 "ext/standard/url_scanner_ex.re"
746 	{ passthru(STD_ARGS); STATE = STATE_VAL; goto state_val; }
747 #line 748 "ext/standard/url_scanner_ex.c"
748 yy54:
749 	yych = *++YYCURSOR;
750 	goto yy51;
751 yy55:
752 	++YYCURSOR;
753 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
754 	yych = *YYCURSOR;
755 yy56:
756 	if (yybm[0+yych] & 128) {
757 		goto yy55;
758 	}
759 	goto yy53;
760 yy57:
761 	++YYCURSOR;
762 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
763 	yych = *YYCURSOR;
764 	if (yych == ' ') goto yy57;
765 	if (yych == '=') goto yy55;
766 	YYCURSOR = YYMARKER;
767 	goto yy51;
768 }
769 #line 338 "ext/standard/url_scanner_ex.re"
770 
771 
772 
773 state_val:
774 	start = YYCURSOR;
775 
776 #line 777 "ext/standard/url_scanner_ex.c"
777 {
778 	YYCTYPE yych;
779 	static const unsigned char yybm[] = {
780 		224, 224, 224, 224, 224, 224, 224, 224,
781 		224, 192, 192, 224, 224, 192, 224, 224,
782 		224, 224, 224, 224, 224, 224, 224, 224,
783 		224, 224, 224, 224, 224, 224, 224, 224,
784 		192, 224,  64, 224, 224, 224, 224, 128,
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,   0, 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 		224, 224, 224, 224, 224, 224, 224, 224,
807 		224, 224, 224, 224, 224, 224, 224, 224,
808 		224, 224, 224, 224, 224, 224, 224, 224,
809 		224, 224, 224, 224, 224, 224, 224, 224,
810 		224, 224, 224, 224, 224, 224, 224, 224,
811 		224, 224, 224, 224, 224, 224, 224, 224,
812 	};
813 	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
814 	yych = *YYCURSOR;
815 	if (yych <= ' ') {
816 		if (yych <= '\f') {
817 			if (yych <= 0x08) goto yy65;
818 			if (yych <= '\n') goto yy67;
819 			goto yy65;
820 		} else {
821 			if (yych <= '\r') goto yy67;
822 			if (yych <= 0x1F) goto yy65;
823 			goto yy67;
824 		}
825 	} else {
826 		if (yych <= '&') {
827 			if (yych != '"') goto yy65;
828 		} else {
829 			if (yych <= '\'') goto yy64;
830 			if (yych == '>') goto yy67;
831 			goto yy65;
832 		}
833 	}
834 	yych = *(YYMARKER = ++YYCURSOR);
835 	if (yych != '>') goto yy76;
836 yy63:
837 #line 347 "ext/standard/url_scanner_ex.re"
838 	{ passthru(STD_ARGS); goto state_next_arg_begin; }
839 #line 840 "ext/standard/url_scanner_ex.c"
840 yy64:
841 	yych = *(YYMARKER = ++YYCURSOR);
842 	if (yych == '>') goto yy63;
843 	goto yy71;
844 yy65:
845 	++YYCURSOR;
846 	yych = *YYCURSOR;
847 	goto yy69;
848 yy66:
849 #line 346 "ext/standard/url_scanner_ex.re"
850 	{ handle_val(STD_ARGS, 0, ' '); goto state_next_arg_begin; }
851 #line 852 "ext/standard/url_scanner_ex.c"
852 yy67:
853 	yych = *++YYCURSOR;
854 	goto yy63;
855 yy68:
856 	++YYCURSOR;
857 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
858 	yych = *YYCURSOR;
859 yy69:
860 	if (yybm[0+yych] & 32) {
861 		goto yy68;
862 	}
863 	goto yy66;
864 yy70:
865 	++YYCURSOR;
866 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
867 	yych = *YYCURSOR;
868 yy71:
869 	if (yybm[0+yych] & 64) {
870 		goto yy70;
871 	}
872 	if (yych <= '=') goto yy73;
873 yy72:
874 	YYCURSOR = YYMARKER;
875 	goto yy63;
876 yy73:
877 	++YYCURSOR;
878 #line 345 "ext/standard/url_scanner_ex.re"
879 	{ handle_val(STD_ARGS, 1, '\''); goto state_next_arg_begin; }
880 #line 881 "ext/standard/url_scanner_ex.c"
881 yy75:
882 	++YYCURSOR;
883 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
884 	yych = *YYCURSOR;
885 yy76:
886 	if (yybm[0+yych] & 128) {
887 		goto yy75;
888 	}
889 	if (yych >= '>') goto yy72;
890 	++YYCURSOR;
891 #line 344 "ext/standard/url_scanner_ex.re"
892 	{ handle_val(STD_ARGS, 1, '"'); goto state_next_arg_begin; }
893 #line 894 "ext/standard/url_scanner_ex.c"
894 }
895 #line 348 "ext/standard/url_scanner_ex.re"
896 
897 
898 stop:
899 	rest = YYLIMIT - start;
900 	scdebug(("stopped in state %d at pos %d (%d:%c) %d\n", STATE, YYCURSOR - ctx->buf.c, *YYCURSOR, *YYCURSOR, rest));
901 	/* XXX: Crash avoidance. Need to work with reporter to figure out what goes wrong */
902 	if (rest < 0) rest = 0;
903 
904 	if (rest) memmove(ctx->buf.c, start, rest);
905 	ctx->buf.len = rest;
906 }
907 
php_url_scanner_adapt_single_url(const char * url,size_t urllen,const char * name,const char * value,size_t * newlen TSRMLS_DC)908 char *php_url_scanner_adapt_single_url(const char *url, size_t urllen, const char *name, const char *value, size_t *newlen TSRMLS_DC)
909 {
910 	smart_str surl = {0};
911 	smart_str buf = {0};
912 	smart_str url_app = {0};
913 
914 	smart_str_setl(&surl, url, urllen);
915 
916 	smart_str_appends(&url_app, name);
917 	smart_str_appendc(&url_app, '=');
918 	smart_str_appends(&url_app, value);
919 
920 	append_modified_url(&surl, &buf, &url_app, PG(arg_separator).output);
921 
922 	smart_str_0(&buf);
923 	if (newlen) *newlen = buf.len;
924 
925 	smart_str_free(&url_app);
926 
927 	return buf.c;
928 }
929 
930 
url_adapt_ext(const char * src,size_t srclen,size_t * newlen,zend_bool do_flush TSRMLS_DC)931 static char *url_adapt_ext(const char *src, size_t srclen, size_t *newlen, zend_bool do_flush TSRMLS_DC)
932 {
933 	url_adapt_state_ex_t *ctx;
934 	char *retval;
935 
936 	ctx = &BG(url_adapt_state_ex);
937 
938 	xx_mainloop(ctx, src, srclen TSRMLS_CC);
939 
940 	*newlen = ctx->result.len;
941 	if (!ctx->result.c) {
942 		smart_str_appendl(&ctx->result, "", 0);
943 	}
944 	smart_str_0(&ctx->result);
945 	if (do_flush) {
946 		smart_str_appendl(&ctx->result, ctx->buf.c, ctx->buf.len);
947 		*newlen += ctx->buf.len;
948 		smart_str_free(&ctx->buf);
949 	}
950 	retval = ctx->result.c;
951 	ctx->result.c = NULL;
952 	ctx->result.len = 0;
953 	return retval;
954 }
955 
php_url_scanner_ex_activate(TSRMLS_D)956 static int php_url_scanner_ex_activate(TSRMLS_D)
957 {
958 	url_adapt_state_ex_t *ctx;
959 
960 	ctx = &BG(url_adapt_state_ex);
961 
962 	memset(ctx, 0, ((size_t) &((url_adapt_state_ex_t *)0)->tags));
963 
964 	return SUCCESS;
965 }
966 
php_url_scanner_ex_deactivate(TSRMLS_D)967 static int php_url_scanner_ex_deactivate(TSRMLS_D)
968 {
969 	url_adapt_state_ex_t *ctx;
970 
971 	ctx = &BG(url_adapt_state_ex);
972 
973 	smart_str_free(&ctx->result);
974 	smart_str_free(&ctx->buf);
975 	smart_str_free(&ctx->tag);
976 	smart_str_free(&ctx->arg);
977 
978 	return SUCCESS;
979 }
980 
php_url_scanner_output_handler(char * output,uint output_len,char ** handled_output,uint * handled_output_len,int mode TSRMLS_DC)981 static void php_url_scanner_output_handler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC)
982 {
983 	size_t len;
984 
985 	if (BG(url_adapt_state_ex).url_app.len != 0) {
986 		*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);
987 		if (sizeof(uint) < sizeof(size_t)) {
988 			if (len > UINT_MAX)
989 				len = UINT_MAX;
990 		}
991 		*handled_output_len = len;
992 	} else if (BG(url_adapt_state_ex).url_app.len == 0) {
993 		url_adapt_state_ex_t *ctx = &BG(url_adapt_state_ex);
994 		if (ctx->buf.len) {
995 			smart_str_appendl(&ctx->result, ctx->buf.c, ctx->buf.len);
996 			smart_str_appendl(&ctx->result, output, output_len);
997 
998 			*handled_output = ctx->result.c;
999 			*handled_output_len = ctx->buf.len + output_len;
1000 
1001 			ctx->result.c = NULL;
1002 			ctx->result.len = 0;
1003 			smart_str_free(&ctx->buf);
1004 		} else {
1005 			*handled_output = estrndup(output, *handled_output_len = output_len);
1006 		}
1007 	} else {
1008 		*handled_output = NULL;
1009 	}
1010 }
1011 
php_url_scanner_add_var(char * name,int name_len,char * value,int value_len,int urlencode TSRMLS_DC)1012 PHPAPI int php_url_scanner_add_var(char *name, int name_len, char *value, int value_len, int urlencode TSRMLS_DC)
1013 {
1014 	char *encoded = NULL;
1015 	int encoded_len;
1016 	smart_str val;
1017 
1018 	if (! BG(url_adapt_state_ex).active) {
1019 		php_url_scanner_ex_activate(TSRMLS_C);
1020 		php_output_start_internal(ZEND_STRL("URL-Rewriter"), php_url_scanner_output_handler, 0, PHP_OUTPUT_HANDLER_STDFLAGS TSRMLS_CC);
1021 		BG(url_adapt_state_ex).active = 1;
1022 	}
1023 
1024 
1025 	if (BG(url_adapt_state_ex).url_app.len != 0) {
1026 		smart_str_appends(&BG(url_adapt_state_ex).url_app, PG(arg_separator).output);
1027 	}
1028 
1029 	if (urlencode) {
1030 		encoded = php_url_encode(value, value_len, &encoded_len);
1031 		smart_str_setl(&val, encoded, encoded_len);
1032 	} else {
1033 		smart_str_setl(&val, value, value_len);
1034 	}
1035 
1036 	smart_str_appendl(&BG(url_adapt_state_ex).url_app, name, name_len);
1037 	smart_str_appendc(&BG(url_adapt_state_ex).url_app, '=');
1038 	smart_str_append(&BG(url_adapt_state_ex).url_app, &val);
1039 
1040 	smart_str_appends(&BG(url_adapt_state_ex).form_app, "<input type=\"hidden\" name=\"");
1041 	smart_str_appendl(&BG(url_adapt_state_ex).form_app, name, name_len);
1042 	smart_str_appends(&BG(url_adapt_state_ex).form_app, "\" value=\"");
1043 	smart_str_append(&BG(url_adapt_state_ex).form_app, &val);
1044 	smart_str_appends(&BG(url_adapt_state_ex).form_app, "\" />");
1045 
1046 	if (urlencode)
1047 		efree(encoded);
1048 
1049 	return SUCCESS;
1050 }
1051 
php_url_scanner_reset_vars(TSRMLS_D)1052 PHPAPI int php_url_scanner_reset_vars(TSRMLS_D)
1053 {
1054 	BG(url_adapt_state_ex).form_app.len = 0;
1055 	BG(url_adapt_state_ex).url_app.len = 0;
1056 
1057 	return SUCCESS;
1058 }
1059 
PHP_MINIT_FUNCTION(url_scanner)1060 PHP_MINIT_FUNCTION(url_scanner)
1061 {
1062 	BG(url_adapt_state_ex).tags = NULL;
1063 
1064 	BG(url_adapt_state_ex).form_app.c = BG(url_adapt_state_ex).url_app.c = 0;
1065 	BG(url_adapt_state_ex).form_app.len = BG(url_adapt_state_ex).url_app.len = 0;
1066 
1067 	REGISTER_INI_ENTRIES();
1068 	return SUCCESS;
1069 }
1070 
PHP_MSHUTDOWN_FUNCTION(url_scanner)1071 PHP_MSHUTDOWN_FUNCTION(url_scanner)
1072 {
1073 	UNREGISTER_INI_ENTRIES();
1074 
1075 	return SUCCESS;
1076 }
1077 
PHP_RINIT_FUNCTION(url_scanner)1078 PHP_RINIT_FUNCTION(url_scanner)
1079 {
1080 	BG(url_adapt_state_ex).active = 0;
1081 
1082 	return SUCCESS;
1083 }
1084 
PHP_RSHUTDOWN_FUNCTION(url_scanner)1085 PHP_RSHUTDOWN_FUNCTION(url_scanner)
1086 {
1087 	if (BG(url_adapt_state_ex).active) {
1088 		php_url_scanner_ex_deactivate(TSRMLS_C);
1089 		BG(url_adapt_state_ex).active = 0;
1090 	}
1091 
1092 	smart_str_free(&BG(url_adapt_state_ex).form_app);
1093 	smart_str_free(&BG(url_adapt_state_ex).url_app);
1094 
1095 	return SUCCESS;
1096 }
1097