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