xref: /PHP-5.4/ext/standard/url_scanner_ex.c (revision c0d060f5)
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-2014 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 yy34;
550 			if (yych <= '\v') goto yy30;
551 			goto yy34;
552 		} else {
553 			if (yych <= '\r') goto yy30;
554 			if (yych <= 0x1F) goto yy34;
555 			goto yy30;
556 		}
557 	} else {
558 		if (yych <= '@') {
559 			if (yych != '>') goto yy34;
560 		} else {
561 			if (yych <= 'Z') goto yy32;
562 			if (yych <= '`') goto yy34;
563 			if (yych <= 'z') goto yy32;
564 			goto yy34;
565 		}
566 	}
567 	++YYCURSOR;
568 #line 320 "ext/standard/url_scanner_ex.re"
569 	{ passthru(STD_ARGS); handle_form(STD_ARGS); goto state_plain_begin; }
570 #line 571 "ext/standard/url_scanner_ex.c"
571 yy30:
572 	++YYCURSOR;
573 	yych = *YYCURSOR;
574 	goto yy37;
575 yy31:
576 #line 321 "ext/standard/url_scanner_ex.re"
577 	{ passthru(STD_ARGS); goto state_next_arg; }
578 #line 579 "ext/standard/url_scanner_ex.c"
579 yy32:
580 	++YYCURSOR;
581 #line 322 "ext/standard/url_scanner_ex.re"
582 	{ --YYCURSOR; STATE = STATE_ARG; goto state_arg; }
583 #line 584 "ext/standard/url_scanner_ex.c"
584 yy34:
585 	++YYCURSOR;
586 #line 323 "ext/standard/url_scanner_ex.re"
587 	{ passthru(STD_ARGS); goto state_plain_begin; }
588 #line 589 "ext/standard/url_scanner_ex.c"
589 yy36:
590 	++YYCURSOR;
591 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
592 	yych = *YYCURSOR;
593 yy37:
594 	if (yybm[0+yych] & 128) {
595 		goto yy36;
596 	}
597 	goto yy31;
598 }
599 #line 324 "ext/standard/url_scanner_ex.re"
600 
601 
602 state_arg:
603 	start = YYCURSOR;
604 
605 #line 606 "ext/standard/url_scanner_ex.c"
606 {
607 	YYCTYPE yych;
608 	static const unsigned char yybm[] = {
609 		  0,   0,   0,   0,   0,   0,   0,   0,
610 		  0,   0,   0,   0,   0,   0,   0,   0,
611 		  0,   0,   0,   0,   0,   0,   0,   0,
612 		  0,   0,   0,   0,   0,   0,   0,   0,
613 		  0,   0,   0,   0,   0,   0,   0,   0,
614 		  0,   0,   0,   0,   0, 128,   0,   0,
615 		  0,   0,   0,   0,   0,   0,   0,   0,
616 		  0,   0,   0,   0,   0,   0,   0,   0,
617 		  0, 128, 128, 128, 128, 128, 128, 128,
618 		128, 128, 128, 128, 128, 128, 128, 128,
619 		128, 128, 128, 128, 128, 128, 128, 128,
620 		128, 128, 128,   0,   0,   0,   0,   0,
621 		  0, 128, 128, 128, 128, 128, 128, 128,
622 		128, 128, 128, 128, 128, 128, 128, 128,
623 		128, 128, 128, 128, 128, 128, 128, 128,
624 		128, 128, 128,   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 		  0,   0,   0,   0,   0,   0,   0,   0,
630 		  0,   0,   0,   0,   0,   0,   0,   0,
631 		  0,   0,   0,   0,   0,   0,   0,   0,
632 		  0,   0,   0,   0,   0,   0,   0,   0,
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,   0,   0,   0,
639 		  0,   0,   0,   0,   0,   0,   0,   0,
640 		  0,   0,   0,   0,   0,   0,   0,   0,
641 	};
642 	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
643 	yych = *YYCURSOR;
644 	if (yych <= '@') goto yy42;
645 	if (yych <= 'Z') goto yy40;
646 	if (yych <= '`') goto yy42;
647 	if (yych >= '{') goto yy42;
648 yy40:
649 	++YYCURSOR;
650 	yych = *YYCURSOR;
651 	goto yy45;
652 yy41:
653 #line 329 "ext/standard/url_scanner_ex.re"
654 	{ passthru(STD_ARGS); handle_arg(STD_ARGS); STATE = STATE_BEFORE_VAL; goto state_before_val; }
655 #line 656 "ext/standard/url_scanner_ex.c"
656 yy42:
657 	++YYCURSOR;
658 #line 330 "ext/standard/url_scanner_ex.re"
659 	{ passthru(STD_ARGS); STATE = STATE_NEXT_ARG; goto state_next_arg; }
660 #line 661 "ext/standard/url_scanner_ex.c"
661 yy44:
662 	++YYCURSOR;
663 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
664 	yych = *YYCURSOR;
665 yy45:
666 	if (yybm[0+yych] & 128) {
667 		goto yy44;
668 	}
669 	goto yy41;
670 }
671 #line 331 "ext/standard/url_scanner_ex.re"
672 
673 
674 state_before_val:
675 	start = YYCURSOR;
676 
677 #line 678 "ext/standard/url_scanner_ex.c"
678 {
679 	YYCTYPE yych;
680 	static const unsigned char yybm[] = {
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 		128,   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 		  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 		  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 		  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 	};
714 	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
715 	yych = *YYCURSOR;
716 	if (yych == ' ') goto yy48;
717 	if (yych == '=') goto yy50;
718 	goto yy52;
719 yy48:
720 	yych = *(YYMARKER = ++YYCURSOR);
721 	if (yych == ' ') goto yy55;
722 	if (yych == '=') goto yy53;
723 yy49:
724 #line 337 "ext/standard/url_scanner_ex.re"
725 	{ --YYCURSOR; goto state_next_arg_begin; }
726 #line 727 "ext/standard/url_scanner_ex.c"
727 yy50:
728 	++YYCURSOR;
729 	yych = *YYCURSOR;
730 	goto yy54;
731 yy51:
732 #line 336 "ext/standard/url_scanner_ex.re"
733 	{ passthru(STD_ARGS); STATE = STATE_VAL; goto state_val; }
734 #line 735 "ext/standard/url_scanner_ex.c"
735 yy52:
736 	yych = *++YYCURSOR;
737 	goto yy49;
738 yy53:
739 	++YYCURSOR;
740 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
741 	yych = *YYCURSOR;
742 yy54:
743 	if (yybm[0+yych] & 128) {
744 		goto yy53;
745 	}
746 	goto yy51;
747 yy55:
748 	++YYCURSOR;
749 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
750 	yych = *YYCURSOR;
751 	if (yych == ' ') goto yy55;
752 	if (yych == '=') goto yy53;
753 	YYCURSOR = YYMARKER;
754 	goto yy49;
755 }
756 #line 338 "ext/standard/url_scanner_ex.re"
757 
758 
759 
760 state_val:
761 	start = YYCURSOR;
762 
763 #line 764 "ext/standard/url_scanner_ex.c"
764 {
765 	YYCTYPE yych;
766 	static const unsigned char yybm[] = {
767 		224, 224, 224, 224, 224, 224, 224, 224,
768 		224, 192, 192, 224, 224, 192, 224, 224,
769 		224, 224, 224, 224, 224, 224, 224, 224,
770 		224, 224, 224, 224, 224, 224, 224, 224,
771 		192, 224,  64, 224, 224, 224, 224, 128,
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,   0, 224,
775 		224, 224, 224, 224, 224, 224, 224, 224,
776 		224, 224, 224, 224, 224, 224, 224, 224,
777 		224, 224, 224, 224, 224, 224, 224, 224,
778 		224, 224, 224, 224, 224, 224, 224, 224,
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, 224, 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 	};
800 	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
801 	yych = *YYCURSOR;
802 	if (yych <= ' ') {
803 		if (yych <= '\f') {
804 			if (yych <= 0x08) goto yy63;
805 			if (yych <= '\n') goto yy65;
806 			goto yy63;
807 		} else {
808 			if (yych <= '\r') goto yy65;
809 			if (yych <= 0x1F) goto yy63;
810 			goto yy65;
811 		}
812 	} else {
813 		if (yych <= '&') {
814 			if (yych != '"') goto yy63;
815 		} else {
816 			if (yych <= '\'') goto yy62;
817 			if (yych == '>') goto yy65;
818 			goto yy63;
819 		}
820 	}
821 	yych = *(YYMARKER = ++YYCURSOR);
822 	if (yych != '>') goto yy74;
823 yy61:
824 #line 347 "ext/standard/url_scanner_ex.re"
825 	{ passthru(STD_ARGS); goto state_next_arg_begin; }
826 #line 827 "ext/standard/url_scanner_ex.c"
827 yy62:
828 	yych = *(YYMARKER = ++YYCURSOR);
829 	if (yych == '>') goto yy61;
830 	goto yy69;
831 yy63:
832 	++YYCURSOR;
833 	yych = *YYCURSOR;
834 	goto yy67;
835 yy64:
836 #line 346 "ext/standard/url_scanner_ex.re"
837 	{ handle_val(STD_ARGS, 0, ' '); goto state_next_arg_begin; }
838 #line 839 "ext/standard/url_scanner_ex.c"
839 yy65:
840 	yych = *++YYCURSOR;
841 	goto yy61;
842 yy66:
843 	++YYCURSOR;
844 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
845 	yych = *YYCURSOR;
846 yy67:
847 	if (yybm[0+yych] & 32) {
848 		goto yy66;
849 	}
850 	goto yy64;
851 yy68:
852 	++YYCURSOR;
853 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
854 	yych = *YYCURSOR;
855 yy69:
856 	if (yybm[0+yych] & 64) {
857 		goto yy68;
858 	}
859 	if (yych <= '=') goto yy71;
860 yy70:
861 	YYCURSOR = YYMARKER;
862 	goto yy61;
863 yy71:
864 	++YYCURSOR;
865 #line 345 "ext/standard/url_scanner_ex.re"
866 	{ handle_val(STD_ARGS, 1, '\''); goto state_next_arg_begin; }
867 #line 868 "ext/standard/url_scanner_ex.c"
868 yy73:
869 	++YYCURSOR;
870 	if (YYLIMIT <= YYCURSOR) YYFILL(1);
871 	yych = *YYCURSOR;
872 yy74:
873 	if (yybm[0+yych] & 128) {
874 		goto yy73;
875 	}
876 	if (yych >= '>') goto yy70;
877 	++YYCURSOR;
878 #line 344 "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 }
882 #line 348 "ext/standard/url_scanner_ex.re"
883 
884 
885 stop:
886 	rest = YYLIMIT - start;
887 	scdebug(("stopped in state %d at pos %d (%d:%c) %d\n", STATE, YYCURSOR - ctx->buf.c, *YYCURSOR, *YYCURSOR, rest));
888 	/* XXX: Crash avoidance. Need to work with reporter to figure out what goes wrong */
889 	if (rest < 0) rest = 0;
890 
891 	if (rest) memmove(ctx->buf.c, start, rest);
892 	ctx->buf.len = rest;
893 }
894 
php_url_scanner_adapt_single_url(const char * url,size_t urllen,const char * name,const char * value,size_t * newlen TSRMLS_DC)895 char *php_url_scanner_adapt_single_url(const char *url, size_t urllen, const char *name, const char *value, size_t *newlen TSRMLS_DC)
896 {
897 	smart_str surl = {0};
898 	smart_str buf = {0};
899 	smart_str url_app = {0};
900 
901 	smart_str_setl(&surl, url, urllen);
902 
903 	smart_str_appends(&url_app, name);
904 	smart_str_appendc(&url_app, '=');
905 	smart_str_appends(&url_app, value);
906 
907 	append_modified_url(&surl, &buf, &url_app, PG(arg_separator).output);
908 
909 	smart_str_0(&buf);
910 	if (newlen) *newlen = buf.len;
911 
912 	smart_str_free(&url_app);
913 
914 	return buf.c;
915 }
916 
917 
url_adapt_ext(const char * src,size_t srclen,size_t * newlen,zend_bool do_flush TSRMLS_DC)918 static char *url_adapt_ext(const char *src, size_t srclen, size_t *newlen, zend_bool do_flush TSRMLS_DC)
919 {
920 	url_adapt_state_ex_t *ctx;
921 	char *retval;
922 
923 	ctx = &BG(url_adapt_state_ex);
924 
925 	xx_mainloop(ctx, src, srclen TSRMLS_CC);
926 
927 	*newlen = ctx->result.len;
928 	if (!ctx->result.c) {
929 		smart_str_appendl(&ctx->result, "", 0);
930 	}
931 	smart_str_0(&ctx->result);
932 	if (do_flush) {
933 		smart_str_appendl(&ctx->result, ctx->buf.c, ctx->buf.len);
934 		*newlen += ctx->buf.len;
935 		smart_str_free(&ctx->buf);
936 	}
937 	retval = ctx->result.c;
938 	ctx->result.c = NULL;
939 	ctx->result.len = 0;
940 	return retval;
941 }
942 
php_url_scanner_ex_activate(TSRMLS_D)943 static int php_url_scanner_ex_activate(TSRMLS_D)
944 {
945 	url_adapt_state_ex_t *ctx;
946 
947 	ctx = &BG(url_adapt_state_ex);
948 
949 	memset(ctx, 0, ((size_t) &((url_adapt_state_ex_t *)0)->tags));
950 
951 	return SUCCESS;
952 }
953 
php_url_scanner_ex_deactivate(TSRMLS_D)954 static int php_url_scanner_ex_deactivate(TSRMLS_D)
955 {
956 	url_adapt_state_ex_t *ctx;
957 
958 	ctx = &BG(url_adapt_state_ex);
959 
960 	smart_str_free(&ctx->result);
961 	smart_str_free(&ctx->buf);
962 	smart_str_free(&ctx->tag);
963 	smart_str_free(&ctx->arg);
964 
965 	return SUCCESS;
966 }
967 
php_url_scanner_output_handler(char * output,uint output_len,char ** handled_output,uint * handled_output_len,int mode TSRMLS_DC)968 static void php_url_scanner_output_handler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC)
969 {
970 	size_t len;
971 
972 	if (BG(url_adapt_state_ex).url_app.len != 0) {
973 		*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);
974 		if (sizeof(uint) < sizeof(size_t)) {
975 			if (len > UINT_MAX)
976 				len = UINT_MAX;
977 		}
978 		*handled_output_len = len;
979 	} else if (BG(url_adapt_state_ex).url_app.len == 0) {
980 		url_adapt_state_ex_t *ctx = &BG(url_adapt_state_ex);
981 		if (ctx->buf.len) {
982 			smart_str_appendl(&ctx->result, ctx->buf.c, ctx->buf.len);
983 			smart_str_appendl(&ctx->result, output, output_len);
984 
985 			*handled_output = ctx->result.c;
986 			*handled_output_len = ctx->buf.len + output_len;
987 
988 			ctx->result.c = NULL;
989 			ctx->result.len = 0;
990 			smart_str_free(&ctx->buf);
991 		} else {
992 			*handled_output = estrndup(output, *handled_output_len = output_len);
993 		}
994 	} else {
995 		*handled_output = NULL;
996 	}
997 }
998 
php_url_scanner_add_var(char * name,int name_len,char * value,int value_len,int urlencode TSRMLS_DC)999 PHPAPI int php_url_scanner_add_var(char *name, int name_len, char *value, int value_len, int urlencode TSRMLS_DC)
1000 {
1001 	char *encoded;
1002 	int encoded_len;
1003 	smart_str val;
1004 
1005 	if (! BG(url_adapt_state_ex).active) {
1006 		php_url_scanner_ex_activate(TSRMLS_C);
1007 		php_output_start_internal(ZEND_STRL("URL-Rewriter"), php_url_scanner_output_handler, 0, PHP_OUTPUT_HANDLER_STDFLAGS TSRMLS_CC);
1008 		BG(url_adapt_state_ex).active = 1;
1009 	}
1010 
1011 
1012 	if (BG(url_adapt_state_ex).url_app.len != 0) {
1013 		smart_str_appends(&BG(url_adapt_state_ex).url_app, PG(arg_separator).output);
1014 	}
1015 
1016 	if (urlencode) {
1017 		encoded = php_url_encode(value, value_len, &encoded_len);
1018 		smart_str_setl(&val, encoded, encoded_len);
1019 	} else {
1020 		smart_str_setl(&val, value, value_len);
1021 	}
1022 
1023 	smart_str_appendl(&BG(url_adapt_state_ex).url_app, name, name_len);
1024 	smart_str_appendc(&BG(url_adapt_state_ex).url_app, '=');
1025 	smart_str_append(&BG(url_adapt_state_ex).url_app, &val);
1026 
1027 	smart_str_appends(&BG(url_adapt_state_ex).form_app, "<input type=\"hidden\" name=\"");
1028 	smart_str_appendl(&BG(url_adapt_state_ex).form_app, name, name_len);
1029 	smart_str_appends(&BG(url_adapt_state_ex).form_app, "\" value=\"");
1030 	smart_str_append(&BG(url_adapt_state_ex).form_app, &val);
1031 	smart_str_appends(&BG(url_adapt_state_ex).form_app, "\" />");
1032 
1033 	if (urlencode)
1034 		efree(encoded);
1035 
1036 	return SUCCESS;
1037 }
1038 
php_url_scanner_reset_vars(TSRMLS_D)1039 PHPAPI int php_url_scanner_reset_vars(TSRMLS_D)
1040 {
1041 	BG(url_adapt_state_ex).form_app.len = 0;
1042 	BG(url_adapt_state_ex).url_app.len = 0;
1043 
1044 	return SUCCESS;
1045 }
1046 
PHP_MINIT_FUNCTION(url_scanner)1047 PHP_MINIT_FUNCTION(url_scanner)
1048 {
1049 	BG(url_adapt_state_ex).tags = NULL;
1050 
1051 	BG(url_adapt_state_ex).form_app.c = BG(url_adapt_state_ex).url_app.c = 0;
1052 	BG(url_adapt_state_ex).form_app.len = BG(url_adapt_state_ex).url_app.len = 0;
1053 
1054 	REGISTER_INI_ENTRIES();
1055 	return SUCCESS;
1056 }
1057 
PHP_MSHUTDOWN_FUNCTION(url_scanner)1058 PHP_MSHUTDOWN_FUNCTION(url_scanner)
1059 {
1060 	UNREGISTER_INI_ENTRIES();
1061 
1062 	return SUCCESS;
1063 }
1064 
PHP_RINIT_FUNCTION(url_scanner)1065 PHP_RINIT_FUNCTION(url_scanner)
1066 {
1067 	BG(url_adapt_state_ex).active = 0;
1068 
1069 	return SUCCESS;
1070 }
1071 
PHP_RSHUTDOWN_FUNCTION(url_scanner)1072 PHP_RSHUTDOWN_FUNCTION(url_scanner)
1073 {
1074 	if (BG(url_adapt_state_ex).active) {
1075 		php_url_scanner_ex_deactivate(TSRMLS_C);
1076 		BG(url_adapt_state_ex).active = 0;
1077 	}
1078 
1079 	smart_str_free(&BG(url_adapt_state_ex).form_app);
1080 	smart_str_free(&BG(url_adapt_state_ex).url_app);
1081 
1082 	return SUCCESS;
1083 }
1084