root/main/php_variables.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. php_register_variable
  2. php_register_variable_safe
  3. php_register_variable_ex
  4. add_post_var
  5. add_post_vars
  6. SAPI_POST_HANDLER_FUNC
  7. SAPI_INPUT_FILTER_FUNC
  8. SAPI_TREAT_DATA_FUNC
  9. _php_import_environment_variables
  10. php_std_auto_global_callback
  11. php_build_argv
  12. php_register_server_variables
  13. php_autoglobal_merge
  14. php_hash_environment
  15. php_auto_globals_create_get
  16. php_auto_globals_create_post
  17. php_auto_globals_create_cookie
  18. php_auto_globals_create_files
  19. php_auto_globals_create_server
  20. php_auto_globals_create_env
  21. php_auto_globals_create_request
  22. php_startup_auto_globals

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 5                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca>                       |
  16    |          Zeev Suraski <zeev@zend.com>                                |
  17    +----------------------------------------------------------------------+
  18  */
  19 
  20 /* $Id$ */
  21 
  22 #include <stdio.h>
  23 #include "php.h"
  24 #include "ext/standard/php_standard.h"
  25 #include "ext/standard/credits.h"
  26 #include "ext/standard/php_smart_str.h"
  27 #include "php_variables.h"
  28 #include "php_globals.h"
  29 #include "php_content_types.h"
  30 #include "SAPI.h"
  31 #include "zend_globals.h"
  32 #ifdef PHP_WIN32
  33 # include "win32/php_inttypes.h"
  34 #endif
  35 
  36 /* for systems that need to override reading of environment variables */
  37 void _php_import_environment_variables(zval *array_ptr TSRMLS_DC);
  38 PHPAPI void (*php_import_environment_variables)(zval *array_ptr TSRMLS_DC) = _php_import_environment_variables;
  39 
  40 PHPAPI void php_register_variable(char *var, char *strval, zval *track_vars_array TSRMLS_DC)
  41 {
  42         php_register_variable_safe(var, strval, strlen(strval), track_vars_array TSRMLS_CC);
  43 }
  44 
  45 /* binary-safe version */
  46 PHPAPI void php_register_variable_safe(char *var, char *strval, int str_len, zval *track_vars_array TSRMLS_DC)
  47 {
  48         zval new_entry;
  49         assert(strval != NULL);
  50         
  51         /* Prepare value */
  52         Z_STRLEN(new_entry) = str_len;
  53         Z_STRVAL(new_entry) = estrndup(strval, Z_STRLEN(new_entry));
  54         Z_TYPE(new_entry) = IS_STRING;
  55 
  56         php_register_variable_ex(var, &new_entry, track_vars_array TSRMLS_CC);
  57 }
  58 
  59 PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars_array TSRMLS_DC)
  60 {
  61         char *p = NULL;
  62         char *ip = NULL;                /* index pointer */
  63         char *index;
  64         char *var, *var_orig;
  65         int var_len, index_len;
  66         zval *gpc_element, **gpc_element_p;
  67         zend_bool is_array = 0;
  68         HashTable *symtable1 = NULL;
  69         ALLOCA_FLAG(use_heap)
  70 
  71         assert(var_name != NULL);
  72 
  73         if (track_vars_array) {
  74                 symtable1 = Z_ARRVAL_P(track_vars_array);
  75         }
  76 
  77         if (!symtable1) {
  78                 /* Nothing to do */
  79                 zval_dtor(val);
  80                 return;
  81         }
  82 
  83 
  84         /* ignore leading spaces in the variable name */
  85         while (*var_name && *var_name==' ') {
  86                 var_name++;
  87         }
  88         
  89         /*
  90          * Prepare variable name
  91          */
  92         var_len = strlen(var_name);
  93         var = var_orig = do_alloca(var_len + 1, use_heap);
  94         memcpy(var_orig, var_name, var_len + 1);
  95 
  96         /* ensure that we don't have spaces or dots in the variable name (not binary safe) */
  97         for (p = var; *p; p++) {
  98                 if (*p == ' ' || *p == '.') {
  99                         *p='_';
 100                 } else if (*p == '[') {
 101                         is_array = 1;
 102                         ip = p;
 103                         *p = 0;
 104                         break;
 105                 }
 106         }
 107         var_len = p - var;
 108 
 109         if (var_len==0) { /* empty variable name, or variable name with a space in it */
 110                 zval_dtor(val);
 111                 free_alloca(var_orig, use_heap);
 112                 return;
 113         }
 114 
 115         /* GLOBALS hijack attempt, reject parameter */
 116         if (symtable1 == EG(active_symbol_table) &&
 117                 var_len == sizeof("GLOBALS")-1 &&
 118                 !memcmp(var, "GLOBALS", sizeof("GLOBALS")-1)) {
 119                 zval_dtor(val);
 120                 free_alloca(var_orig, use_heap);
 121                 return;
 122         }
 123 
 124         index = var;
 125         index_len = var_len;
 126 
 127         if (is_array) {
 128                 int nest_level = 0;
 129                 while (1) {
 130                         char *index_s;
 131                         int new_idx_len = 0;
 132 
 133                         if(++nest_level > PG(max_input_nesting_level)) {
 134                                 HashTable *ht;
 135                                 /* too many levels of nesting */
 136 
 137                                 if (track_vars_array) {
 138                                         ht = Z_ARRVAL_P(track_vars_array);
 139                                         zend_symtable_del(ht, var, var_len + 1);
 140                                 }
 141 
 142                                 zval_dtor(val);
 143 
 144                                 /* do not output the error message to the screen,
 145                                  this helps us to to avoid "information disclosure" */
 146                                 if (!PG(display_errors)) {
 147                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Input variable nesting level exceeded %ld. To increase the limit change max_input_nesting_level in php.ini.", PG(max_input_nesting_level));
 148                                 }
 149                                 free_alloca(var_orig, use_heap);
 150                                 return;
 151                         }
 152 
 153                         ip++;
 154                         index_s = ip;
 155                         if (isspace(*ip)) {
 156                                 ip++;
 157                         }
 158                         if (*ip==']') {
 159                                 index_s = NULL;
 160                         } else {
 161                                 ip = strchr(ip, ']');
 162                                 if (!ip) {
 163                                         /* PHP variables cannot contain '[' in their names, so we replace the character with a '_' */
 164                                         *(index_s - 1) = '_';
 165 
 166                                         index_len = 0;
 167                                         if (index) {
 168                                                 index_len = strlen(index);
 169                                         }
 170                                         goto plain_var;
 171                                         return;
 172                                 }
 173                                 *ip = 0;
 174                                 new_idx_len = strlen(index_s);  
 175                         }
 176 
 177                         if (!index) {
 178                                 MAKE_STD_ZVAL(gpc_element);
 179                                 array_init(gpc_element);
 180                                 if (zend_hash_next_index_insert(symtable1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p) == FAILURE) {
 181                                         zval_ptr_dtor(&gpc_element);
 182                                         zval_dtor(val);
 183                                         free_alloca(var_orig, use_heap);
 184                                         return;
 185                                 }
 186                         } else {
 187                                 if (zend_symtable_find(symtable1, index, index_len + 1, (void **) &gpc_element_p) == FAILURE
 188                                         || Z_TYPE_PP(gpc_element_p) != IS_ARRAY) {
 189                                         MAKE_STD_ZVAL(gpc_element);
 190                                         array_init(gpc_element);
 191                                         zend_symtable_update(symtable1, index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
 192                                 }
 193                         }
 194                         symtable1 = Z_ARRVAL_PP(gpc_element_p);
 195                         /* ip pointed to the '[' character, now obtain the key */
 196                         index = index_s;
 197                         index_len = new_idx_len;
 198 
 199                         ip++;
 200                         if (*ip == '[') {
 201                                 is_array = 1;
 202                                 *ip = 0;
 203                         } else {
 204                                 goto plain_var;
 205                         }
 206                 }
 207         } else {
 208 plain_var:
 209                 MAKE_STD_ZVAL(gpc_element);
 210                 gpc_element->value = val->value;
 211                 Z_TYPE_P(gpc_element) = Z_TYPE_P(val);
 212                 if (!index) {
 213                         if (zend_hash_next_index_insert(symtable1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p) == FAILURE) {
 214                                 zval_ptr_dtor(&gpc_element);
 215                         }
 216                 } else {
 217                         /* 
 218                          * According to rfc2965, more specific paths are listed above the less specific ones.
 219                          * If we encounter a duplicate cookie name, we should skip it, since it is not possible
 220                          * to have the same (plain text) cookie name for the same path and we should not overwrite
 221                          * more specific cookies with the less specific ones.
 222                          */
 223                         if (PG(http_globals)[TRACK_VARS_COOKIE] &&
 224                                 symtable1 == Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_COOKIE]) &&
 225                                 zend_symtable_exists(symtable1, index, index_len + 1)) {
 226                                 zval_ptr_dtor(&gpc_element);
 227                         } else {
 228                                 zend_symtable_update(symtable1, index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
 229                         }
 230                 }
 231         }
 232         free_alloca(var_orig, use_heap);
 233 }
 234 
 235 typedef struct post_var_data {
 236         smart_str str;
 237         char *ptr;
 238         char *end;
 239         uint64_t cnt;
 240 } post_var_data_t;
 241 
 242 static zend_bool add_post_var(zval *arr, post_var_data_t *var, zend_bool eof TSRMLS_DC)
 243 {
 244         char *ksep, *vsep, *val;
 245         size_t klen, vlen;
 246         /* FIXME: string-size_t */
 247         unsigned int new_vlen;
 248 
 249         if (var->ptr >= var->end) {
 250                 return 0;
 251         }
 252 
 253         vsep = memchr(var->ptr, '&', var->end - var->ptr);
 254         if (!vsep) {
 255                 if (!eof) {
 256                         return 0;
 257                 } else {
 258                         vsep = var->end;
 259                 }
 260         }
 261 
 262         ksep = memchr(var->ptr, '=', vsep - var->ptr);
 263         if (ksep) {
 264                 *ksep = '\0';
 265                 /* "foo=bar&" or "foo=&" */
 266                 klen = ksep - var->ptr;
 267                 vlen = vsep - ++ksep;
 268         } else {
 269                 ksep = "";
 270                 /* "foo&" */
 271                 klen = vsep - var->ptr;
 272                 vlen = 0;
 273         }
 274 
 275         php_url_decode(var->ptr, klen);
 276 
 277         val = estrndup(ksep, vlen);
 278         if (vlen) {
 279                 vlen = php_url_decode(val, vlen);
 280         }
 281 
 282         if (sapi_module.input_filter(PARSE_POST, var->ptr, &val, vlen, &new_vlen TSRMLS_CC)) {
 283                 php_register_variable_safe(var->ptr, val, new_vlen, arr TSRMLS_CC);
 284         }
 285         efree(val);
 286 
 287         var->ptr = vsep + (vsep != var->end);
 288         return 1;
 289 }
 290 
 291 static inline int add_post_vars(zval *arr, post_var_data_t *vars, zend_bool eof TSRMLS_DC)
 292 {
 293         uint64_t max_vars = PG(max_input_vars);
 294 
 295         vars->ptr = vars->str.c;
 296         vars->end = vars->str.c + vars->str.len;
 297         while (add_post_var(arr, vars, eof TSRMLS_CC)) {
 298                 if (++vars->cnt > max_vars) {
 299                         php_error_docref(NULL TSRMLS_CC, E_WARNING,
 300                                         "Input variables exceeded %" PRIu64 ". "
 301                                         "To increase the limit change max_input_vars in php.ini.",
 302                                         max_vars);
 303                         return FAILURE;
 304                 }
 305         }
 306 
 307         if (!eof) {
 308                 memmove(vars->str.c, vars->ptr, vars->str.len = vars->end - vars->ptr);
 309         }
 310         return SUCCESS;
 311 }
 312 
 313 #ifdef PHP_WIN32
 314 #define SAPI_POST_HANDLER_BUFSIZ 16384
 315 #else
 316 # define SAPI_POST_HANDLER_BUFSIZ BUFSIZ
 317 #endif
 318 SAPI_API SAPI_POST_HANDLER_FUNC(php_std_post_handler)
 319 {
 320         zval *arr = (zval *) arg;
 321         php_stream *s = SG(request_info).request_body;
 322         post_var_data_t post_data;
 323 
 324         if (s && SUCCESS == php_stream_rewind(s)) {
 325                 memset(&post_data, 0, sizeof(post_data));
 326 
 327                 while (!php_stream_eof(s)) {
 328                         char buf[SAPI_POST_HANDLER_BUFSIZ] = {0};
 329                         size_t len = php_stream_read(s, buf, SAPI_POST_HANDLER_BUFSIZ);
 330 
 331                         if (len && len != (size_t) -1) {
 332                                 smart_str_appendl(&post_data.str, buf, len);
 333 
 334                                 if (SUCCESS != add_post_vars(arr, &post_data, 0 TSRMLS_CC)) {
 335                                         if (post_data.str.c) {
 336                                                 efree(post_data.str.c);
 337                                         }
 338                                         return;
 339                                 }
 340                         }
 341 
 342                         if (len != SAPI_POST_HANDLER_BUFSIZ){
 343                                 break;
 344                         }
 345                 }
 346 
 347                 add_post_vars(arr, &post_data, 1 TSRMLS_CC);
 348                 if (post_data.str.c) {
 349                         efree(post_data.str.c);
 350                 }
 351         }
 352 }
 353 #undef SAPI_POST_HANDLER_BUFSIZ
 354 
 355 SAPI_API SAPI_INPUT_FILTER_FUNC(php_default_input_filter)
 356 {
 357         /* TODO: check .ini setting here and apply user-defined input filter */
 358         if(new_val_len) *new_val_len = val_len;
 359         return 1;
 360 }
 361 
 362 SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
 363 {
 364         char *res = NULL, *var, *val, *separator = NULL;
 365         const char *c_var;
 366         zval *array_ptr;
 367         int free_buffer = 0;
 368         char *strtok_buf = NULL;
 369         long count = 0;
 370         
 371         switch (arg) {
 372                 case PARSE_POST:
 373                 case PARSE_GET:
 374                 case PARSE_COOKIE:
 375                         ALLOC_ZVAL(array_ptr);
 376                         array_init(array_ptr);
 377                         INIT_PZVAL(array_ptr);
 378                         switch (arg) {
 379                                 case PARSE_POST:
 380                                         if (PG(http_globals)[TRACK_VARS_POST]) {
 381                                                 zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_POST]);
 382                                         }
 383                                         PG(http_globals)[TRACK_VARS_POST] = array_ptr;
 384                                         break;
 385                                 case PARSE_GET:
 386                                         if (PG(http_globals)[TRACK_VARS_GET]) {
 387                                                 zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_GET]);
 388                                         }
 389                                         PG(http_globals)[TRACK_VARS_GET] = array_ptr;
 390                                         break;
 391                                 case PARSE_COOKIE:
 392                                         if (PG(http_globals)[TRACK_VARS_COOKIE]) {
 393                                                 zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_COOKIE]);
 394                                         }
 395                                         PG(http_globals)[TRACK_VARS_COOKIE] = array_ptr;
 396                                         break;
 397                         }
 398                         break;
 399                 default:
 400                         array_ptr = destArray;
 401                         break;
 402         }
 403 
 404         if (arg == PARSE_POST) {
 405                 sapi_handle_post(array_ptr TSRMLS_CC);
 406                 return;
 407         }
 408 
 409         if (arg == PARSE_GET) {         /* GET data */
 410                 c_var = SG(request_info).query_string;
 411                 if (c_var && *c_var) {
 412                         res = (char *) estrdup(c_var);
 413                         free_buffer = 1;
 414                 } else {
 415                         free_buffer = 0;
 416                 }
 417         } else if (arg == PARSE_COOKIE) {               /* Cookie data */
 418                 c_var = SG(request_info).cookie_data;
 419                 if (c_var && *c_var) {
 420                         res = (char *) estrdup(c_var);
 421                         free_buffer = 1;
 422                 } else {
 423                         free_buffer = 0;
 424                 }
 425         } else if (arg == PARSE_STRING) {               /* String data */
 426                 res = str;
 427                 free_buffer = 1;
 428         }
 429 
 430         if (!res) {
 431                 return;
 432         }
 433 
 434         switch (arg) {
 435                 case PARSE_GET:
 436                 case PARSE_STRING:
 437                         separator = (char *) estrdup(PG(arg_separator).input);
 438                         break;
 439                 case PARSE_COOKIE:
 440                         separator = ";\0";
 441                         break;
 442         }
 443         
 444         var = php_strtok_r(res, separator, &strtok_buf);
 445         
 446         while (var) {
 447                 val = strchr(var, '=');
 448 
 449                 if (arg == PARSE_COOKIE) {
 450                         /* Remove leading spaces from cookie names, needed for multi-cookie header where ; can be followed by a space */
 451                         while (isspace(*var)) {
 452                                 var++;
 453                         }
 454                         if (var == val || *var == '\0') {
 455                                 goto next_cookie;
 456                         }
 457                 }
 458 
 459                 if (++count > PG(max_input_vars)) {
 460                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Input variables exceeded %ld. To increase the limit change max_input_vars in php.ini.", PG(max_input_vars));
 461                         break;
 462                 }
 463 
 464                 if (val) { /* have a value */
 465                         int val_len;
 466                         unsigned int new_val_len;
 467 
 468                         *val++ = '\0';
 469                         php_url_decode(var, strlen(var));
 470                         val_len = php_url_decode(val, strlen(val));
 471                         val = estrndup(val, val_len);
 472                         if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) {
 473                                 php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
 474                         }
 475                         efree(val);
 476                 } else {
 477                         int val_len;
 478                         unsigned int new_val_len;
 479 
 480                         php_url_decode(var, strlen(var));
 481                         val_len = 0;
 482                         val = estrndup("", val_len);
 483                         if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) {
 484                                 php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
 485                         }
 486                         efree(val);
 487                 }
 488 next_cookie:
 489                 var = php_strtok_r(NULL, separator, &strtok_buf);
 490         }
 491 
 492         if (arg != PARSE_COOKIE) {
 493                 efree(separator);
 494         }
 495 
 496         if (free_buffer) {
 497                 efree(res);
 498         }
 499 }
 500 
 501 void _php_import_environment_variables(zval *array_ptr TSRMLS_DC)
 502 {
 503         char buf[128];
 504         char **env, *p, *t = buf;
 505         size_t alloc_size = sizeof(buf);
 506         unsigned long nlen; /* ptrdiff_t is not portable */
 507 
 508         for (env = environ; env != NULL && *env != NULL; env++) {
 509                 p = strchr(*env, '=');
 510                 if (!p) {                               /* malformed entry? */
 511                         continue;
 512                 }
 513                 nlen = p - *env;
 514                 if (nlen >= alloc_size) {
 515                         alloc_size = nlen + 64;
 516                         t = (t == buf ? emalloc(alloc_size): erealloc(t, alloc_size));
 517                 }
 518                 memcpy(t, *env, nlen);
 519                 t[nlen] = '\0';
 520                 php_register_variable(t, p + 1, array_ptr TSRMLS_CC);
 521         }
 522         if (t != buf && t != NULL) {
 523                 efree(t);
 524         }
 525 }
 526 
 527 zend_bool php_std_auto_global_callback(char *name, uint name_len TSRMLS_DC)
 528 {
 529         zend_printf("%s\n", name);
 530         return 0; /* don't rearm */
 531 }
 532 
 533 /* {{{ php_build_argv
 534  */
 535 static void php_build_argv(char *s, zval *track_vars_array TSRMLS_DC)
 536 {
 537         zval *arr, *argc, *tmp;
 538         int count = 0;
 539         char *ss, *space;
 540         
 541         if (!(SG(request_info).argc || track_vars_array)) {
 542                 return;
 543         }
 544         
 545         ALLOC_INIT_ZVAL(arr);
 546         array_init(arr);
 547 
 548         /* Prepare argv */
 549         if (SG(request_info).argc) { /* are we in cli sapi? */
 550                 int i;
 551                 for (i = 0; i < SG(request_info).argc; i++) {
 552                         ALLOC_ZVAL(tmp);
 553                         Z_TYPE_P(tmp) = IS_STRING;
 554                         Z_STRLEN_P(tmp) = strlen(SG(request_info).argv[i]);
 555                         Z_STRVAL_P(tmp) = estrndup(SG(request_info).argv[i], Z_STRLEN_P(tmp));
 556                         INIT_PZVAL(tmp);
 557                         if (zend_hash_next_index_insert(Z_ARRVAL_P(arr), &tmp, sizeof(zval *), NULL) == FAILURE) {
 558                                 if (Z_TYPE_P(tmp) == IS_STRING) {
 559                                         efree(Z_STRVAL_P(tmp));
 560                                 }
 561                         }
 562                 }
 563         } else  if (s && *s) {
 564                 ss = s;
 565                 while (ss) {
 566                         space = strchr(ss, '+');
 567                         if (space) {
 568                                 *space = '\0';
 569                         }
 570                         /* auto-type */
 571                         ALLOC_ZVAL(tmp);
 572                         Z_TYPE_P(tmp) = IS_STRING;
 573                         Z_STRLEN_P(tmp) = strlen(ss);
 574                         Z_STRVAL_P(tmp) = estrndup(ss, Z_STRLEN_P(tmp));
 575                         INIT_PZVAL(tmp);
 576                         count++;
 577                         if (zend_hash_next_index_insert(Z_ARRVAL_P(arr), &tmp, sizeof(zval *), NULL) == FAILURE) {
 578                                 if (Z_TYPE_P(tmp) == IS_STRING) {
 579                                         efree(Z_STRVAL_P(tmp));
 580                                 }
 581                         }
 582                         if (space) {
 583                                 *space = '+';
 584                                 ss = space + 1;
 585                         } else {
 586                                 ss = space;
 587                         }
 588                 }
 589         }
 590 
 591         /* prepare argc */
 592         ALLOC_INIT_ZVAL(argc);
 593         if (SG(request_info).argc) {
 594                 Z_LVAL_P(argc) = SG(request_info).argc;
 595         } else {
 596                 Z_LVAL_P(argc) = count;
 597         }
 598         Z_TYPE_P(argc) = IS_LONG;
 599 
 600         if (SG(request_info).argc) {
 601                 Z_ADDREF_P(arr);
 602                 Z_ADDREF_P(argc);
 603                 zend_hash_update(&EG(symbol_table), "argv", sizeof("argv"), &arr, sizeof(zval *), NULL);
 604                 zend_hash_update(&EG(symbol_table), "argc", sizeof("argc"), &argc, sizeof(zval *), NULL);
 605         } 
 606         if (track_vars_array) {
 607                 Z_ADDREF_P(arr);
 608                 Z_ADDREF_P(argc);
 609                 zend_hash_update(Z_ARRVAL_P(track_vars_array), "argv", sizeof("argv"), &arr, sizeof(zval *), NULL);
 610                 zend_hash_update(Z_ARRVAL_P(track_vars_array), "argc", sizeof("argc"), &argc, sizeof(zval *), NULL);
 611         }
 612         zval_ptr_dtor(&arr);
 613         zval_ptr_dtor(&argc);
 614 }
 615 /* }}} */
 616 
 617 /* {{{ php_register_server_variables
 618  */
 619 static inline void php_register_server_variables(TSRMLS_D)
 620 {
 621         zval *array_ptr = NULL;
 622 
 623         ALLOC_ZVAL(array_ptr);
 624         array_init(array_ptr);
 625         INIT_PZVAL(array_ptr);
 626         if (PG(http_globals)[TRACK_VARS_SERVER]) {
 627                 zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_SERVER]);
 628         }
 629         PG(http_globals)[TRACK_VARS_SERVER] = array_ptr;
 630 
 631         /* Server variables */
 632         if (sapi_module.register_server_variables) {
 633                 sapi_module.register_server_variables(array_ptr TSRMLS_CC);
 634         }
 635 
 636         /* PHP Authentication support */
 637         if (SG(request_info).auth_user) {
 638                 php_register_variable("PHP_AUTH_USER", SG(request_info).auth_user, array_ptr TSRMLS_CC);
 639         }
 640         if (SG(request_info).auth_password) {
 641                 php_register_variable("PHP_AUTH_PW", SG(request_info).auth_password, array_ptr TSRMLS_CC);
 642         }
 643         if (SG(request_info).auth_digest) {
 644                 php_register_variable("PHP_AUTH_DIGEST", SG(request_info).auth_digest, array_ptr TSRMLS_CC);
 645         }
 646         /* store request init time */
 647         {
 648                 zval request_time_float, request_time_long;
 649                 Z_TYPE(request_time_float) = IS_DOUBLE;
 650                 Z_DVAL(request_time_float) = sapi_get_request_time(TSRMLS_C);
 651                 php_register_variable_ex("REQUEST_TIME_FLOAT", &request_time_float, array_ptr TSRMLS_CC);
 652                 Z_TYPE(request_time_long) = IS_LONG;
 653                 Z_LVAL(request_time_long) = zend_dval_to_lval(Z_DVAL(request_time_float));
 654                 php_register_variable_ex("REQUEST_TIME", &request_time_long, array_ptr TSRMLS_CC);
 655         }
 656 
 657 }
 658 /* }}} */
 659 
 660 /* {{{ php_autoglobal_merge
 661  */
 662 static void php_autoglobal_merge(HashTable *dest, HashTable *src TSRMLS_DC)
 663 {
 664         zval **src_entry, **dest_entry;
 665         char *string_key;
 666         uint string_key_len;
 667         ulong num_key;
 668         HashPosition pos;
 669         int key_type;
 670         int globals_check = (dest == (&EG(symbol_table)));
 671 
 672         zend_hash_internal_pointer_reset_ex(src, &pos);
 673         while (zend_hash_get_current_data_ex(src, (void **)&src_entry, &pos) == SUCCESS) {
 674                 key_type = zend_hash_get_current_key_ex(src, &string_key, &string_key_len, &num_key, 0, &pos);
 675                 if (Z_TYPE_PP(src_entry) != IS_ARRAY
 676                         || (key_type == HASH_KEY_IS_STRING && zend_hash_find(dest, string_key, string_key_len, (void **) &dest_entry) != SUCCESS)
 677                         || (key_type == HASH_KEY_IS_LONG && zend_hash_index_find(dest, num_key, (void **)&dest_entry) != SUCCESS)
 678                         || Z_TYPE_PP(dest_entry) != IS_ARRAY
 679                         ) {
 680                         Z_ADDREF_PP(src_entry);
 681                         if (key_type == HASH_KEY_IS_STRING) {
 682                                 if (!globals_check || string_key_len != sizeof("GLOBALS") || memcmp(string_key, "GLOBALS", sizeof("GLOBALS") - 1)) {
 683                                         zend_hash_update(dest, string_key, string_key_len, src_entry, sizeof(zval *), NULL);
 684                                 } else {
 685                                         Z_DELREF_PP(src_entry);
 686                                 }
 687                         } else {
 688                                 zend_hash_index_update(dest, num_key, src_entry, sizeof(zval *), NULL);
 689                         }
 690                 } else {
 691                         SEPARATE_ZVAL(dest_entry);
 692                         php_autoglobal_merge(Z_ARRVAL_PP(dest_entry), Z_ARRVAL_PP(src_entry) TSRMLS_CC);
 693                 }
 694                 zend_hash_move_forward_ex(src, &pos);
 695         }
 696 }
 697 /* }}} */
 698 
 699 static zend_bool php_auto_globals_create_server(const char *name, uint name_len TSRMLS_DC);
 700 static zend_bool php_auto_globals_create_env(const char *name, uint name_len TSRMLS_DC);
 701 static zend_bool php_auto_globals_create_request(const char *name, uint name_len TSRMLS_DC);
 702 
 703 /* {{{ php_hash_environment
 704  */
 705 PHPAPI int php_hash_environment(TSRMLS_D)
 706 {
 707         memset(PG(http_globals), 0, sizeof(PG(http_globals)));
 708         zend_activate_auto_globals(TSRMLS_C);
 709         if (PG(register_argc_argv)) {
 710                 php_build_argv(SG(request_info).query_string, PG(http_globals)[TRACK_VARS_SERVER] TSRMLS_CC);
 711         }
 712         return SUCCESS;
 713 }
 714 /* }}} */
 715 
 716 static zend_bool php_auto_globals_create_get(const char *name, uint name_len TSRMLS_DC)
 717 {
 718         zval *vars;
 719 
 720         if (PG(variables_order) && (strchr(PG(variables_order),'G') || strchr(PG(variables_order),'g'))) {
 721                 sapi_module.treat_data(PARSE_GET, NULL, NULL TSRMLS_CC);
 722                 vars = PG(http_globals)[TRACK_VARS_GET];
 723         } else {
 724                 ALLOC_ZVAL(vars);
 725                 array_init(vars);
 726                 INIT_PZVAL(vars);
 727                 if (PG(http_globals)[TRACK_VARS_GET]) {
 728                         zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_GET]);
 729                 }
 730                 PG(http_globals)[TRACK_VARS_GET] = vars;
 731         }
 732 
 733         zend_hash_update(&EG(symbol_table), name, name_len + 1, &vars, sizeof(zval *), NULL);
 734         Z_ADDREF_P(vars);
 735         
 736         return 0; /* don't rearm */
 737 }
 738 
 739 static zend_bool php_auto_globals_create_post(const char *name, uint name_len TSRMLS_DC)
 740 {
 741         zval *vars;
 742 
 743         if (PG(variables_order) &&
 744                         (strchr(PG(variables_order),'P') || strchr(PG(variables_order),'p')) &&
 745                 SG(request_info).request_method &&
 746                 !strcasecmp(SG(request_info).request_method, "POST")) {
 747                 sapi_module.treat_data(PARSE_POST, NULL, NULL TSRMLS_CC);
 748                 vars = PG(http_globals)[TRACK_VARS_POST];
 749         } else {
 750                 ALLOC_ZVAL(vars);
 751                 array_init(vars);
 752                 INIT_PZVAL(vars);
 753                 if (PG(http_globals)[TRACK_VARS_POST]) {
 754                         zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_POST]);
 755                 }
 756                 PG(http_globals)[TRACK_VARS_POST] = vars;
 757         }
 758 
 759         zend_hash_update(&EG(symbol_table), name, name_len + 1, &vars, sizeof(zval *), NULL);
 760         Z_ADDREF_P(vars);
 761         
 762         return 0; /* don't rearm */
 763 }
 764 
 765 static zend_bool php_auto_globals_create_cookie(const char *name, uint name_len TSRMLS_DC)
 766 {
 767         zval *vars;
 768 
 769         if (PG(variables_order) && (strchr(PG(variables_order),'C') || strchr(PG(variables_order),'c'))) {
 770                 sapi_module.treat_data(PARSE_COOKIE, NULL, NULL TSRMLS_CC);
 771                 vars = PG(http_globals)[TRACK_VARS_COOKIE];
 772         } else {
 773                 ALLOC_ZVAL(vars);
 774                 array_init(vars);
 775                 INIT_PZVAL(vars);
 776                 if (PG(http_globals)[TRACK_VARS_COOKIE]) {
 777                         zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_COOKIE]);
 778                 }
 779                 PG(http_globals)[TRACK_VARS_COOKIE] = vars;
 780         }
 781 
 782         zend_hash_update(&EG(symbol_table), name, name_len + 1, &vars, sizeof(zval *), NULL);
 783         Z_ADDREF_P(vars);
 784         
 785         return 0; /* don't rearm */
 786 }
 787 
 788 static zend_bool php_auto_globals_create_files(const char *name, uint name_len TSRMLS_DC)
 789 {
 790         zval *vars;
 791 
 792         if (PG(http_globals)[TRACK_VARS_FILES]) {
 793                 vars = PG(http_globals)[TRACK_VARS_FILES];
 794         } else {
 795                 ALLOC_ZVAL(vars);
 796                 array_init(vars);
 797                 INIT_PZVAL(vars);
 798                 PG(http_globals)[TRACK_VARS_FILES] = vars;
 799         }
 800 
 801         zend_hash_update(&EG(symbol_table), name, name_len + 1, &vars, sizeof(zval *), NULL);
 802         Z_ADDREF_P(vars);
 803         
 804         return 0; /* don't rearm */
 805 }
 806 
 807 static zend_bool php_auto_globals_create_server(const char *name, uint name_len TSRMLS_DC)
 808 {
 809         if (PG(variables_order) && (strchr(PG(variables_order),'S') || strchr(PG(variables_order),'s'))) {
 810                 php_register_server_variables(TSRMLS_C);
 811 
 812                 if (PG(register_argc_argv)) {
 813                         if (SG(request_info).argc) {
 814                                 zval **argc, **argv;
 815         
 816                                 if (zend_hash_find(&EG(symbol_table), "argc", sizeof("argc"), (void**)&argc) == SUCCESS &&
 817                                         zend_hash_find(&EG(symbol_table), "argv", sizeof("argv"), (void**)&argv) == SUCCESS) {
 818                                         Z_ADDREF_PP(argc);
 819                                         Z_ADDREF_PP(argv);
 820                                         zend_hash_update(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]), "argv", sizeof("argv"), argv, sizeof(zval *), NULL);
 821                                         zend_hash_update(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]), "argc", sizeof("argc"), argc, sizeof(zval *), NULL);
 822                                 }
 823                         } else {
 824                                 php_build_argv(SG(request_info).query_string, PG(http_globals)[TRACK_VARS_SERVER] TSRMLS_CC);
 825                         }
 826                 }
 827         
 828         } else {
 829                 zval *server_vars=NULL;
 830                 ALLOC_ZVAL(server_vars);
 831                 array_init(server_vars);
 832                 INIT_PZVAL(server_vars);
 833                 if (PG(http_globals)[TRACK_VARS_SERVER]) {
 834                         zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_SERVER]);
 835                 }
 836                 PG(http_globals)[TRACK_VARS_SERVER] = server_vars;
 837         }
 838 
 839         zend_hash_update(&EG(symbol_table), name, name_len + 1, &PG(http_globals)[TRACK_VARS_SERVER], sizeof(zval *), NULL);
 840         Z_ADDREF_P(PG(http_globals)[TRACK_VARS_SERVER]);
 841         
 842         return 0; /* don't rearm */
 843 }
 844 
 845 static zend_bool php_auto_globals_create_env(const char *name, uint name_len TSRMLS_DC)
 846 {
 847         zval *env_vars = NULL;
 848         ALLOC_ZVAL(env_vars);
 849         array_init(env_vars);
 850         INIT_PZVAL(env_vars);
 851         if (PG(http_globals)[TRACK_VARS_ENV]) {
 852                 zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_ENV]);
 853         }
 854         PG(http_globals)[TRACK_VARS_ENV] = env_vars;
 855         
 856         if (PG(variables_order) && (strchr(PG(variables_order),'E') || strchr(PG(variables_order),'e'))) {
 857                 php_import_environment_variables(PG(http_globals)[TRACK_VARS_ENV] TSRMLS_CC);
 858         }
 859 
 860         zend_hash_update(&EG(symbol_table), name, name_len + 1, &PG(http_globals)[TRACK_VARS_ENV], sizeof(zval *), NULL);
 861         Z_ADDREF_P(PG(http_globals)[TRACK_VARS_ENV]);
 862 
 863         return 0; /* don't rearm */
 864 }
 865 
 866 static zend_bool php_auto_globals_create_request(const char *name, uint name_len TSRMLS_DC)
 867 {
 868         zval *form_variables;
 869         unsigned char _gpc_flags[3] = {0, 0, 0};
 870         char *p;
 871 
 872         ALLOC_ZVAL(form_variables);
 873         array_init(form_variables);
 874         INIT_PZVAL(form_variables);
 875 
 876         if (PG(request_order) != NULL) {
 877                 p = PG(request_order);
 878         } else {
 879                 p = PG(variables_order);
 880         }
 881 
 882         for (; p && *p; p++) {
 883                 switch (*p) {
 884                         case 'g':
 885                         case 'G':
 886                                 if (!_gpc_flags[0]) {
 887                                         php_autoglobal_merge(Z_ARRVAL_P(form_variables), Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_GET]) TSRMLS_CC);
 888                                         _gpc_flags[0] = 1;
 889                                 }
 890                                 break;
 891                         case 'p':
 892                         case 'P':
 893                                 if (!_gpc_flags[1]) {
 894                                         php_autoglobal_merge(Z_ARRVAL_P(form_variables), Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_POST]) TSRMLS_CC);
 895                                         _gpc_flags[1] = 1;
 896                                 }
 897                                 break;
 898                         case 'c':
 899                         case 'C':
 900                                 if (!_gpc_flags[2]) {
 901                                         php_autoglobal_merge(Z_ARRVAL_P(form_variables), Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_COOKIE]) TSRMLS_CC);
 902                                         _gpc_flags[2] = 1;
 903                                 }
 904                                 break;
 905                 }
 906         }
 907 
 908         zend_hash_update(&EG(symbol_table), name, name_len + 1, &form_variables, sizeof(zval *), NULL);
 909         return 0;
 910 }
 911 
 912 void php_startup_auto_globals(TSRMLS_D)
 913 {
 914         zend_register_auto_global(ZEND_STRL("_GET"), 0, php_auto_globals_create_get TSRMLS_CC);
 915         zend_register_auto_global(ZEND_STRL("_POST"), 0, php_auto_globals_create_post TSRMLS_CC);
 916         zend_register_auto_global(ZEND_STRL("_COOKIE"), 0, php_auto_globals_create_cookie TSRMLS_CC);
 917         zend_register_auto_global(ZEND_STRL("_SERVER"), PG(auto_globals_jit), php_auto_globals_create_server TSRMLS_CC);
 918         zend_register_auto_global(ZEND_STRL("_ENV"), PG(auto_globals_jit), php_auto_globals_create_env TSRMLS_CC);
 919         zend_register_auto_global(ZEND_STRL("_REQUEST"), PG(auto_globals_jit), php_auto_globals_create_request TSRMLS_CC);
 920         zend_register_auto_global(ZEND_STRL("_FILES"), 0, php_auto_globals_create_files TSRMLS_CC);
 921 }
 922 
 923 /*
 924  * Local variables:
 925  * tab-width: 4
 926  * c-basic-offset: 4
 927  * End:
 928  * vim600: sw=4 ts=4 fdm=marker
 929  * vim<600: sw=4 ts=4
 930  */

/* [<][>][^][v][top][bottom][index][help] */