PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - lcov_data/ext/standard - url_scanner_ex.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 107 136 78.7 %
Date: 2022-01-23 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Generated by re2c 0.16 */
       2             : #line 1 "ext/standard/url_scanner_ex.re"
       3             : /*
       4             :   +----------------------------------------------------------------------+
       5             :   | PHP Version 7                                                        |
       6             :   +----------------------------------------------------------------------+
       7             :   | Copyright (c) 1997-2018 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             :   |         Yasuo Ohgaki <yohgaki@ohgaki.net>                            |
      19             :   +----------------------------------------------------------------------+
      20             : */
      21             : 
      22             : /* $Id$ */
      23             : 
      24             : #include "php.h"
      25             : 
      26             : #ifdef HAVE_UNISTD_H
      27             : #include <unistd.h>
      28             : #endif
      29             : #ifdef HAVE_LIMITS_H
      30             : #include <limits.h>
      31             : #endif
      32             : 
      33             : #include <stdio.h>
      34             : #include <stdlib.h>
      35             : #include <string.h>
      36             : 
      37             : #include "SAPI.h"
      38             : #include "php_ini.h"
      39             : #include "php_globals.h"
      40             : #include "php_string.h"
      41             : #define STATE_TAG SOME_OTHER_STATE_TAG
      42             : #include "basic_functions.h"
      43             : #include "url.h"
      44             : #include "html.h"
      45             : #undef STATE_TAG
      46             : 
      47             : #define url_scanner url_scanner_ex
      48             : 
      49             : #include "zend_smart_str.h"
      50             : 
      51             : static void tag_dtor(zval *zv)
      52             : {
      53             :         free(Z_PTR_P(zv));
      54             : }
      55             : 
      56             : static int php_ini_on_update_tags(zend_ini_entry *entry, zend_string *new_value, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage, int type)
      57             : {
      58             :         url_adapt_state_ex_t *ctx;
      59             :         char *key;
      60             :         char *tmp;
      61             :         char *lasts = NULL;
      62             : 
      63             :         if (type) {
      64             :                 ctx = &BG(url_adapt_session_ex);
      65             :         } else {
      66             :                 ctx = &BG(url_adapt_output_ex);
      67             :         }
      68             : 
      69             :         tmp = estrndup(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
      70             : 
      71             :         if (ctx->tags)
      72             :                 zend_hash_destroy(ctx->tags);
      73             :         else {
      74             :                 ctx->tags = malloc(sizeof(HashTable));
      75             :                 if (!ctx->tags) {
      76             :                         efree(tmp);
      77             :                         return FAILURE;
      78             :                 }
      79             :         }
      80             : 
      81             :         zend_hash_init(ctx->tags, 0, NULL, tag_dtor, 1);
      82             : 
      83             :         for (key = php_strtok_r(tmp, ",", &lasts);
      84             :                  key;
      85             :                  key = php_strtok_r(NULL, ",", &lasts)) {
      86             :                 char *val;
      87             : 
      88             :                 val = strchr(key, '=');
      89             :                 if (val) {
      90             :                         char *q;
      91             :                         size_t keylen;
      92             : 
      93             :                         *val++ = '\0';
      94             :                         for (q = key; *q; q++) {
      95             :                                 *q = tolower(*q);
      96             :                         }
      97             :                         keylen = q - key;
      98             :                         zend_hash_str_add_mem(ctx->tags, key, keylen, val, strlen(val)+1);
      99             :                 }
     100             :         }
     101             : 
     102             :         efree(tmp);
     103             : 
     104             :         return SUCCESS;
     105             : }
     106             : 
     107             : static PHP_INI_MH(OnUpdateSessionTags)
     108             : {
     109             :         return php_ini_on_update_tags(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage, 1);
     110             : }
     111             : 
     112             : static PHP_INI_MH(OnUpdateOutputTags)
     113             : {
     114             :         return php_ini_on_update_tags(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage, 0);
     115             : }
     116             : 
     117             : static int php_ini_on_update_hosts(zend_ini_entry *entry, zend_string *new_value, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage, int type)
     118             : {
     119             :         HashTable *hosts;
     120             :         char *key;
     121             :         char *tmp;
     122             :         char *lasts = NULL;
     123             : 
     124             :         if (type) {
     125             :                 hosts = &BG(url_adapt_session_hosts_ht);
     126             :         } else {
     127             :                 hosts = &BG(url_adapt_output_hosts_ht);
     128             :         }
     129             :         zend_hash_clean(hosts);
     130             : 
     131             :         /* Use user supplied host whitelist */
     132             :         tmp = estrndup(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
     133             :         for (key = php_strtok_r(tmp, ",", &lasts);
     134             :                  key;
     135             :                  key = php_strtok_r(NULL, ",", &lasts)) {
     136             :                 size_t keylen;
     137             :                 zend_string *tmp_key;
     138             :                 char *q;
     139             : 
     140             :                 for (q = key; *q; q++) {
     141             :                         *q = tolower(*q);
     142             :                 }
     143             :                 keylen = q - key;
     144             :                 if (keylen > 0) {
     145             :                         tmp_key = zend_string_init(key, keylen, 0);
     146             :                         zend_hash_add_empty_element(hosts, tmp_key);
     147             :                         zend_string_release(tmp_key);
     148             :                 }
     149             :         }
     150             :         efree(tmp);
     151             : 
     152             :         return SUCCESS;
     153             : }
     154             : 
     155             : static PHP_INI_MH(OnUpdateSessionHosts)
     156             : {
     157             :         return php_ini_on_update_hosts(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage, 1);
     158             : }
     159             : 
     160             : static PHP_INI_MH(OnUpdateOutputHosts)
     161             : {
     162             :         return php_ini_on_update_hosts(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage, 0);
     163             : }
     164             : 
     165             : /* FIXME: OnUpdate*Hosts cannot set default to $_SERVER['HTTP_HOST'] at startup */
     166             : PHP_INI_BEGIN()
     167             :         STD_PHP_INI_ENTRY("session.trans_sid_tags", "a=href,area=href,frame=src,form=", PHP_INI_ALL, OnUpdateSessionTags, url_adapt_session_ex, php_basic_globals, basic_globals)
     168             :         STD_PHP_INI_ENTRY("session.trans_sid_hosts", "", PHP_INI_ALL, OnUpdateSessionHosts, url_adapt_session_hosts_ht, php_basic_globals, basic_globals)
     169             :         STD_PHP_INI_ENTRY("url_rewriter.tags", "form=", PHP_INI_ALL, OnUpdateOutputTags, url_adapt_session_ex, php_basic_globals, basic_globals)
     170             :         STD_PHP_INI_ENTRY("url_rewriter.hosts", "", PHP_INI_ALL, OnUpdateOutputHosts, url_adapt_session_hosts_ht, php_basic_globals, basic_globals)
     171             : PHP_INI_END()
     172             : 
     173             : #line 177 "ext/standard/url_scanner_ex.re"
     174             : 
     175             : 
     176             : #define YYFILL(n) goto done
     177             : #define YYCTYPE unsigned char
     178             : #define YYCURSOR p
     179             : #define YYLIMIT q
     180             : #define YYMARKER r
     181             : 
     182             : static inline void append_modified_url(smart_str *url, smart_str *dest, smart_str *url_app, const char *separator)
     183             : {
     184             :         php_url *url_parts;
     185             :         char *tmp;
     186             :         size_t tmp_len;
     187             : 
     188             :         smart_str_0(url); /* FIXME: Bug #70480 php_url_parse_ex() crashes by processing chars exceed len */
     189             :         url_parts = php_url_parse_ex(ZSTR_VAL(url->s), ZSTR_LEN(url->s));
     190             : 
     191             :         /* Ignore malformed URLs */
     192             :         if (!url_parts) {
     193             :                 smart_str_append_smart_str(dest, url);
     194             :                 return;
     195             :         }
     196             : 
     197             :         /* Don't modify URLs of the format "#mark" */
     198             :         if (url_parts->fragment && '#' == ZSTR_VAL(url->s)[0]) {
     199             :                 smart_str_append_smart_str(dest, url);
     200             :                 php_url_free(url_parts);
     201             :                 return;
     202             :         }
     203             : 
     204             :         /* Check protocol. Only http/https is allowed. */
     205             :         if (url_parts->scheme
     206             :                 && strcasecmp("http", url_parts->scheme)
     207             :                 && strcasecmp("https", url_parts->scheme)) {
     208             :                 smart_str_append_smart_str(dest, url);
     209             :                 php_url_free(url_parts);
     210             :                 return;
     211             :         }
     212             : 
     213             :         /* Check host whitelist. If it's not listed, do nothing. */
     214             :         if (url_parts->host
     215             :                 && (tmp_len = strlen(url_parts->host))
     216             :                 && (tmp = php_strtolower(url_parts->host, tmp_len))
     217             :                 && !zend_hash_str_find(&BG(url_adapt_session_hosts_ht), tmp, tmp_len)) {
     218             :                 smart_str_append_smart_str(dest, url);
     219             :                 php_url_free(url_parts);
     220             :                 return;
     221             :         }
     222             : 
     223             :         /*
     224             :          * When URL does not have path and query string add "/?".
     225             :          * i.e. If URL is only "?foo=bar", should not add "/?".
     226             :          */
     227             :         if (!url_parts->path && !url_parts->query && !url_parts->fragment) {
     228             :                 /* URL is http://php.net or like */
     229             :                 smart_str_append_smart_str(dest, url);
     230             :                 smart_str_appendc(dest, '/');
     231             :                 smart_str_appendc(dest, '?');
     232             :                 smart_str_append_smart_str(dest, url_app);
     233             :                 php_url_free(url_parts);
     234             :                 return;
     235             :         }
     236             : 
     237             :         if (url_parts->scheme) {
     238             :                 smart_str_appends(dest, url_parts->scheme);
     239             :                 smart_str_appends(dest, "://");
     240             :         } else if (*(ZSTR_VAL(url->s)) == '/' && *(ZSTR_VAL(url->s)+1) == '/') {
     241             :                 smart_str_appends(dest, "//");
     242             :         }
     243             :         if (url_parts->user) {
     244             :                 smart_str_appends(dest, url_parts->user);
     245             :                 if (url_parts->pass) {
     246             :                         smart_str_appends(dest, url_parts->pass);
     247             :                         smart_str_appendc(dest, ':');
     248             :                 }
     249             :                 smart_str_appendc(dest, '@');
     250             :         }
     251             :         if (url_parts->host) {
     252             :                                 smart_str_appends(dest, url_parts->host);
     253             :         }
     254             :         if (url_parts->port) {
     255             :                 smart_str_appendc(dest, ':');
     256             :                 smart_str_append_unsigned(dest, (long)url_parts->port);
     257             :         }
     258             :         if (url_parts->path) {
     259             :                 smart_str_appends(dest, url_parts->path);
     260             :         }
     261             :         smart_str_appendc(dest, '?');
     262             :         if (url_parts->query) {
     263             :                 smart_str_appends(dest, url_parts->query);
     264             :                 smart_str_appends(dest, separator);
     265             :                 smart_str_append_smart_str(dest, url_app);
     266             :         } else {
     267             :                 smart_str_append_smart_str(dest, url_app);
     268             :         }
     269             :         if (url_parts->fragment) {
     270             :                 smart_str_appendc(dest, '#');
     271             :                 smart_str_appends(dest, url_parts->fragment);
     272             :         }
     273             :         php_url_free(url_parts);
     274             : }
     275             : 
     276             : enum {
     277             :         TAG_NORMAL = 0,
     278             :         TAG_FORM
     279             : };
     280             : 
     281             : enum {
     282             :         ATTR_NORMAL = 0,
     283             :         ATTR_ACTION
     284             : };
     285             : 
     286             : #undef YYFILL
     287             : #undef YYCTYPE
     288             : #undef YYCURSOR
     289             : #undef YYLIMIT
     290             : #undef YYMARKER
     291             : 
     292             : static inline void tag_arg(url_adapt_state_ex_t *ctx, char quotes, char type)
     293             : {
     294             :         char f = 0;
     295             : 
     296             :         /* arg.s is string WITHOUT NUL.
     297             :            To avoid partial match, NUL is added here */
     298             :         ZSTR_VAL(ctx->arg.s)[ZSTR_LEN(ctx->arg.s)] = '\0';
     299             :         if (!strcasecmp(ZSTR_VAL(ctx->arg.s), ctx->lookup_data)) {
     300             :                 f = 1;
     301             :         }
     302             : 
     303             :         if (quotes) {
     304             :                 smart_str_appendc(&ctx->result, type);
     305             :         }
     306             :         if (f) {
     307             :                 append_modified_url(&ctx->val, &ctx->result, &ctx->url_app, PG(arg_separator).output);
     308             :         } else {
     309             :                 smart_str_append_smart_str(&ctx->result, &ctx->val);
     310             :         }
     311             :         if (quotes) {
     312             :                 smart_str_appendc(&ctx->result, type);
     313             :         }
     314             : }
     315             : 
     316             : enum {
     317             :         STATE_PLAIN = 0,
     318             :         STATE_TAG,
     319             :         STATE_NEXT_ARG,
     320             :         STATE_ARG,
     321             :         STATE_BEFORE_VAL,
     322             :         STATE_VAL
     323             : };
     324             : 
     325             : #define YYFILL(n) goto stop
     326             : #define YYCTYPE unsigned char
     327             : #define YYCURSOR xp
     328             : #define YYLIMIT end
     329             : #define YYMARKER q
     330             : #define STATE ctx->state
     331             : 
     332             : #define STD_PARA url_adapt_state_ex_t *ctx, char *start, char *YYCURSOR
     333             : #define STD_ARGS ctx, start, xp
     334             : 
     335             : #if SCANNER_DEBUG
     336             : #define scdebug(x) printf x
     337             : #else
     338             : #define scdebug(x)
     339             : #endif
     340             : 
     341             : static inline void passthru(STD_PARA)
     342             : {
     343             :         scdebug(("appending %d chars, starting with %c\n", YYCURSOR-start, *start));
     344             :         smart_str_appendl(&ctx->result, start, YYCURSOR - start);
     345             : }
     346             : 
     347             : 
     348             : static int check_http_host(char *target)
     349             : {
     350             :         zval *host, *tmp;
     351             :         zend_string *host_tmp;
     352             :         char *colon;
     353             : 
     354             :         if ((tmp  = zend_hash_str_find(&EG(symbol_table), ZEND_STRL("_SERVER"))) &&
     355             :                 Z_TYPE_P(tmp) == IS_ARRAY &&
     356             :                 (host = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("HTTP_HOST"))) &&
     357             :                 Z_TYPE_P(host) == IS_STRING) {
     358             :                 host_tmp = zend_string_init(Z_STRVAL_P(host), Z_STRLEN_P(host), 0);
     359             :                 /* HTTP_HOST could be 'localhost:8888' etc. */
     360             :                 colon = strchr(ZSTR_VAL(host_tmp), ':');
     361             :                 if (colon) {
     362             :                         ZSTR_LEN(host_tmp) = colon - ZSTR_VAL(host_tmp);
     363             :                         ZSTR_VAL(host_tmp)[ZSTR_LEN(host_tmp)] = '\0';
     364             :                 }
     365             :                 if (!strcasecmp(ZSTR_VAL(host_tmp), target)) {
     366             :                         zend_string_release(host_tmp);
     367             :                         return SUCCESS;
     368             :                 }
     369             :                 zend_string_release(host_tmp);
     370             :         }
     371             :         return FAILURE;
     372             : }
     373             : 
     374             : static int check_host_whitelist(url_adapt_state_ex_t *ctx)
     375             : {
     376             :         php_url *url_parts = NULL;
     377             :         HashTable *allowed_hosts = ctx->type ? &BG(url_adapt_session_hosts_ht) : &BG(url_adapt_output_hosts_ht);
     378             : 
     379             :         ZEND_ASSERT(ctx->tag_type == TAG_FORM);
     380             : 
     381             :         if (ctx->attr_val.s && ZSTR_LEN(ctx->attr_val.s)) {
     382             :                 url_parts = php_url_parse_ex(ZSTR_VAL(ctx->attr_val.s), ZSTR_LEN(ctx->attr_val.s));
     383             :         } else {
     384             :                 return SUCCESS; /* empty URL is valid */
     385             :         }
     386             : 
     387             :         if (!url_parts) {
     388             :                 return FAILURE;
     389             :         }
     390             :         if (url_parts->scheme) {
     391             :                 /* Only http/https should be handled.
     392             :                    A bit hacky check this here, but saves a URL parse. */
     393             :                 if (strcasecmp(url_parts->scheme, "http") &&
     394             :                         strcasecmp(url_parts->scheme, "https")) {
     395             :                 php_url_free(url_parts);
     396             :                 return FAILURE;
     397             :                 }
     398             :         }
     399             :         if (!url_parts->host) {
     400             :                 php_url_free(url_parts);
     401             :                 return SUCCESS;
     402             :         }
     403             :         if (!zend_hash_num_elements(allowed_hosts) &&
     404             :                 check_http_host(url_parts->host) == SUCCESS) {
     405             :                 php_url_free(url_parts);
     406             :                 return SUCCESS;
     407             :         }
     408             :         if (!zend_hash_str_find(allowed_hosts,
     409             :                                                         url_parts->host,
     410             :                                                         strlen(url_parts->host))) {
     411             :                 php_url_free(url_parts);
     412             :                 return FAILURE;
     413             :         }
     414             :         php_url_free(url_parts);
     415             :         return SUCCESS;
     416             : }
     417             : 
     418             : /*
     419             :  * This function appends a hidden input field after a <form>.
     420             :  */
     421             : static void handle_form(STD_PARA)
     422             : {
     423             :         int doit = 0;
     424             : 
     425             :         if (ZSTR_LEN(ctx->form_app.s) > 0) {
     426             :                 switch (ZSTR_LEN(ctx->tag.s)) {
     427             :                         case sizeof("form") - 1:
     428             :                                 if (!strncasecmp(ZSTR_VAL(ctx->tag.s), "form", ZSTR_LEN(ctx->tag.s))
     429             :                                         && check_host_whitelist(ctx) == SUCCESS) {
     430             :                                         doit = 1;
     431             :                                 }
     432             :                                 break;
     433             :                 }
     434             :         }
     435             : 
     436             :         if (doit) {
     437             :                 smart_str_append_smart_str(&ctx->result, &ctx->form_app);
     438             :         }
     439             : }
     440             : 
     441             : /*
     442             :  *  HANDLE_TAG copies the HTML Tag and checks whether we
     443             :  *  have that tag in our table. If we might modify it,
     444             :  *  we continue to scan the tag, otherwise we simply copy the complete
     445             :  *  HTML stuff to the result buffer.
     446             :  */
     447             : 
     448             : static inline void handle_tag(STD_PARA)
     449             : {
     450             :         int ok = 0;
     451             :         unsigned int i;
     452             : 
     453             :         if (ctx->tag.s) {
     454             :                 ZSTR_LEN(ctx->tag.s) = 0;
     455             :         }
     456             :         smart_str_appendl(&ctx->tag, start, YYCURSOR - start);
     457             :         for (i = 0; i < ZSTR_LEN(ctx->tag.s); i++)
     458             :                 ZSTR_VAL(ctx->tag.s)[i] = tolower((int)(unsigned char)ZSTR_VAL(ctx->tag.s)[i]);
     459             :     /* intentionally using str_find here, in case the hash value is set, but the string val is changed later */
     460             :         if ((ctx->lookup_data = zend_hash_str_find_ptr(ctx->tags, ZSTR_VAL(ctx->tag.s), ZSTR_LEN(ctx->tag.s))) != NULL) {
     461             :                 ok = 1;
     462             :                 if (ZSTR_LEN(ctx->tag.s) == sizeof("form")-1
     463             :                         && !strncasecmp(ZSTR_VAL(ctx->tag.s), "form", ZSTR_LEN(ctx->tag.s))) {
     464             :                         ctx->tag_type = TAG_FORM;
     465             :                 } else {
     466             :                         ctx->tag_type = TAG_NORMAL;
     467             :                 }
     468             :         }
     469             :         STATE = ok ? STATE_NEXT_ARG : STATE_PLAIN;
     470             : }
     471             : 
     472             : static inline void handle_arg(STD_PARA)
     473             : {
     474             :         if (ctx->arg.s) {
     475             :                 ZSTR_LEN(ctx->arg.s) = 0;
     476             :         }
     477             :         smart_str_appendl(&ctx->arg, start, YYCURSOR - start);
     478             :         if (ctx->tag_type == TAG_FORM &&
     479             :                 strncasecmp(ZSTR_VAL(ctx->arg.s), "action", ZSTR_LEN(ctx->arg.s)) == 0) {
     480             :                 ctx->attr_type = ATTR_ACTION;
     481             :         } else {
     482             :                 ctx->attr_type = ATTR_NORMAL;
     483             :         }
     484             : }
     485             : 
     486             : static inline void handle_val(STD_PARA, char quotes, char type)
     487             : {
     488             :         smart_str_setl(&ctx->val, start + quotes, YYCURSOR - start - quotes * 2);
     489             :         if (ctx->tag_type == TAG_FORM && ctx->attr_type == ATTR_ACTION) {
     490             :                 smart_str_setl(&ctx->attr_val, start + quotes, YYCURSOR - start - quotes * 2);
     491             :         }
     492             :         tag_arg(ctx, quotes, type);
     493             : }
     494             : 
     495             : static inline void xx_mainloop(url_adapt_state_ex_t *ctx, const char *newdata, size_t newlen)
     496             : {
     497             :         char *end, *q;
     498             :         char *xp;
     499             :         char *start;
     500             :         size_t rest;
     501             : 
     502             :         smart_str_appendl(&ctx->buf, newdata, newlen);
     503             : 
     504             :         YYCURSOR = ZSTR_VAL(ctx->buf.s);
     505             :         YYLIMIT = ZSTR_VAL(ctx->buf.s) + ZSTR_LEN(ctx->buf.s);
     506             : 
     507             :         switch (STATE) {
     508             :                 case STATE_PLAIN: goto state_plain;
     509             :                 case STATE_TAG: goto state_tag;
     510             :                 case STATE_NEXT_ARG: goto state_next_arg;
     511             :                 case STATE_ARG: goto state_arg;
     512             :                 case STATE_BEFORE_VAL: goto state_before_val;
     513             :                 case STATE_VAL: goto state_val;
     514             :         }
     515             : 
     516             : 
     517             : state_plain_begin:
     518             :         STATE = STATE_PLAIN;
     519             : 
     520             : state_plain:
     521             :         start = YYCURSOR;
     522             : 
     523             : #line 524 "ext/standard/url_scanner_ex.c"
     524             : {
     525             :         YYCTYPE yych;
     526             :         static const unsigned char yybm[] = {
     527             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     528             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     529             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     530             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     531             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     532             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     533             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     534             :                 128, 128, 128, 128,   0, 128, 128, 128, 
     535             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     536             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     537             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     538             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     539             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     540             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     541             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     542             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     543             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     544             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     545             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     546             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     547             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     548             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     549             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     550             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     551             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     552             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     553             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     554             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     555             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     556             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     557             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     558             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     559             :         };
     560        1866 :         if (YYLIMIT <= YYCURSOR) YYFILL(1);
     561        1864 :         yych = *YYCURSOR;
     562        1864 :         if (yybm[0+yych] & 128) {
     563         932 :                 goto yy2;
     564             :         }
     565         932 :         goto yy5;
     566        5003 : yy2:
     567        5003 :         ++YYCURSOR;
     568        5003 :         if (YYLIMIT <= YYCURSOR) YYFILL(1);
     569        4977 :         yych = *YYCURSOR;
     570        4977 :         if (yybm[0+yych] & 128) {
     571        4071 :                 goto yy2;
     572             :         }
     573             : #line 527 "ext/standard/url_scanner_ex.re"
     574             :         { passthru(STD_ARGS); goto state_plain; }
     575             : #line 576 "ext/standard/url_scanner_ex.c"
     576         932 : yy5:
     577         932 :         ++YYCURSOR;
     578             : #line 526 "ext/standard/url_scanner_ex.re"
     579             :         { passthru(STD_ARGS); STATE = STATE_TAG; goto state_tag; }
     580             : #line 581 "ext/standard/url_scanner_ex.c"
     581             : }
     582             : #line 528 "ext/standard/url_scanner_ex.re"
     583             : 
     584             : 
     585             : state_tag:
     586             :         start = YYCURSOR;
     587             : 
     588             : #line 589 "ext/standard/url_scanner_ex.c"
     589             : {
     590             :         YYCTYPE yych;
     591             :         static const unsigned char yybm[] = {
     592             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     593             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     594             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     595             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     596             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     597             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     598             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     599             :                   0,   0, 128,   0,   0,   0,   0,   0, 
     600             :                   0, 128, 128, 128, 128, 128, 128, 128, 
     601             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     602             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     603             :                 128, 128, 128,   0,   0,   0,   0,   0, 
     604             :                   0, 128, 128, 128, 128, 128, 128, 128, 
     605             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     606             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     607             :                 128, 128, 128,   0,   0,   0,   0,   0, 
     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,   0,   0,   0, 
     614             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     615             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     616             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     617             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     618             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     619             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     620             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     621             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     622             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     623             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     624             :         };
     625         932 :         if (YYLIMIT <= YYCURSOR) YYFILL(1);
     626         932 :         yych = *YYCURSOR;
     627         932 :         if (yybm[0+yych] & 128) {
     628         499 :                 goto yy11;
     629             :         }
     630         433 :         ++YYCURSOR;
     631             : #line 534 "ext/standard/url_scanner_ex.re"
     632             :         { passthru(STD_ARGS); goto state_plain_begin; }
     633             : #line 634 "ext/standard/url_scanner_ex.c"
     634        1101 : yy11:
     635        1101 :         ++YYCURSOR;
     636        1101 :         if (YYLIMIT <= YYCURSOR) YYFILL(1);
     637        1101 :         yych = *YYCURSOR;
     638        1101 :         if (yybm[0+yych] & 128) {
     639         602 :                 goto yy11;
     640             :         }
     641             : #line 533 "ext/standard/url_scanner_ex.re"
     642             :         { handle_tag(STD_ARGS); /* Sets STATE */; passthru(STD_ARGS); if (STATE == STATE_PLAIN) goto state_plain; else goto state_next_arg; }
     643             : #line 644 "ext/standard/url_scanner_ex.c"
     644             : }
     645             : #line 535 "ext/standard/url_scanner_ex.re"
     646             : 
     647             : 
     648             : state_next_arg_begin:
     649             :         STATE = STATE_NEXT_ARG;
     650             : 
     651             : state_next_arg:
     652             :         start = YYCURSOR;
     653             : 
     654             : #line 655 "ext/standard/url_scanner_ex.c"
     655             : {
     656             :         YYCTYPE yych;
     657             :         static const unsigned char yybm[] = {
     658             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     659             :                   0, 128, 128, 128,   0, 128,   0,   0, 
     660             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     661             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     662             :                 128,   0,   0,   0,   0,   0,   0,   0, 
     663             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     664             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     665             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     666             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     667             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     668             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     669             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     670             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     671             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     672             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     673             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     674             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     675             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     676             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     677             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     678             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     679             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     680             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     681             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     682             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     683             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     684             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     685             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     686             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     687             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     688             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     689             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     690             :         };
     691        1494 :         if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
     692        1494 :         yych = *YYCURSOR;
     693        1494 :         if (yybm[0+yych] & 128) {
     694         532 :                 goto yy18;
     695             :         }
     696         962 :         if (yych <= '>') {
     697         432 :                 if (yych == '/') goto yy21;
     698         427 :                 if (yych >= '>') goto yy22;
     699             :         } else {
     700         530 :                 if (yych <= 'Z') {
     701           0 :                         if (yych >= 'A') goto yy24;
     702             :                 } else {
     703         530 :                         if (yych <= '`') goto yy16;
     704         530 :                         if (yych <= 'z') goto yy24;
     705             :                 }
     706             :         }
     707           0 : yy16:
     708           0 :         ++YYCURSOR;
     709           0 : yy17:
     710             : #line 546 "ext/standard/url_scanner_ex.re"
     711             :         { passthru(STD_ARGS); goto state_plain_begin; }
     712             : #line 713 "ext/standard/url_scanner_ex.c"
     713         539 : yy18:
     714         539 :         ++YYCURSOR;
     715         539 :         if (YYLIMIT <= YYCURSOR) YYFILL(1);
     716         539 :         yych = *YYCURSOR;
     717         539 :         if (yybm[0+yych] & 128) {
     718           7 :                 goto yy18;
     719             :         }
     720             : #line 544 "ext/standard/url_scanner_ex.re"
     721             :         { passthru(STD_ARGS); goto state_next_arg; }
     722             : #line 723 "ext/standard/url_scanner_ex.c"
     723           5 : yy21:
     724           5 :         yych = *++YYCURSOR;
     725           5 :         if (yych != '>') goto yy17;
     726           5 : yy22:
     727         432 :         ++YYCURSOR;
     728             : #line 543 "ext/standard/url_scanner_ex.re"
     729             :         { passthru(STD_ARGS); handle_form(STD_ARGS); goto state_plain_begin; }
     730             : #line 731 "ext/standard/url_scanner_ex.c"
     731         530 : yy24:
     732         530 :         ++YYCURSOR;
     733             : #line 545 "ext/standard/url_scanner_ex.re"
     734             :         { --YYCURSOR; STATE = STATE_ARG; goto state_arg; }
     735             : #line 736 "ext/standard/url_scanner_ex.c"
     736             : }
     737             : #line 547 "ext/standard/url_scanner_ex.re"
     738             : 
     739             : 
     740             : state_arg:
     741             :         start = YYCURSOR;
     742             : 
     743             : #line 744 "ext/standard/url_scanner_ex.c"
     744             : {
     745             :         YYCTYPE yych;
     746             :         static const unsigned char yybm[] = {
     747             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     748             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     749             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     750             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     751             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     752             :                   0,   0,   0,   0,   0, 128,   0,   0, 
     753             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     754             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     755             :                   0, 128, 128, 128, 128, 128, 128, 128, 
     756             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     757             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     758             :                 128, 128, 128,   0,   0,   0,   0,   0, 
     759             :                   0, 128, 128, 128, 128, 128, 128, 128, 
     760             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     761             :                 128, 128, 128, 128, 128, 128, 128, 128, 
     762             :                 128, 128, 128,   0,   0,   0,   0,   0, 
     763             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     764             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     765             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     766             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     767             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     768             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     769             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     770             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     771             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     772             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     773             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     774             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     775             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     776             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     777             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     778             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     779             :         };
     780         530 :         if (YYLIMIT <= YYCURSOR) YYFILL(1);
     781         530 :         yych = *YYCURSOR;
     782         530 :         if (yych <= '@') goto yy28;
     783         530 :         if (yych <= 'Z') goto yy30;
     784         530 :         if (yych <= '`') goto yy28;
     785         530 :         if (yych <= 'z') goto yy30;
     786           0 : yy28:
     787           0 :         ++YYCURSOR;
     788             : #line 553 "ext/standard/url_scanner_ex.re"
     789             :         { passthru(STD_ARGS); STATE = STATE_NEXT_ARG; goto state_next_arg; }
     790             : #line 791 "ext/standard/url_scanner_ex.c"
     791         530 : yy30:
     792        2554 :         ++YYCURSOR;
     793        2554 :         if (YYLIMIT <= YYCURSOR) YYFILL(1);
     794        2554 :         yych = *YYCURSOR;
     795        2554 :         if (yybm[0+yych] & 128) {
     796        2024 :                 goto yy30;
     797             :         }
     798             : #line 552 "ext/standard/url_scanner_ex.re"
     799             :         { passthru(STD_ARGS); handle_arg(STD_ARGS); STATE = STATE_BEFORE_VAL; goto state_before_val; }
     800             : #line 801 "ext/standard/url_scanner_ex.c"
     801             : }
     802             : #line 554 "ext/standard/url_scanner_ex.re"
     803             : 
     804             : 
     805             : state_before_val:
     806             :         start = YYCURSOR;
     807             : 
     808             : #line 809 "ext/standard/url_scanner_ex.c"
     809             : {
     810             :         YYCTYPE yych;
     811             :         static const unsigned char yybm[] = {
     812             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     813             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     814             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     815             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     816             :                 128,   0,   0,   0,   0,   0,   0,   0, 
     817             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     818             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     819             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     820             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     821             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     822             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     823             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     824             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     825             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     826             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     827             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     828             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     829             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     830             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     831             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     832             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     833             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     834             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     835             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     836             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     837             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     838             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     839             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     840             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     841             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     842             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     843             :                   0,   0,   0,   0,   0,   0,   0,   0, 
     844             :         };
     845         530 :         if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
     846         530 :         yych = *YYCURSOR;
     847         530 :         if (yych == ' ') goto yy37;
     848         530 :         if (yych == '=') goto yy38;
     849           0 :         ++YYCURSOR;
     850           0 : yy36:
     851             : #line 560 "ext/standard/url_scanner_ex.re"
     852             :         { --YYCURSOR; goto state_next_arg_begin; }
     853             : #line 854 "ext/standard/url_scanner_ex.c"
     854           0 : yy37:
     855           0 :         yych = *(YYMARKER = ++YYCURSOR);
     856           0 :         if (yych == ' ') goto yy41;
     857           0 :         if (yych != '=') goto yy36;
     858           0 : yy38:
     859         530 :         ++YYCURSOR;
     860         530 :         if (YYLIMIT <= YYCURSOR) YYFILL(1);
     861         530 :         yych = *YYCURSOR;
     862         530 :         if (yybm[0+yych] & 128) {
     863           0 :                 goto yy38;
     864             :         }
     865             : #line 559 "ext/standard/url_scanner_ex.re"
     866             :         { passthru(STD_ARGS); STATE = STATE_VAL; goto state_val; }
     867             : #line 868 "ext/standard/url_scanner_ex.c"
     868           0 : yy41:
     869           0 :         ++YYCURSOR;
     870           0 :         if (YYLIMIT <= YYCURSOR) YYFILL(1);
     871           0 :         yych = *YYCURSOR;
     872           0 :         if (yych == ' ') goto yy41;
     873           0 :         if (yych == '=') goto yy38;
     874           0 :         YYCURSOR = YYMARKER;
     875           0 :         goto yy36;
     876             : }
     877             : #line 561 "ext/standard/url_scanner_ex.re"
     878             : 
     879             : 
     880             : 
     881             : state_val:
     882             :         start = YYCURSOR;
     883             : 
     884             : #line 885 "ext/standard/url_scanner_ex.c"
     885             : {
     886             :         YYCTYPE yych;
     887             :         static const unsigned char yybm[] = {
     888             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     889             :                 224, 192, 192, 224, 224, 192, 224, 224, 
     890             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     891             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     892             :                 192, 224, 128, 224, 224, 224, 224,  64, 
     893             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     894             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     895             :                 224, 224, 224, 224, 224, 224,   0, 224, 
     896             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     897             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     898             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     899             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     900             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     901             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     902             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     903             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     904             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     905             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     906             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     907             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     908             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     909             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     910             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     911             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     912             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     913             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     914             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     915             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     916             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     917             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     918             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     919             :                 224, 224, 224, 224, 224, 224, 224, 224, 
     920             :         };
     921         530 :         if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
     922         530 :         yych = *YYCURSOR;
     923         530 :         if (yybm[0+yych] & 32) {
     924           5 :                 goto yy46;
     925             :         }
     926         525 :         if (yych <= ' ') goto yy49;
     927         525 :         if (yych <= '"') goto yy51;
     928           3 :         if (yych <= '\'') goto yy52;
     929           0 :         goto yy49;
     930          23 : yy46:
     931          23 :         ++YYCURSOR;
     932          23 :         if (YYLIMIT <= YYCURSOR) YYFILL(1);
     933          23 :         yych = *YYCURSOR;
     934          23 :         if (yybm[0+yych] & 32) {
     935          18 :                 goto yy46;
     936             :         }
     937             : #line 569 "ext/standard/url_scanner_ex.re"
     938             :         { handle_val(STD_ARGS, 0, ' '); goto state_next_arg_begin; }
     939             : #line 940 "ext/standard/url_scanner_ex.c"
     940           0 : yy49:
     941           0 :         ++YYCURSOR;
     942           0 : yy50:
     943             : #line 570 "ext/standard/url_scanner_ex.re"
     944             :         { passthru(STD_ARGS); goto state_next_arg_begin; }
     945             : #line 946 "ext/standard/url_scanner_ex.c"
     946         522 : yy51:
     947         522 :         yych = *(YYMARKER = ++YYCURSOR);
     948         522 :         if (yych == '>') goto yy50;
     949         522 :         goto yy54;
     950           3 : yy52:
     951           3 :         yych = *(YYMARKER = ++YYCURSOR);
     952           3 :         if (yych == '>') goto yy50;
     953           3 :         goto yy59;
     954        8400 : yy53:
     955        8400 :         ++YYCURSOR;
     956        8400 :         if (YYLIMIT <= YYCURSOR) YYFILL(1);
     957        8400 :         yych = *YYCURSOR;
     958        8922 : yy54:
     959        8922 :         if (yybm[0+yych] & 64) {
     960        8400 :                 goto yy53;
     961             :         }
     962         522 :         if (yych <= '"') goto yy56;
     963           0 : yy55:
     964           0 :         YYCURSOR = YYMARKER;
     965           0 :         goto yy50;
     966         522 : yy56:
     967         522 :         ++YYCURSOR;
     968             : #line 567 "ext/standard/url_scanner_ex.re"
     969             :         { handle_val(STD_ARGS, 1, '"'); goto state_next_arg_begin; }
     970             : #line 971 "ext/standard/url_scanner_ex.c"
     971          19 : yy58:
     972          19 :         ++YYCURSOR;
     973          19 :         if (YYLIMIT <= YYCURSOR) YYFILL(1);
     974          19 :         yych = *YYCURSOR;
     975          22 : yy59:
     976          22 :         if (yybm[0+yych] & 128) {
     977          19 :                 goto yy58;
     978             :         }
     979           3 :         if (yych >= '(') goto yy55;
     980           3 :         ++YYCURSOR;
     981             : #line 568 "ext/standard/url_scanner_ex.re"
     982             :         { handle_val(STD_ARGS, 1, '\''); goto state_next_arg_begin; }
     983             : #line 984 "ext/standard/url_scanner_ex.c"
     984             : }
     985             : #line 571 "ext/standard/url_scanner_ex.re"
     986             : 
     987             : 
     988             : stop:
     989             :         if (YYLIMIT < start) {
     990             :                 /* XXX: Crash avoidance. Need to work with reporter to figure out what goes wrong */
     991             :                 rest = 0;
     992             :         } else {
     993             :                 rest = YYLIMIT - start;
     994             :                 scdebug(("stopped in state %d at pos %d (%d:%c) %d\n", STATE, YYCURSOR - ctx->buf.c, *YYCURSOR, *YYCURSOR, rest));
     995             :         }
     996             : 
     997             :         if (rest) memmove(ZSTR_VAL(ctx->buf.s), start, rest);
     998             :         ZSTR_LEN(ctx->buf.s) = rest;
     999             : }
    1000             : 
    1001             : 
    1002             : PHPAPI char *php_url_scanner_adapt_single_url(const char *url, size_t urllen, const char *name, const char *value, size_t *newlen, int encode)
    1003             : {
    1004             :         char *result;
    1005             :         smart_str surl = {0};
    1006             :         smart_str buf = {0};
    1007             :         smart_str url_app = {0};
    1008             :         zend_string *encoded;
    1009             : 
    1010             :         smart_str_appendl(&surl, url, urllen);
    1011             : 
    1012             :         if (encode) {
    1013             :                 encoded = php_raw_url_encode(name, strlen(name));
    1014             :                 smart_str_appendl(&url_app, ZSTR_VAL(encoded), ZSTR_LEN(encoded));
    1015             :                 zend_string_free(encoded);
    1016             :         } else {
    1017             :                 smart_str_appends(&url_app, name);
    1018             :         }
    1019             :         smart_str_appendc(&url_app, '=');
    1020             :         if (encode) {
    1021             :                 encoded = php_raw_url_encode(value, strlen(value));
    1022             :                 smart_str_appendl(&url_app, ZSTR_VAL(encoded), ZSTR_LEN(encoded));
    1023             :                 zend_string_free(encoded);
    1024             :         } else {
    1025             :                 smart_str_appends(&url_app, value);
    1026             :         }
    1027             : 
    1028             :         append_modified_url(&surl, &buf, &url_app, PG(arg_separator).output);
    1029             : 
    1030             :         smart_str_0(&buf);
    1031             :         if (newlen) *newlen = ZSTR_LEN(buf.s);
    1032             :         result = estrndup(ZSTR_VAL(buf.s), ZSTR_LEN(buf.s));
    1033             : 
    1034             :         smart_str_free(&url_app);
    1035             :         smart_str_free(&buf);
    1036             : 
    1037             :         return result;
    1038             : }
    1039             : 
    1040             : 
    1041             : static char *url_adapt_ext(const char *src, size_t srclen, size_t *newlen, zend_bool do_flush, url_adapt_state_ex_t *ctx)
    1042             : {
    1043             :         char *retval;
    1044             : 
    1045             :         xx_mainloop(ctx, src, srclen);
    1046             : 
    1047             :         if (!ctx->result.s) {
    1048             :                 smart_str_appendl(&ctx->result, "", 0);
    1049             :                 *newlen = 0;
    1050             :         } else {
    1051             :                 *newlen = ZSTR_LEN(ctx->result.s);
    1052             :         }
    1053             :         smart_str_0(&ctx->result);
    1054             :         if (do_flush) {
    1055             :                 smart_str_append(&ctx->result, ctx->buf.s);
    1056             :                 *newlen += ZSTR_LEN(ctx->buf.s);
    1057             :                 smart_str_free(&ctx->buf);
    1058             :                 smart_str_free(&ctx->val);
    1059             :                 smart_str_free(&ctx->attr_val);
    1060             :         }
    1061             :         retval = estrndup(ZSTR_VAL(ctx->result.s), ZSTR_LEN(ctx->result.s));
    1062             :         smart_str_free(&ctx->result);
    1063             :         return retval;
    1064             : }
    1065             : 
    1066             : static int php_url_scanner_ex_activate(int type)
    1067             : {
    1068             :         url_adapt_state_ex_t *ctx;
    1069             : 
    1070             :         if (type) {
    1071             :                 ctx = &BG(url_adapt_session_ex);
    1072             :         } else {
    1073             :                 ctx = &BG(url_adapt_output_ex);
    1074             :         }
    1075             : 
    1076             :         memset(ctx, 0, ((size_t) &((url_adapt_state_ex_t *)0)->tags));
    1077             : 
    1078             :         return SUCCESS;
    1079             : }
    1080             : 
    1081             : static int php_url_scanner_ex_deactivate(int type)
    1082             : {
    1083             :         url_adapt_state_ex_t *ctx;
    1084             : 
    1085             :         if (type) {
    1086             :                 ctx = &BG(url_adapt_session_ex);
    1087             :         } else {
    1088             :                 ctx = &BG(url_adapt_output_ex);
    1089             :         }
    1090             : 
    1091             :         smart_str_free(&ctx->result);
    1092             :         smart_str_free(&ctx->buf);
    1093             :         smart_str_free(&ctx->tag);
    1094             :         smart_str_free(&ctx->arg);
    1095             :         smart_str_free(&ctx->attr_val);
    1096             : 
    1097             :         return SUCCESS;
    1098             : }
    1099             : 
    1100             : static inline void php_url_scanner_session_handler_impl(char *output, size_t output_len, char **handled_output, size_t *handled_output_len, int mode, int type)
    1101             : {
    1102             :         size_t len;
    1103             :         url_adapt_state_ex_t *url_state;
    1104             : 
    1105             :         if (type) {
    1106             :                 url_state = &BG(url_adapt_session_ex);
    1107             :         } else {
    1108             :                 url_state = &BG(url_adapt_output_ex);
    1109             :         }
    1110             : 
    1111             :         if (ZSTR_LEN(url_state->url_app.s) != 0) {
    1112             :                 *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), url_state);
    1113             :                 if (sizeof(uint) < sizeof(size_t)) {
    1114             :                         if (len > UINT_MAX)
    1115             :                                 len = UINT_MAX;
    1116             :                 }
    1117             :                 *handled_output_len = len;
    1118             :         } else if (ZSTR_LEN(url_state->url_app.s) == 0) {
    1119             :                 url_adapt_state_ex_t *ctx = url_state;
    1120             :                 if (ctx->buf.s && ZSTR_LEN(ctx->buf.s)) {
    1121             :                         smart_str_append(&ctx->result, ctx->buf.s);
    1122             :                         smart_str_appendl(&ctx->result, output, output_len);
    1123             : 
    1124             :                         *handled_output = estrndup(ZSTR_VAL(ctx->result.s), ZSTR_LEN(ctx->result.s));
    1125             :                         *handled_output_len = ZSTR_LEN(ctx->buf.s) + output_len;
    1126             : 
    1127             :                         smart_str_free(&ctx->buf);
    1128             :                         smart_str_free(&ctx->result);
    1129             :                 } else {
    1130             :                         *handled_output = estrndup(output, *handled_output_len = output_len);
    1131             :                 }
    1132             :         } else {
    1133             :                 *handled_output = NULL;
    1134             :         }
    1135             : }
    1136             : 
    1137             : static void php_url_scanner_session_handler(char *output, size_t output_len, char **handled_output, size_t *handled_output_len, int mode)
    1138             : {
    1139             :         php_url_scanner_session_handler_impl(output, output_len, handled_output, handled_output_len, mode, 1);
    1140             : }
    1141             : 
    1142             : static void php_url_scanner_output_handler(char *output, size_t output_len, char **handled_output, size_t *handled_output_len, int mode)
    1143             : {
    1144             :         php_url_scanner_session_handler_impl(output, output_len, handled_output, handled_output_len, mode, 0);
    1145             : }
    1146             : 
    1147             : static inline int php_url_scanner_add_var_impl(char *name, size_t name_len, char *value, size_t value_len, int encode, int type)
    1148             : {
    1149             :         smart_str sname = {0};
    1150             :         smart_str svalue = {0};
    1151             :         smart_str hname = {0};
    1152             :         smart_str hvalue = {0};
    1153             :         zend_string *encoded;
    1154             :         url_adapt_state_ex_t *url_state;
    1155             :         php_output_handler_func_t handler;
    1156             : 
    1157             :         if (type) {
    1158             :                 url_state = &BG(url_adapt_session_ex);
    1159             :                 handler = php_url_scanner_session_handler;
    1160             :         } else {
    1161             :                 url_state = &BG(url_adapt_output_ex);
    1162             :                 handler = php_url_scanner_output_handler;
    1163             :         }
    1164             : 
    1165             :         if (!url_state->active) {
    1166             :                 php_url_scanner_ex_activate(type);
    1167             :                 php_output_start_internal(ZEND_STRL("URL-Rewriter"), handler, 0, PHP_OUTPUT_HANDLER_STDFLAGS);
    1168             :                 url_state->active = 1;
    1169             :         }
    1170             : 
    1171             :         if (url_state->url_app.s && ZSTR_LEN(url_state->url_app.s) != 0) {
    1172             :                 smart_str_appends(&url_state->url_app, PG(arg_separator).output);
    1173             :         }
    1174             : 
    1175             :         if (encode) {
    1176             :                 encoded = php_raw_url_encode(name, name_len);
    1177             :                 smart_str_appendl(&sname, ZSTR_VAL(encoded), ZSTR_LEN(encoded)); zend_string_free(encoded);
    1178             :                 encoded = php_raw_url_encode(value, value_len);
    1179             :                 smart_str_appendl(&svalue, ZSTR_VAL(encoded), ZSTR_LEN(encoded)); zend_string_free(encoded);
    1180             :                 encoded = php_escape_html_entities_ex((unsigned char*)name, name_len, 0, ENT_QUOTES|ENT_SUBSTITUTE, SG(default_charset), 0);
    1181             :                 smart_str_appendl(&hname, ZSTR_VAL(encoded), ZSTR_LEN(encoded)); zend_string_free(encoded);
    1182             :                 encoded = php_escape_html_entities_ex((unsigned char*)value, value_len, 0, ENT_QUOTES|ENT_SUBSTITUTE, SG(default_charset), 0);
    1183             :                 smart_str_appendl(&hvalue, ZSTR_VAL(encoded), ZSTR_LEN(encoded)); zend_string_free(encoded);
    1184             :         } else {
    1185             :                 smart_str_appendl(&sname, name, name_len);
    1186             :                 smart_str_appendl(&svalue, value, value_len);
    1187             :                 smart_str_appendl(&hname, name, name_len);
    1188             :                 smart_str_appendl(&hvalue, value, value_len);
    1189             :         }
    1190             : 
    1191             :         smart_str_append_smart_str(&url_state->url_app, &sname);
    1192             :         smart_str_appendc(&url_state->url_app, '=');
    1193             :         smart_str_append_smart_str(&url_state->url_app, &svalue);
    1194             : 
    1195             :         smart_str_appends(&url_state->form_app, "<input type=\"hidden\" name=\"");
    1196             :         smart_str_append_smart_str(&url_state->form_app, &hname);
    1197             :         smart_str_appends(&url_state->form_app, "\" value=\"");
    1198             :         smart_str_append_smart_str(&url_state->form_app, &hvalue);
    1199             :         smart_str_appends(&url_state->form_app, "\" />");
    1200             : 
    1201             :         smart_str_free(&sname);
    1202             :         smart_str_free(&svalue);
    1203             :         smart_str_free(&hname);
    1204             :         smart_str_free(&hvalue);
    1205             : 
    1206             :         return SUCCESS;
    1207             : }
    1208             : 
    1209             : 
    1210             : PHPAPI int php_url_scanner_add_session_var(char *name, size_t name_len, char *value, size_t value_len, int encode)
    1211             : {
    1212             :         return php_url_scanner_add_var_impl(name, name_len, value, value_len, encode, 1);
    1213             : }
    1214             : 
    1215             : 
    1216             : PHPAPI int php_url_scanner_add_var(char *name, size_t name_len, char *value, size_t value_len, int encode)
    1217             : {
    1218             :         return php_url_scanner_add_var_impl(name, name_len, value, value_len, encode, 0);
    1219             : }
    1220             : 
    1221             : 
    1222             : static inline void php_url_scanner_reset_vars_impl(int type) {
    1223             :         url_adapt_state_ex_t *url_state;
    1224             : 
    1225             :         if (type) {
    1226             :                 url_state = &BG(url_adapt_session_ex);
    1227             :         } else {
    1228             :                 url_state = &BG(url_adapt_output_ex);
    1229             :         }
    1230             : 
    1231             :         if (url_state->form_app.s) {
    1232             :                 ZSTR_LEN(url_state->form_app.s) = 0;
    1233             :         }
    1234             :         if (url_state->url_app.s) {
    1235             :                 ZSTR_LEN(url_state->url_app.s) = 0;
    1236             :         }
    1237             : }
    1238             : 
    1239             : 
    1240             : PHPAPI int php_url_scanner_reset_session_vars(void)
    1241             : {
    1242             :         php_url_scanner_reset_vars_impl(1);
    1243             :         return SUCCESS;
    1244             : }
    1245             : 
    1246             : 
    1247             : PHPAPI int php_url_scanner_reset_vars(void)
    1248             : {
    1249             :         php_url_scanner_reset_vars_impl(0);
    1250             :         return SUCCESS;
    1251             : }
    1252             : 
    1253             : 
    1254             : static inline int php_url_scanner_reset_var_impl(zend_string *name, int encode, int type)
    1255             : {
    1256             :         char *start, *end, *limit;
    1257             :         size_t separator_len;
    1258             :         smart_str sname = {0};
    1259             :         smart_str hname = {0};
    1260             :         smart_str url_app = {0};
    1261             :         smart_str form_app = {0};
    1262             :         zend_string *encoded;
    1263             :         int ret = SUCCESS;
    1264             :         zend_bool sep_removed = 0;
    1265             :         url_adapt_state_ex_t *url_state;
    1266             : 
    1267             :         if (type) {
    1268             :                 url_state = &BG(url_adapt_session_ex);
    1269             :         } else {
    1270             :                 url_state = &BG(url_adapt_output_ex);
    1271             :         }
    1272             : 
    1273             :         /* Short circuit check. Only check url_app. */
    1274             :         if (!url_state->url_app.s || !ZSTR_LEN(url_state->url_app.s)) {
    1275             :                 return SUCCESS;
    1276             :         }
    1277             : 
    1278             :         if (encode) {
    1279             :                 encoded = php_raw_url_encode(ZSTR_VAL(name), ZSTR_LEN(name));
    1280             :                 smart_str_appendl(&sname, ZSTR_VAL(encoded), ZSTR_LEN(encoded));
    1281             :                 zend_string_free(encoded);
    1282             :                 encoded = php_escape_html_entities_ex((unsigned char *)ZSTR_VAL(name), ZSTR_LEN(name), 0, ENT_QUOTES|ENT_SUBSTITUTE, SG(default_charset), 0);
    1283             :                 smart_str_appendl(&hname, ZSTR_VAL(encoded), ZSTR_LEN(encoded));
    1284             :                 zend_string_free(encoded);
    1285             :         } else {
    1286             :                 smart_str_appendl(&sname, ZSTR_VAL(name), ZSTR_LEN(name));
    1287             :                 smart_str_appendl(&hname, ZSTR_VAL(name), ZSTR_LEN(name));
    1288             :         }
    1289             :         smart_str_0(&sname);
    1290             :         smart_str_0(&hname);
    1291             : 
    1292             :         smart_str_append_smart_str(&url_app, &sname);
    1293             :         smart_str_appendc(&url_app, '=');
    1294             :         smart_str_0(&url_app);
    1295             : 
    1296             :         smart_str_appends(&form_app, "<input type=\"hidden\" name=\"");
    1297             :         smart_str_append_smart_str(&form_app, &hname);
    1298             :         smart_str_appends(&form_app, "\" value=\"");
    1299             :         smart_str_0(&form_app);
    1300             : 
    1301             :         /* Short circuit check. Only check url_app. */
    1302             :         start = (char *) php_memnstr(ZSTR_VAL(url_state->url_app.s),
    1303             :                                                                  ZSTR_VAL(url_app.s), ZSTR_LEN(url_app.s),
    1304             :                                                                  ZSTR_VAL(url_state->url_app.s) + ZSTR_LEN(url_state->url_app.s));
    1305             :         if (!start) {
    1306             :                 ret = FAILURE;
    1307             :                 goto finish;
    1308             :         }
    1309             : 
    1310             :         /* Get end of url var */
    1311             :         limit = ZSTR_VAL(url_state->url_app.s) + ZSTR_LEN(url_state->url_app.s);
    1312             :         end = start + ZSTR_LEN(url_app.s);
    1313             :         separator_len = strlen(PG(arg_separator).output);
    1314             :         while (end < limit) {
    1315             :                 if (!memcmp(end, PG(arg_separator).output, separator_len)) {
    1316             :                         end += separator_len;
    1317             :                         sep_removed = 1;
    1318             :                         break;
    1319             :                 }
    1320             :                 end++;
    1321             :         }
    1322             :         /* Remove all when this is the only rewrite var */
    1323             :         if (ZSTR_LEN(url_state->url_app.s) == end - start) {
    1324             :                 php_url_scanner_reset_vars_impl(type);
    1325             :                 goto finish;
    1326             :         }
    1327             :         /* Check preceeding separator */
    1328             :         if (!sep_removed
    1329             :                 && start - PG(arg_separator).output >= separator_len
    1330             :                 && !memcmp(start - separator_len, PG(arg_separator).output, separator_len)) {
    1331             :                 start -= separator_len;
    1332             :         }
    1333             :         /* Remove partially */
    1334             :         memmove(start, end,
    1335             :                         ZSTR_LEN(url_state->url_app.s) - (end - ZSTR_VAL(url_state->url_app.s)));
    1336             :         ZSTR_LEN(url_state->url_app.s) -= end - start;
    1337             :         ZSTR_VAL(url_state->url_app.s)[ZSTR_LEN(url_state->url_app.s)] = '\0';
    1338             : 
    1339             :         /* Remove form var */
    1340             :         start = (char *) php_memnstr(ZSTR_VAL(url_state->form_app.s),
    1341             :                                                 ZSTR_VAL(form_app.s), ZSTR_LEN(form_app.s),
    1342             :                                                 ZSTR_VAL(url_state->form_app.s) + ZSTR_LEN(url_state->form_app.s));
    1343             :         if (!start) {
    1344             :                 /* Should not happen */
    1345             :                 ret = FAILURE;
    1346             :                 php_url_scanner_reset_vars_impl(type);
    1347             :                 goto finish;
    1348             :         }
    1349             :         /* Get end of form var */
    1350             :         limit = ZSTR_VAL(url_state->form_app.s) + ZSTR_LEN(url_state->form_app.s);
    1351             :         end = start + ZSTR_LEN(form_app.s);
    1352             :         while (end < limit) {
    1353             :                 if (*end == '>') {
    1354             :                         end += 1;
    1355             :                         break;
    1356             :                 }
    1357             :                 end++;
    1358             :         }
    1359             :         /* Remove partially */
    1360             :         memmove(start, end,
    1361             :                         ZSTR_LEN(url_state->form_app.s) - (end - ZSTR_VAL(url_state->form_app.s)));
    1362             :         ZSTR_LEN(url_state->form_app.s) -= end - start;
    1363             :         ZSTR_VAL(url_state->form_app.s)[ZSTR_LEN(url_state->form_app.s)] = '\0';
    1364             : 
    1365             : finish:
    1366             :         smart_str_free(&url_app);
    1367             :         smart_str_free(&form_app);
    1368             :         smart_str_free(&sname);
    1369             :         smart_str_free(&hname);
    1370             :         return ret;
    1371             : }
    1372             : 
    1373             : 
    1374             : PHPAPI int php_url_scanner_reset_session_var(zend_string *name, int encode)
    1375             : {
    1376             :         return php_url_scanner_reset_var_impl(name, encode, 1);
    1377             : }
    1378             : 
    1379             : 
    1380             : PHPAPI int php_url_scanner_reset_var(zend_string *name, int encode)
    1381             : {
    1382             :         return php_url_scanner_reset_var_impl(name, encode, 0);
    1383             : }
    1384             : 
    1385             : 
    1386             : PHP_MINIT_FUNCTION(url_scanner)
    1387             : {
    1388             :         REGISTER_INI_ENTRIES();
    1389             :         return SUCCESS;
    1390             : }
    1391             : 
    1392             : PHP_MSHUTDOWN_FUNCTION(url_scanner)
    1393             : {
    1394             :         UNREGISTER_INI_ENTRIES();
    1395             : 
    1396             :         return SUCCESS;
    1397             : }
    1398             : 
    1399             : PHP_RINIT_FUNCTION(url_scanner)
    1400             : {
    1401             :         BG(url_adapt_session_ex).active    = 0;
    1402             :         BG(url_adapt_session_ex).tag_type  = 0;
    1403             :         BG(url_adapt_session_ex).attr_type = 0;
    1404             :         BG(url_adapt_output_ex).active    = 0;
    1405             :         BG(url_adapt_output_ex).tag_type  = 0;
    1406             :         BG(url_adapt_output_ex).attr_type = 0;
    1407             :         return SUCCESS;
    1408             : }
    1409             : 
    1410             : PHP_RSHUTDOWN_FUNCTION(url_scanner)
    1411             : {
    1412             :         if (BG(url_adapt_session_ex).active) {
    1413             :                 php_url_scanner_ex_deactivate(1);
    1414             :                 BG(url_adapt_session_ex).active    = 0;
    1415             :                 BG(url_adapt_session_ex).tag_type  = 0;
    1416             :                 BG(url_adapt_session_ex).attr_type = 0;
    1417             :         }
    1418             :         smart_str_free(&BG(url_adapt_session_ex).form_app);
    1419             :         smart_str_free(&BG(url_adapt_session_ex).url_app);
    1420             : 
    1421             :         if (BG(url_adapt_output_ex).active) {
    1422             :                 php_url_scanner_ex_deactivate(0);
    1423             :                 BG(url_adapt_output_ex).active    = 0;
    1424             :                 BG(url_adapt_output_ex).tag_type  = 0;
    1425             :                 BG(url_adapt_output_ex).attr_type = 0;
    1426             :         }
    1427             :         smart_str_free(&BG(url_adapt_output_ex).form_app);
    1428             :         smart_str_free(&BG(url_adapt_output_ex).url_app);
    1429             : 
    1430             :         return SUCCESS;
    1431             : }

Generated by: LCOV version 1.10

Generated at Mon, 24 Jan 2022 01:16:36 +0000 (5 days ago)

Copyright © 2005-2022 The PHP Group
All rights reserved.