Back to index

php5  5.3.10
url_scanner_ex.c
Go to the documentation of this file.
00001 /* Generated by re2c 0.13.5 on Fri Dec 31 23:52:51 2010 */
00002 /*
00003   +----------------------------------------------------------------------+
00004   | PHP Version 5                                                        |
00005   +----------------------------------------------------------------------+
00006   | Copyright (c) 1997-2006 The PHP Group                                |
00007   +----------------------------------------------------------------------+
00008   | This source file is subject to version 3.01 of the PHP license,      |
00009   | that is bundled with this package in the file LICENSE, and is        |
00010   | available through the world-wide-web at the following url:           |
00011   | http://www.php.net/license/3_01.txt                                  |
00012   | If you did not receive a copy of the PHP license and are unable to   |
00013   | obtain it through the world-wide-web, please send a note to          |
00014   | license@php.net so we can mail you a copy immediately.               |
00015   +----------------------------------------------------------------------+
00016   | Author: Sascha Schumann <sascha@schumann.cx>                         |
00017   +----------------------------------------------------------------------+
00018 */
00019 
00020 /* $Id: url_scanner_ex.c 313832 2011-07-28 10:52:45Z pajoye $ */
00021 
00022 #include "php.h"
00023 
00024 #ifdef HAVE_UNISTD_H
00025 #include <unistd.h>
00026 #endif
00027 #ifdef HAVE_LIMITS_H
00028 #include <limits.h>
00029 #endif
00030 
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 
00035 #include "php_ini.h"
00036 #include "php_globals.h"
00037 #define STATE_TAG SOME_OTHER_STATE_TAG
00038 #include "basic_functions.h"
00039 #include "url.h"
00040 #undef STATE_TAG
00041 
00042 #define url_scanner url_scanner_ex
00043 
00044 #include "php_smart_str.h"
00045 
00046 static PHP_INI_MH(OnUpdateTags)
00047 {
00048        url_adapt_state_ex_t *ctx;
00049        char *key;
00050        char *lasts;
00051        char *tmp;
00052        
00053        ctx = &BG(url_adapt_state_ex);
00054        
00055        tmp = estrndup(new_value, new_value_length);
00056        
00057        if (ctx->tags)
00058               zend_hash_destroy(ctx->tags);
00059        else {
00060               ctx->tags = malloc(sizeof(HashTable));
00061               if (!ctx->tags) {
00062                      return FAILURE;
00063               }
00064        }
00065        zend_hash_init(ctx->tags, 0, NULL, NULL, 1);
00066        
00067        for (key = php_strtok_r(tmp, ",", &lasts);
00068                      key;
00069                      key = php_strtok_r(NULL, ",", &lasts)) {
00070               char *val;
00071 
00072               val = strchr(key, '=');
00073               if (val) {
00074                      char *q;
00075                      int keylen;
00076                      
00077                      *val++ = '\0';
00078                      for (q = key; *q; q++)
00079                             *q = tolower(*q);
00080                      keylen = q - key;
00081                      /* key is stored withOUT NUL
00082                         val is stored WITH    NUL */
00083                      zend_hash_add(ctx->tags, key, keylen, val, strlen(val)+1, NULL);
00084               }
00085        }
00086 
00087        efree(tmp);
00088 
00089        return SUCCESS;
00090 }
00091 
00092 PHP_INI_BEGIN()
00093        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)
00094 PHP_INI_END()
00095 
00096 
00097 
00098 #define YYFILL(n) goto done
00099 #define YYCTYPE unsigned char
00100 #define YYCURSOR p
00101 #define YYLIMIT q
00102 #define YYMARKER r
00103        
00104 static inline void append_modified_url(smart_str *url, smart_str *dest, smart_str *url_app, const char *separator)
00105 {
00106        register const char *p, *q;
00107        const char *bash = NULL;
00108        const char *sep = "?";
00109        
00110        q = (p = url->c) + url->len;
00111 
00112 scan:
00113 
00114 {
00115        YYCTYPE yych;
00116        static const unsigned char yybm[] = {
00117               128, 128, 128, 128, 128, 128, 128, 128, 
00118               128, 128, 128, 128, 128, 128, 128, 128, 
00119               128, 128, 128, 128, 128, 128, 128, 128, 
00120               128, 128, 128, 128, 128, 128, 128, 128, 
00121               128, 128, 128,   0, 128, 128, 128, 128, 
00122               128, 128, 128, 128, 128, 128, 128, 128, 
00123               128, 128, 128, 128, 128, 128, 128, 128, 
00124               128, 128,   0, 128, 128, 128, 128,   0, 
00125               128, 128, 128, 128, 128, 128, 128, 128, 
00126               128, 128, 128, 128, 128, 128, 128, 128, 
00127               128, 128, 128, 128, 128, 128, 128, 128, 
00128               128, 128, 128, 128, 128, 128, 128, 128, 
00129               128, 128, 128, 128, 128, 128, 128, 128, 
00130               128, 128, 128, 128, 128, 128, 128, 128, 
00131               128, 128, 128, 128, 128, 128, 128, 128, 
00132               128, 128, 128, 128, 128, 128, 128, 128, 
00133               128, 128, 128, 128, 128, 128, 128, 128, 
00134               128, 128, 128, 128, 128, 128, 128, 128, 
00135               128, 128, 128, 128, 128, 128, 128, 128, 
00136               128, 128, 128, 128, 128, 128, 128, 128, 
00137               128, 128, 128, 128, 128, 128, 128, 128, 
00138               128, 128, 128, 128, 128, 128, 128, 128, 
00139               128, 128, 128, 128, 128, 128, 128, 128, 
00140               128, 128, 128, 128, 128, 128, 128, 128, 
00141               128, 128, 128, 128, 128, 128, 128, 128, 
00142               128, 128, 128, 128, 128, 128, 128, 128, 
00143               128, 128, 128, 128, 128, 128, 128, 128, 
00144               128, 128, 128, 128, 128, 128, 128, 128, 
00145               128, 128, 128, 128, 128, 128, 128, 128, 
00146               128, 128, 128, 128, 128, 128, 128, 128, 
00147               128, 128, 128, 128, 128, 128, 128, 128, 
00148               128, 128, 128, 128, 128, 128, 128, 128, 
00149        };
00150 
00151        if (YYLIMIT <= YYCURSOR) YYFILL(1);
00152        yych = *YYCURSOR;
00153        if (yybm[0+yych] & 128) {
00154               goto yy8;
00155        }
00156        if (yych <= '9') goto yy6;
00157        if (yych >= ';') goto yy4;
00158        ++YYCURSOR;
00159        { smart_str_append(dest, url); return; }
00160 yy4:
00161        ++YYCURSOR;
00162        { sep = separator; goto scan; }
00163 yy6:
00164        ++YYCURSOR;
00165        { bash = p - 1; goto done; }
00166 yy8:
00167        ++YYCURSOR;
00168        if (YYLIMIT <= YYCURSOR) YYFILL(1);
00169        yych = *YYCURSOR;
00170        if (yybm[0+yych] & 128) {
00171               goto yy8;
00172        }
00173        { goto scan; }
00174 }
00175 
00176 done:
00177        
00178        /* Don't modify URLs of the format "#mark" */
00179        if (bash && bash - url->c == 0) {
00180               smart_str_append(dest, url);
00181               return;
00182        }
00183 
00184        if (bash)
00185               smart_str_appendl(dest, url->c, bash - url->c);
00186        else
00187               smart_str_append(dest, url);
00188 
00189        smart_str_appends(dest, sep);
00190        smart_str_append(dest, url_app);
00191 
00192        if (bash)
00193               smart_str_appendl(dest, bash, q - bash);
00194 }
00195 
00196 
00197 #undef YYFILL
00198 #undef YYCTYPE
00199 #undef YYCURSOR
00200 #undef YYLIMIT
00201 #undef YYMARKER
00202 
00203 static inline void tag_arg(url_adapt_state_ex_t *ctx, char quotes, char type TSRMLS_DC)
00204 {
00205        char f = 0;
00206 
00207        if (strncasecmp(ctx->arg.c, ctx->lookup_data, ctx->arg.len) == 0)
00208               f = 1;
00209 
00210        if (quotes)
00211               smart_str_appendc(&ctx->result, type);
00212        if (f) {
00213               append_modified_url(&ctx->val, &ctx->result, &ctx->url_app, PG(arg_separator).output);
00214        } else {
00215               smart_str_append(&ctx->result, &ctx->val);
00216        }
00217        if (quotes)
00218               smart_str_appendc(&ctx->result, type);
00219 }
00220 
00221 enum {
00222        STATE_PLAIN = 0,
00223        STATE_TAG,
00224        STATE_NEXT_ARG,
00225        STATE_ARG,
00226        STATE_BEFORE_VAL,
00227        STATE_VAL
00228 };
00229 
00230 #define YYFILL(n) goto stop
00231 #define YYCTYPE unsigned char
00232 #define YYCURSOR xp
00233 #define YYLIMIT end
00234 #define YYMARKER q
00235 #define STATE ctx->state
00236 
00237 #define STD_PARA url_adapt_state_ex_t *ctx, char *start, char *YYCURSOR TSRMLS_DC
00238 #define STD_ARGS ctx, start, xp TSRMLS_CC
00239 
00240 #if SCANNER_DEBUG
00241 #define scdebug(x) printf x
00242 #else
00243 #define scdebug(x)
00244 #endif
00245 
00246 static inline void passthru(STD_PARA) 
00247 {
00248        scdebug(("appending %d chars, starting with %c\n", YYCURSOR-start, *start));
00249        smart_str_appendl(&ctx->result, start, YYCURSOR - start);
00250 }
00251 
00252 /*
00253  * This function appends a hidden input field after a <form> or
00254  * <fieldset>.  The latter is important for XHTML.
00255  */
00256 
00257 static void handle_form(STD_PARA) 
00258 {
00259        int doit = 0;
00260 
00261        if (ctx->form_app.len > 0) {
00262               switch (ctx->tag.len) {
00263                      case sizeof("form") - 1:
00264                             if (!strncasecmp(ctx->tag.c, "form", sizeof("form") - 1)) {
00265                                    doit = 1;            
00266                             }
00267                             if (doit && ctx->val.c && ctx->lookup_data && *ctx->lookup_data) {
00268                                    char *e, *p = zend_memnstr(ctx->val.c, "://", sizeof("://") - 1, ctx->val.c + ctx->val.len);
00269                                    if (p) {
00270                                           e = memchr(p, '/', (ctx->val.c + ctx->val.len) - p);
00271                                           if (!e) {
00272                                                  e = ctx->val.c + ctx->val.len;
00273                                           }
00274                                           if ((e - p) && strncasecmp(p, ctx->lookup_data, (e - p))) {
00275                                                  doit = 0;
00276                                           }
00277                                    }
00278                             }
00279                             break;
00280 
00281                      case sizeof("fieldset") - 1:
00282                             if (!strncasecmp(ctx->tag.c, "fieldset", sizeof("fieldset") - 1)) {
00283                                    doit = 1;            
00284                             }
00285                             break;
00286               }
00287 
00288               if (doit)
00289                      smart_str_append(&ctx->result, &ctx->form_app);
00290        }
00291 }
00292 
00293 /*
00294  *  HANDLE_TAG copies the HTML Tag and checks whether we 
00295  *  have that tag in our table. If we might modify it,
00296  *  we continue to scan the tag, otherwise we simply copy the complete
00297  *  HTML stuff to the result buffer.
00298  */
00299 
00300 static inline void handle_tag(STD_PARA) 
00301 {
00302        int ok = 0;
00303        int i;
00304 
00305        ctx->tag.len = 0;
00306        smart_str_appendl(&ctx->tag, start, YYCURSOR - start);
00307        for (i = 0; i < ctx->tag.len; i++)
00308               ctx->tag.c[i] = tolower((int)(unsigned char)ctx->tag.c[i]);
00309        if (zend_hash_find(ctx->tags, ctx->tag.c, ctx->tag.len, (void **) &ctx->lookup_data) == SUCCESS)
00310               ok = 1;
00311        STATE = ok ? STATE_NEXT_ARG : STATE_PLAIN;
00312 }
00313 
00314 static inline void handle_arg(STD_PARA) 
00315 {
00316        ctx->arg.len = 0;
00317        smart_str_appendl(&ctx->arg, start, YYCURSOR - start);
00318 }
00319 
00320 static inline void handle_val(STD_PARA, char quotes, char type) 
00321 {
00322        smart_str_setl(&ctx->val, start + quotes, YYCURSOR - start - quotes * 2);
00323        tag_arg(ctx, quotes, type TSRMLS_CC);
00324 }
00325 
00326 static inline void xx_mainloop(url_adapt_state_ex_t *ctx, const char *newdata, size_t newlen TSRMLS_DC)
00327 {
00328        char *end, *q;
00329        char *xp;
00330        char *start;
00331        int rest;
00332 
00333        smart_str_appendl(&ctx->buf, newdata, newlen);
00334        
00335        YYCURSOR = ctx->buf.c;
00336        YYLIMIT = ctx->buf.c + ctx->buf.len;
00337 
00338        switch (STATE) {
00339               case STATE_PLAIN: goto state_plain;
00340               case STATE_TAG: goto state_tag;
00341               case STATE_NEXT_ARG: goto state_next_arg;
00342               case STATE_ARG: goto state_arg;
00343               case STATE_BEFORE_VAL: goto state_before_val;
00344               case STATE_VAL: goto state_val;
00345        }
00346        
00347 
00348 state_plain_begin:
00349        STATE = STATE_PLAIN;
00350        
00351 state_plain:
00352        start = YYCURSOR;
00353 
00354 {
00355        YYCTYPE yych;
00356        static const unsigned char yybm[] = {
00357               128, 128, 128, 128, 128, 128, 128, 128, 
00358               128, 128, 128, 128, 128, 128, 128, 128, 
00359               128, 128, 128, 128, 128, 128, 128, 128, 
00360               128, 128, 128, 128, 128, 128, 128, 128, 
00361               128, 128, 128, 128, 128, 128, 128, 128, 
00362               128, 128, 128, 128, 128, 128, 128, 128, 
00363               128, 128, 128, 128, 128, 128, 128, 128, 
00364               128, 128, 128, 128,   0, 128, 128, 128, 
00365               128, 128, 128, 128, 128, 128, 128, 128, 
00366               128, 128, 128, 128, 128, 128, 128, 128, 
00367               128, 128, 128, 128, 128, 128, 128, 128, 
00368               128, 128, 128, 128, 128, 128, 128, 128, 
00369               128, 128, 128, 128, 128, 128, 128, 128, 
00370               128, 128, 128, 128, 128, 128, 128, 128, 
00371               128, 128, 128, 128, 128, 128, 128, 128, 
00372               128, 128, 128, 128, 128, 128, 128, 128, 
00373               128, 128, 128, 128, 128, 128, 128, 128, 
00374               128, 128, 128, 128, 128, 128, 128, 128, 
00375               128, 128, 128, 128, 128, 128, 128, 128, 
00376               128, 128, 128, 128, 128, 128, 128, 128, 
00377               128, 128, 128, 128, 128, 128, 128, 128, 
00378               128, 128, 128, 128, 128, 128, 128, 128, 
00379               128, 128, 128, 128, 128, 128, 128, 128, 
00380               128, 128, 128, 128, 128, 128, 128, 128, 
00381               128, 128, 128, 128, 128, 128, 128, 128, 
00382               128, 128, 128, 128, 128, 128, 128, 128, 
00383               128, 128, 128, 128, 128, 128, 128, 128, 
00384               128, 128, 128, 128, 128, 128, 128, 128, 
00385               128, 128, 128, 128, 128, 128, 128, 128, 
00386               128, 128, 128, 128, 128, 128, 128, 128, 
00387               128, 128, 128, 128, 128, 128, 128, 128, 
00388               128, 128, 128, 128, 128, 128, 128, 128, 
00389        };
00390        if (YYLIMIT <= YYCURSOR) YYFILL(1);
00391        yych = *YYCURSOR;
00392        if (yybm[0+yych] & 128) {
00393               goto yy15;
00394        }
00395        ++YYCURSOR;
00396        { passthru(STD_ARGS); STATE = STATE_TAG; goto state_tag; }
00397 yy15:
00398        ++YYCURSOR;
00399        if (YYLIMIT <= YYCURSOR) YYFILL(1);
00400        yych = *YYCURSOR;
00401        if (yybm[0+yych] & 128) {
00402               goto yy15;
00403        }
00404        { passthru(STD_ARGS); goto state_plain; }
00405 }
00406 
00407 
00408 state_tag:    
00409        start = YYCURSOR;
00410 
00411 {
00412        YYCTYPE yych;
00413        static const unsigned char yybm[] = {
00414                 0,   0,   0,   0,   0,   0,   0,   0, 
00415                 0,   0,   0,   0,   0,   0,   0,   0, 
00416                 0,   0,   0,   0,   0,   0,   0,   0, 
00417                 0,   0,   0,   0,   0,   0,   0,   0, 
00418                 0,   0,   0,   0,   0,   0,   0,   0, 
00419                 0,   0,   0,   0,   0,   0,   0,   0, 
00420                 0,   0,   0,   0,   0,   0,   0,   0, 
00421                 0,   0, 128,   0,   0,   0,   0,   0, 
00422                 0, 128, 128, 128, 128, 128, 128, 128, 
00423               128, 128, 128, 128, 128, 128, 128, 128, 
00424               128, 128, 128, 128, 128, 128, 128, 128, 
00425               128, 128, 128,   0,   0,   0,   0,   0, 
00426                 0, 128, 128, 128, 128, 128, 128, 128, 
00427               128, 128, 128, 128, 128, 128, 128, 128, 
00428               128, 128, 128, 128, 128, 128, 128, 128, 
00429               128, 128, 128,   0,   0,   0,   0,   0, 
00430                 0,   0,   0,   0,   0,   0,   0,   0, 
00431                 0,   0,   0,   0,   0,   0,   0,   0, 
00432                 0,   0,   0,   0,   0,   0,   0,   0, 
00433                 0,   0,   0,   0,   0,   0,   0,   0, 
00434                 0,   0,   0,   0,   0,   0,   0,   0, 
00435                 0,   0,   0,   0,   0,   0,   0,   0, 
00436                 0,   0,   0,   0,   0,   0,   0,   0, 
00437                 0,   0,   0,   0,   0,   0,   0,   0, 
00438                 0,   0,   0,   0,   0,   0,   0,   0, 
00439                 0,   0,   0,   0,   0,   0,   0,   0, 
00440                 0,   0,   0,   0,   0,   0,   0,   0, 
00441                 0,   0,   0,   0,   0,   0,   0,   0, 
00442                 0,   0,   0,   0,   0,   0,   0,   0, 
00443                 0,   0,   0,   0,   0,   0,   0,   0, 
00444                 0,   0,   0,   0,   0,   0,   0,   0, 
00445                 0,   0,   0,   0,   0,   0,   0,   0, 
00446        };
00447        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
00448        yych = *YYCURSOR;
00449        if (yych <= '@') {
00450               if (yych != ':') goto yy22;
00451        } else {
00452               if (yych <= 'Z') goto yy20;
00453               if (yych <= '`') goto yy22;
00454               if (yych >= '{') goto yy22;
00455        }
00456 yy20:
00457        ++YYCURSOR;
00458        yych = *YYCURSOR;
00459        goto yy25;
00460 yy21:
00461        { handle_tag(STD_ARGS); /* Sets STATE */; passthru(STD_ARGS); if (STATE == STATE_PLAIN) goto state_plain; else goto state_next_arg; }
00462 yy22:
00463        ++YYCURSOR;
00464        { passthru(STD_ARGS); goto state_plain_begin; }
00465 yy24:
00466        ++YYCURSOR;
00467        if (YYLIMIT <= YYCURSOR) YYFILL(1);
00468        yych = *YYCURSOR;
00469 yy25:
00470        if (yybm[0+yych] & 128) {
00471               goto yy24;
00472        }
00473        goto yy21;
00474 }
00475 
00476 
00477 state_next_arg_begin:
00478        STATE = STATE_NEXT_ARG;
00479        
00480 state_next_arg:
00481        start = YYCURSOR;
00482 
00483 {
00484        YYCTYPE yych;
00485        static const unsigned char yybm[] = {
00486                 0,   0,   0,   0,   0,   0,   0,   0, 
00487                 0, 128, 128, 128,   0, 128,   0,   0, 
00488                 0,   0,   0,   0,   0,   0,   0,   0, 
00489                 0,   0,   0,   0,   0,   0,   0,   0, 
00490               128,   0,   0,   0,   0,   0,   0,   0, 
00491                 0,   0,   0,   0,   0,   0,   0,   0, 
00492                 0,   0,   0,   0,   0,   0,   0,   0, 
00493                 0,   0,   0,   0,   0,   0,   0,   0, 
00494                 0,   0,   0,   0,   0,   0,   0,   0, 
00495                 0,   0,   0,   0,   0,   0,   0,   0, 
00496                 0,   0,   0,   0,   0,   0,   0,   0, 
00497                 0,   0,   0,   0,   0,   0,   0,   0, 
00498                 0,   0,   0,   0,   0,   0,   0,   0, 
00499                 0,   0,   0,   0,   0,   0,   0,   0, 
00500                 0,   0,   0,   0,   0,   0,   0,   0, 
00501                 0,   0,   0,   0,   0,   0,   0,   0, 
00502                 0,   0,   0,   0,   0,   0,   0,   0, 
00503                 0,   0,   0,   0,   0,   0,   0,   0, 
00504                 0,   0,   0,   0,   0,   0,   0,   0, 
00505                 0,   0,   0,   0,   0,   0,   0,   0, 
00506                 0,   0,   0,   0,   0,   0,   0,   0, 
00507                 0,   0,   0,   0,   0,   0,   0,   0, 
00508                 0,   0,   0,   0,   0,   0,   0,   0, 
00509                 0,   0,   0,   0,   0,   0,   0,   0, 
00510                 0,   0,   0,   0,   0,   0,   0,   0, 
00511                 0,   0,   0,   0,   0,   0,   0,   0, 
00512                 0,   0,   0,   0,   0,   0,   0,   0, 
00513                 0,   0,   0,   0,   0,   0,   0,   0, 
00514                 0,   0,   0,   0,   0,   0,   0,   0, 
00515                 0,   0,   0,   0,   0,   0,   0,   0, 
00516                 0,   0,   0,   0,   0,   0,   0,   0, 
00517                 0,   0,   0,   0,   0,   0,   0,   0, 
00518        };
00519        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
00520        yych = *YYCURSOR;
00521        if (yych <= ' ') {
00522               if (yych <= '\f') {
00523                      if (yych <= 0x08) goto yy34;
00524                      if (yych <= '\v') goto yy30;
00525                      goto yy34;
00526               } else {
00527                      if (yych <= '\r') goto yy30;
00528                      if (yych <= 0x1F) goto yy34;
00529                      goto yy30;
00530               }
00531        } else {
00532               if (yych <= '@') {
00533                      if (yych != '>') goto yy34;
00534               } else {
00535                      if (yych <= 'Z') goto yy32;
00536                      if (yych <= '`') goto yy34;
00537                      if (yych <= 'z') goto yy32;
00538                      goto yy34;
00539               }
00540        }
00541        ++YYCURSOR;
00542        { passthru(STD_ARGS); handle_form(STD_ARGS); goto state_plain_begin; }
00543 yy30:
00544        ++YYCURSOR;
00545        yych = *YYCURSOR;
00546        goto yy37;
00547 yy31:
00548        { passthru(STD_ARGS); goto state_next_arg; }
00549 yy32:
00550        ++YYCURSOR;
00551        { --YYCURSOR; STATE = STATE_ARG; goto state_arg; }
00552 yy34:
00553        ++YYCURSOR;
00554        { passthru(STD_ARGS); goto state_plain_begin; }
00555 yy36:
00556        ++YYCURSOR;
00557        if (YYLIMIT <= YYCURSOR) YYFILL(1);
00558        yych = *YYCURSOR;
00559 yy37:
00560        if (yybm[0+yych] & 128) {
00561               goto yy36;
00562        }
00563        goto yy31;
00564 }
00565 
00566 
00567 state_arg:
00568        start = YYCURSOR;
00569 
00570 {
00571        YYCTYPE yych;
00572        static const unsigned char yybm[] = {
00573                 0,   0,   0,   0,   0,   0,   0,   0, 
00574                 0,   0,   0,   0,   0,   0,   0,   0, 
00575                 0,   0,   0,   0,   0,   0,   0,   0, 
00576                 0,   0,   0,   0,   0,   0,   0,   0, 
00577                 0,   0,   0,   0,   0,   0,   0,   0, 
00578                 0,   0,   0,   0,   0, 128,   0,   0, 
00579                 0,   0,   0,   0,   0,   0,   0,   0, 
00580                 0,   0,   0,   0,   0,   0,   0,   0, 
00581                 0, 128, 128, 128, 128, 128, 128, 128, 
00582               128, 128, 128, 128, 128, 128, 128, 128, 
00583               128, 128, 128, 128, 128, 128, 128, 128, 
00584               128, 128, 128,   0,   0,   0,   0,   0, 
00585                 0, 128, 128, 128, 128, 128, 128, 128, 
00586               128, 128, 128, 128, 128, 128, 128, 128, 
00587               128, 128, 128, 128, 128, 128, 128, 128, 
00588               128, 128, 128,   0,   0,   0,   0,   0, 
00589                 0,   0,   0,   0,   0,   0,   0,   0, 
00590                 0,   0,   0,   0,   0,   0,   0,   0, 
00591                 0,   0,   0,   0,   0,   0,   0,   0, 
00592                 0,   0,   0,   0,   0,   0,   0,   0, 
00593                 0,   0,   0,   0,   0,   0,   0,   0, 
00594                 0,   0,   0,   0,   0,   0,   0,   0, 
00595                 0,   0,   0,   0,   0,   0,   0,   0, 
00596                 0,   0,   0,   0,   0,   0,   0,   0, 
00597                 0,   0,   0,   0,   0,   0,   0,   0, 
00598                 0,   0,   0,   0,   0,   0,   0,   0, 
00599                 0,   0,   0,   0,   0,   0,   0,   0, 
00600                 0,   0,   0,   0,   0,   0,   0,   0, 
00601                 0,   0,   0,   0,   0,   0,   0,   0, 
00602                 0,   0,   0,   0,   0,   0,   0,   0, 
00603                 0,   0,   0,   0,   0,   0,   0,   0, 
00604                 0,   0,   0,   0,   0,   0,   0,   0, 
00605        };
00606        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
00607        yych = *YYCURSOR;
00608        if (yych <= '@') goto yy42;
00609        if (yych <= 'Z') goto yy40;
00610        if (yych <= '`') goto yy42;
00611        if (yych >= '{') goto yy42;
00612 yy40:
00613        ++YYCURSOR;
00614        yych = *YYCURSOR;
00615        goto yy45;
00616 yy41:
00617        { passthru(STD_ARGS); handle_arg(STD_ARGS); STATE = STATE_BEFORE_VAL; goto state_before_val; }
00618 yy42:
00619        ++YYCURSOR;
00620        { passthru(STD_ARGS); STATE = STATE_NEXT_ARG; goto state_next_arg; }
00621 yy44:
00622        ++YYCURSOR;
00623        if (YYLIMIT <= YYCURSOR) YYFILL(1);
00624        yych = *YYCURSOR;
00625 yy45:
00626        if (yybm[0+yych] & 128) {
00627               goto yy44;
00628        }
00629        goto yy41;
00630 }
00631 
00632 
00633 state_before_val:
00634        start = YYCURSOR;
00635 
00636 {
00637        YYCTYPE yych;
00638        static const unsigned char yybm[] = {
00639                 0,   0,   0,   0,   0,   0,   0,   0, 
00640                 0,   0,   0,   0,   0,   0,   0,   0, 
00641                 0,   0,   0,   0,   0,   0,   0,   0, 
00642                 0,   0,   0,   0,   0,   0,   0,   0, 
00643               128,   0,   0,   0,   0,   0,   0,   0, 
00644                 0,   0,   0,   0,   0,   0,   0,   0, 
00645                 0,   0,   0,   0,   0,   0,   0,   0, 
00646                 0,   0,   0,   0,   0,   0,   0,   0, 
00647                 0,   0,   0,   0,   0,   0,   0,   0, 
00648                 0,   0,   0,   0,   0,   0,   0,   0, 
00649                 0,   0,   0,   0,   0,   0,   0,   0, 
00650                 0,   0,   0,   0,   0,   0,   0,   0, 
00651                 0,   0,   0,   0,   0,   0,   0,   0, 
00652                 0,   0,   0,   0,   0,   0,   0,   0, 
00653                 0,   0,   0,   0,   0,   0,   0,   0, 
00654                 0,   0,   0,   0,   0,   0,   0,   0, 
00655                 0,   0,   0,   0,   0,   0,   0,   0, 
00656                 0,   0,   0,   0,   0,   0,   0,   0, 
00657                 0,   0,   0,   0,   0,   0,   0,   0, 
00658                 0,   0,   0,   0,   0,   0,   0,   0, 
00659                 0,   0,   0,   0,   0,   0,   0,   0, 
00660                 0,   0,   0,   0,   0,   0,   0,   0, 
00661                 0,   0,   0,   0,   0,   0,   0,   0, 
00662                 0,   0,   0,   0,   0,   0,   0,   0, 
00663                 0,   0,   0,   0,   0,   0,   0,   0, 
00664                 0,   0,   0,   0,   0,   0,   0,   0, 
00665                 0,   0,   0,   0,   0,   0,   0,   0, 
00666                 0,   0,   0,   0,   0,   0,   0,   0, 
00667                 0,   0,   0,   0,   0,   0,   0,   0, 
00668                 0,   0,   0,   0,   0,   0,   0,   0, 
00669                 0,   0,   0,   0,   0,   0,   0,   0, 
00670                 0,   0,   0,   0,   0,   0,   0,   0, 
00671        };
00672        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
00673        yych = *YYCURSOR;
00674        if (yych == ' ') goto yy48;
00675        if (yych == '=') goto yy50;
00676        goto yy52;
00677 yy48:
00678        yych = *(YYMARKER = ++YYCURSOR);
00679        if (yych == ' ') goto yy55;
00680        if (yych == '=') goto yy53;
00681 yy49:
00682        { --YYCURSOR; goto state_next_arg_begin; }
00683 yy50:
00684        ++YYCURSOR;
00685        yych = *YYCURSOR;
00686        goto yy54;
00687 yy51:
00688        { passthru(STD_ARGS); STATE = STATE_VAL; goto state_val; }
00689 yy52:
00690        yych = *++YYCURSOR;
00691        goto yy49;
00692 yy53:
00693        ++YYCURSOR;
00694        if (YYLIMIT <= YYCURSOR) YYFILL(1);
00695        yych = *YYCURSOR;
00696 yy54:
00697        if (yybm[0+yych] & 128) {
00698               goto yy53;
00699        }
00700        goto yy51;
00701 yy55:
00702        ++YYCURSOR;
00703        if (YYLIMIT <= YYCURSOR) YYFILL(1);
00704        yych = *YYCURSOR;
00705        if (yych == ' ') goto yy55;
00706        if (yych == '=') goto yy53;
00707        YYCURSOR = YYMARKER;
00708        goto yy49;
00709 }
00710 
00711 
00712 
00713 state_val:
00714        start = YYCURSOR;
00715 
00716 {
00717        YYCTYPE yych;
00718        static const unsigned char yybm[] = {
00719               248, 248, 248, 248, 248, 248, 248, 248, 
00720               248, 160, 160, 248, 248, 160, 248, 248, 
00721               248, 248, 248, 248, 248, 248, 248, 248, 
00722               248, 248, 248, 248, 248, 248, 248, 248, 
00723               160, 248,  56, 248, 248, 248, 248, 200, 
00724               248, 248, 248, 248, 248, 248, 248, 248, 
00725               248, 248, 248, 248, 248, 248, 248, 248, 
00726               248, 248, 248, 248, 248, 248,   0, 248, 
00727               248, 248, 248, 248, 248, 248, 248, 248, 
00728               248, 248, 248, 248, 248, 248, 248, 248, 
00729               248, 248, 248, 248, 248, 248, 248, 248, 
00730               248, 248, 248, 248, 248, 248, 248, 248, 
00731               248, 248, 248, 248, 248, 248, 248, 248, 
00732               248, 248, 248, 248, 248, 248, 248, 248, 
00733               248, 248, 248, 248, 248, 248, 248, 248, 
00734               248, 248, 248, 248, 248, 248, 248, 248, 
00735               248, 248, 248, 248, 248, 248, 248, 248, 
00736               248, 248, 248, 248, 248, 248, 248, 248, 
00737               248, 248, 248, 248, 248, 248, 248, 248, 
00738               248, 248, 248, 248, 248, 248, 248, 248, 
00739               248, 248, 248, 248, 248, 248, 248, 248, 
00740               248, 248, 248, 248, 248, 248, 248, 248, 
00741               248, 248, 248, 248, 248, 248, 248, 248, 
00742               248, 248, 248, 248, 248, 248, 248, 248, 
00743               248, 248, 248, 248, 248, 248, 248, 248, 
00744               248, 248, 248, 248, 248, 248, 248, 248, 
00745               248, 248, 248, 248, 248, 248, 248, 248, 
00746               248, 248, 248, 248, 248, 248, 248, 248, 
00747               248, 248, 248, 248, 248, 248, 248, 248, 
00748               248, 248, 248, 248, 248, 248, 248, 248, 
00749               248, 248, 248, 248, 248, 248, 248, 248, 
00750               248, 248, 248, 248, 248, 248, 248, 248, 
00751        };
00752        if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3);
00753        yych = *YYCURSOR;
00754        if (yych <= ' ') {
00755               if (yych <= '\f') {
00756                      if (yych <= 0x08) goto yy63;
00757                      if (yych <= '\n') goto yy64;
00758                      goto yy63;
00759               } else {
00760                      if (yych <= '\r') goto yy64;
00761                      if (yych <= 0x1F) goto yy63;
00762                      goto yy64;
00763               }
00764        } else {
00765               if (yych <= '&') {
00766                      if (yych != '"') goto yy63;
00767               } else {
00768                      if (yych <= '\'') goto yy62;
00769                      if (yych == '>') goto yy64;
00770                      goto yy63;
00771               }
00772        }
00773        yych = *(YYMARKER = ++YYCURSOR);
00774        goto yy77;
00775 yy61:
00776        { handle_val(STD_ARGS, 0, ' '); goto state_next_arg_begin; }
00777 yy62:
00778        yych = *(YYMARKER = ++YYCURSOR);
00779        goto yy69;
00780 yy63:
00781        yych = *++YYCURSOR;
00782        goto yy67;
00783 yy64:
00784        ++YYCURSOR;
00785        { passthru(STD_ARGS); goto state_next_arg_begin; }
00786 yy66:
00787        ++YYCURSOR;
00788        if (YYLIMIT <= YYCURSOR) YYFILL(1);
00789        yych = *YYCURSOR;
00790 yy67:
00791        if (yybm[0+yych] & 8) {
00792               goto yy66;
00793        }
00794        goto yy61;
00795 yy68:
00796        YYMARKER = ++YYCURSOR;
00797        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
00798        yych = *YYCURSOR;
00799 yy69:
00800        if (yybm[0+yych] & 16) {
00801               goto yy68;
00802        }
00803        if (yych <= '&') goto yy72;
00804        if (yych >= '(') goto yy61;
00805        ++YYCURSOR;
00806        if (yybm[0+(yych = *YYCURSOR)] & 8) {
00807               goto yy66;
00808        }
00809 yy71:
00810        { handle_val(STD_ARGS, 1, '\''); goto state_next_arg_begin; }
00811 yy72:
00812        ++YYCURSOR;
00813        if (YYLIMIT <= YYCURSOR) YYFILL(1);
00814        yych = *YYCURSOR;
00815        if (yybm[0+yych] & 32) {
00816               goto yy72;
00817        }
00818        if (yych <= '=') goto yy75;
00819 yy74:
00820        YYCURSOR = YYMARKER;
00821        goto yy61;
00822 yy75:
00823        yych = *++YYCURSOR;
00824        goto yy71;
00825 yy76:
00826        YYMARKER = ++YYCURSOR;
00827        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
00828        yych = *YYCURSOR;
00829 yy77:
00830        if (yybm[0+yych] & 64) {
00831               goto yy76;
00832        }
00833        if (yych <= '!') goto yy80;
00834        if (yych >= '#') goto yy61;
00835        ++YYCURSOR;
00836        if (yybm[0+(yych = *YYCURSOR)] & 8) {
00837               goto yy66;
00838        }
00839 yy79:
00840        { handle_val(STD_ARGS, 1, '"'); goto state_next_arg_begin; }
00841 yy80:
00842        ++YYCURSOR;
00843        if (YYLIMIT <= YYCURSOR) YYFILL(1);
00844        yych = *YYCURSOR;
00845        if (yybm[0+yych] & 128) {
00846               goto yy80;
00847        }
00848        if (yych >= '>') goto yy74;
00849        ++YYCURSOR;
00850        yych = *YYCURSOR;
00851        goto yy79;
00852 }
00853 
00854 
00855 stop:
00856        rest = YYLIMIT - start;
00857        scdebug(("stopped in state %d at pos %d (%d:%c) %d\n", STATE, YYCURSOR - ctx->buf.c, *YYCURSOR, *YYCURSOR, rest));
00858        /* XXX: Crash avoidance. Need to work with reporter to figure out what goes wrong */       
00859        if (rest < 0) rest = 0;
00860        
00861        if (rest) memmove(ctx->buf.c, start, rest);
00862        ctx->buf.len = rest;
00863 }
00864 
00865 char *php_url_scanner_adapt_single_url(const char *url, size_t urllen, const char *name, const char *value, size_t *newlen TSRMLS_DC)
00866 {
00867        smart_str surl = {0};
00868        smart_str buf = {0};
00869        smart_str url_app = {0};
00870 
00871        smart_str_setl(&surl, url, urllen);
00872 
00873        smart_str_appends(&url_app, name);
00874        smart_str_appendc(&url_app, '=');
00875        smart_str_appends(&url_app, value);
00876 
00877        append_modified_url(&surl, &buf, &url_app, PG(arg_separator).output);
00878 
00879        smart_str_0(&buf);
00880        if (newlen) *newlen = buf.len;
00881 
00882        smart_str_free(&url_app);
00883 
00884        return buf.c;
00885 }
00886 
00887 
00888 static char *url_adapt_ext(const char *src, size_t srclen, size_t *newlen, zend_bool do_flush TSRMLS_DC)
00889 {
00890        url_adapt_state_ex_t *ctx;
00891        char *retval;
00892 
00893        ctx = &BG(url_adapt_state_ex);
00894 
00895        xx_mainloop(ctx, src, srclen TSRMLS_CC);
00896 
00897        *newlen = ctx->result.len;
00898        if (!ctx->result.c) {
00899               smart_str_appendl(&ctx->result, "", 0);
00900        }
00901        smart_str_0(&ctx->result);
00902        if (do_flush) {
00903               smart_str_appendl(&ctx->result, ctx->buf.c, ctx->buf.len);
00904               *newlen += ctx->buf.len;
00905               smart_str_free(&ctx->buf);
00906        }
00907        retval = ctx->result.c;
00908        ctx->result.c = NULL;
00909        ctx->result.len = 0;
00910        return retval;
00911 }
00912 
00913 static int php_url_scanner_ex_activate(TSRMLS_D)
00914 {
00915        url_adapt_state_ex_t *ctx;
00916        
00917        ctx = &BG(url_adapt_state_ex);
00918 
00919        memset(ctx, 0, ((size_t) &((url_adapt_state_ex_t *)0)->tags));
00920 
00921        return SUCCESS;
00922 }
00923 
00924 static int php_url_scanner_ex_deactivate(TSRMLS_D)
00925 {
00926        url_adapt_state_ex_t *ctx;
00927        
00928        ctx = &BG(url_adapt_state_ex);
00929 
00930        smart_str_free(&ctx->result);
00931        smart_str_free(&ctx->buf);
00932        smart_str_free(&ctx->tag);
00933        smart_str_free(&ctx->arg);
00934 
00935        return SUCCESS;
00936 }
00937 
00938 static void php_url_scanner_output_handler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC)
00939 {
00940        size_t len;
00941 
00942        if (BG(url_adapt_state_ex).url_app.len != 0) {
00943               *handled_output = url_adapt_ext(output, output_len, &len, (zend_bool) (mode & (PHP_OUTPUT_HANDLER_END | PHP_OUTPUT_HANDLER_CONT) ? 1 : 0) TSRMLS_CC);
00944               if (sizeof(uint) < sizeof(size_t)) {
00945                      if (len > UINT_MAX)
00946                             len = UINT_MAX;
00947               }
00948               *handled_output_len = len;
00949        } else if (BG(url_adapt_state_ex).url_app.len == 0) {
00950               url_adapt_state_ex_t *ctx = &BG(url_adapt_state_ex);
00951               if (ctx->buf.len) {
00952                      smart_str_appendl(&ctx->result, ctx->buf.c, ctx->buf.len);
00953                      smart_str_appendl(&ctx->result, output, output_len);
00954 
00955                      *handled_output = ctx->result.c;
00956                      *handled_output_len = ctx->buf.len + output_len;
00957 
00958                      ctx->result.c = NULL;
00959                      ctx->result.len = 0;
00960                      smart_str_free(&ctx->buf);
00961               } else {
00962                      *handled_output = NULL;
00963               }
00964        } else {
00965               *handled_output = NULL;
00966        }
00967 }
00968 
00969 PHPAPI int php_url_scanner_add_var(char *name, int name_len, char *value, int value_len, int urlencode TSRMLS_DC)
00970 {
00971        char *encoded;
00972        int encoded_len;
00973        smart_str val;
00974        
00975        if (! BG(url_adapt_state_ex).active) {
00976               php_url_scanner_ex_activate(TSRMLS_C);
00977               php_ob_set_internal_handler(php_url_scanner_output_handler, 0, "URL-Rewriter", 1 TSRMLS_CC);
00978               BG(url_adapt_state_ex).active = 1;
00979        }
00980 
00981 
00982        if (BG(url_adapt_state_ex).url_app.len != 0) {
00983               smart_str_appends(&BG(url_adapt_state_ex).url_app, PG(arg_separator).output);
00984        }
00985 
00986        if (urlencode) {
00987               encoded = php_url_encode(value, value_len, &encoded_len);
00988               smart_str_setl(&val, encoded, encoded_len);
00989        } else {
00990               smart_str_setl(&val, value, value_len);
00991        }
00992        
00993        smart_str_appendl(&BG(url_adapt_state_ex).url_app, name, name_len);
00994        smart_str_appendc(&BG(url_adapt_state_ex).url_app, '=');
00995        smart_str_append(&BG(url_adapt_state_ex).url_app, &val);
00996 
00997        smart_str_appends(&BG(url_adapt_state_ex).form_app, "<input type=\"hidden\" name=\""); 
00998        smart_str_appendl(&BG(url_adapt_state_ex).form_app, name, name_len);
00999        smart_str_appends(&BG(url_adapt_state_ex).form_app, "\" value=\"");
01000        smart_str_append(&BG(url_adapt_state_ex).form_app, &val);
01001        smart_str_appends(&BG(url_adapt_state_ex).form_app, "\" />");
01002 
01003        if (urlencode)
01004               efree(encoded);
01005 
01006        return SUCCESS;
01007 }
01008 
01009 PHPAPI int php_url_scanner_reset_vars(TSRMLS_D)
01010 {
01011        BG(url_adapt_state_ex).form_app.len = 0;
01012        BG(url_adapt_state_ex).url_app.len = 0;
01013 
01014        return SUCCESS;
01015 }
01016 
01017 PHP_MINIT_FUNCTION(url_scanner)
01018 {
01019        BG(url_adapt_state_ex).tags = NULL;
01020 
01021        BG(url_adapt_state_ex).form_app.c = BG(url_adapt_state_ex).url_app.c = 0;
01022        BG(url_adapt_state_ex).form_app.len = BG(url_adapt_state_ex).url_app.len = 0;
01023 
01024        REGISTER_INI_ENTRIES();
01025        return SUCCESS;
01026 }
01027 
01028 PHP_MSHUTDOWN_FUNCTION(url_scanner)
01029 {
01030        UNREGISTER_INI_ENTRIES();
01031 
01032        return SUCCESS;
01033 }
01034 
01035 PHP_RINIT_FUNCTION(url_scanner)
01036 {
01037        BG(url_adapt_state_ex).active = 0;
01038        
01039        return SUCCESS;
01040 }
01041 
01042 PHP_RSHUTDOWN_FUNCTION(url_scanner)
01043 {
01044        if (BG(url_adapt_state_ex).active) {
01045               php_url_scanner_ex_deactivate(TSRMLS_C);
01046               BG(url_adapt_state_ex).active = 0;
01047        }
01048 
01049        smart_str_free(&BG(url_adapt_state_ex).form_app);
01050        smart_str_free(&BG(url_adapt_state_ex).url_app);
01051 
01052        return SUCCESS;
01053 }