Back to index

php5  5.3.10
php_variables.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca>                       |
00016    |          Zeev Suraski <zeev@zend.com>                                |
00017    +----------------------------------------------------------------------+
00018  */
00019 
00020 /* $Id: php_variables.c 323031 2012-02-02 17:51:44Z johannes $ */
00021 
00022 #include <stdio.h>
00023 #include "php.h"
00024 #include "ext/standard/php_standard.h"
00025 #include "ext/standard/credits.h"
00026 #include "php_variables.h"
00027 #include "php_globals.h"
00028 #include "php_content_types.h"
00029 #include "SAPI.h"
00030 #include "php_logos.h"
00031 #include "zend_globals.h"
00032 
00033 /* for systems that need to override reading of environment variables */
00034 void _php_import_environment_variables(zval *array_ptr TSRMLS_DC);
00035 PHPAPI void (*php_import_environment_variables)(zval *array_ptr TSRMLS_DC) = _php_import_environment_variables;
00036 
00037 PHPAPI void php_register_variable(char *var, char *strval, zval *track_vars_array TSRMLS_DC)
00038 {
00039        php_register_variable_safe(var, strval, strlen(strval), track_vars_array TSRMLS_CC);
00040 }
00041 
00042 /* binary-safe version */
00043 PHPAPI void php_register_variable_safe(char *var, char *strval, int str_len, zval *track_vars_array TSRMLS_DC)
00044 {
00045        zval new_entry;
00046        assert(strval != NULL);
00047        
00048        /* Prepare value */
00049        Z_STRLEN(new_entry) = str_len;
00050        if (PG(magic_quotes_gpc)) {
00051               Z_STRVAL(new_entry) = php_addslashes(strval, Z_STRLEN(new_entry), &Z_STRLEN(new_entry), 0 TSRMLS_CC);
00052        } else {
00053               Z_STRVAL(new_entry) = estrndup(strval, Z_STRLEN(new_entry));
00054        }
00055        Z_TYPE(new_entry) = IS_STRING;
00056 
00057        php_register_variable_ex(var, &new_entry, track_vars_array TSRMLS_CC);
00058 }
00059 
00060 PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars_array TSRMLS_DC)
00061 {
00062        char *p = NULL;
00063        char *ip;            /* index pointer */
00064        char *index, *escaped_index = NULL;
00065        char *var, *var_orig;
00066        int var_len, index_len;
00067        zval *gpc_element, **gpc_element_p;
00068        zend_bool is_array = 0;
00069        HashTable *symtable1 = NULL;
00070 
00071        assert(var_name != NULL);
00072 
00073        if (track_vars_array) {
00074               symtable1 = Z_ARRVAL_P(track_vars_array);
00075        } else if (PG(register_globals)) {
00076               if (!EG(active_symbol_table)) {
00077                      zend_rebuild_symbol_table(TSRMLS_C);
00078               }
00079               symtable1 = EG(active_symbol_table);
00080        }
00081        if (!symtable1) {
00082               /* Nothing to do */
00083               zval_dtor(val);
00084               return;
00085        }
00086 
00087        /*
00088         * Prepare variable name
00089         */
00090 
00091        var_orig = estrdup(var_name);
00092        var = var_orig;
00093        /* ignore leading spaces in the variable name */
00094        while (*var && *var==' ') {
00095               var++;
00096        }
00097 
00098        /* ensure that we don't have spaces or dots in the variable name (not binary safe) */
00099        for (p = var; *p; p++) {
00100               if (*p == ' ' || *p == '.') {
00101                      *p='_';
00102               } else if (*p == '[') {
00103                      is_array = 1;
00104                      ip = p;
00105                      *p = 0;
00106                      break;
00107               }
00108        }
00109        var_len = p - var;
00110 
00111        if (var_len==0) { /* empty variable name, or variable name with a space in it */
00112               zval_dtor(val);
00113               efree(var_orig);
00114               return;
00115        }
00116 
00117        /* GLOBALS hijack attempt, reject parameter */
00118        if (symtable1 == EG(active_symbol_table) &&
00119               var_len == sizeof("GLOBALS")-1 &&
00120               !memcmp(var, "GLOBALS", sizeof("GLOBALS")-1)) {
00121               zval_dtor(val);
00122               efree(var_orig);
00123               return;
00124        }
00125 
00126        index = var;
00127        index_len = var_len;
00128 
00129        if (is_array) {
00130               int nest_level = 0;
00131               while (1) {
00132                      char *index_s;
00133                      int new_idx_len = 0;
00134 
00135                      if(++nest_level > PG(max_input_nesting_level)) {
00136                             HashTable *ht;
00137                             /* too many levels of nesting */
00138 
00139                             if (track_vars_array) {
00140                                    ht = Z_ARRVAL_P(track_vars_array);
00141                                    zend_hash_del(ht, var, var_len + 1);
00142                             } else if (PG(register_globals)) {
00143                                    ht = EG(active_symbol_table);
00144                                    zend_hash_del(ht, var, var_len + 1);
00145                             }
00146 
00147                             zval_dtor(val);
00148 
00149                             /* do not output the error message to the screen,
00150                              this helps us to to avoid "information disclosure" */
00151                             if (!PG(display_errors)) {
00152                                    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));
00153                             }
00154                             efree(var_orig);
00155                             return;
00156                      }
00157 
00158                      ip++;
00159                      index_s = ip;
00160                      if (isspace(*ip)) {
00161                             ip++;
00162                      }
00163                      if (*ip==']') {
00164                             index_s = NULL;
00165                      } else {
00166                             ip = strchr(ip, ']');
00167                             if (!ip) {
00168                                    /* PHP variables cannot contain '[' in their names, so we replace the character with a '_' */
00169                                    *(index_s - 1) = '_';
00170 
00171                                    index_len = 0;
00172                                    if (index) {
00173                                           index_len = strlen(index);
00174                                    }
00175                                    goto plain_var;
00176                                    return;
00177                             }
00178                             *ip = 0;
00179                             new_idx_len = strlen(index_s);     
00180                      }
00181 
00182                      if (!index) {
00183                             MAKE_STD_ZVAL(gpc_element);
00184                             array_init(gpc_element);
00185                             if (zend_hash_next_index_insert(symtable1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p) == FAILURE) {
00186                                    zval_ptr_dtor(&gpc_element);
00187                                    zval_dtor(val);
00188                                    efree(var_orig);
00189                                    return;
00190                             }
00191                      } else {
00192                             if (PG(magic_quotes_gpc)) {
00193                                    escaped_index = php_addslashes(index, index_len, &index_len, 0 TSRMLS_CC);
00194                             } else {
00195                                    escaped_index = index;
00196                             }
00197                             if (zend_symtable_find(symtable1, escaped_index, index_len + 1, (void **) &gpc_element_p) == FAILURE
00198                                    || Z_TYPE_PP(gpc_element_p) != IS_ARRAY) {
00199                                    if (zend_hash_num_elements(symtable1) <= PG(max_input_vars)) {
00200                                           if (zend_hash_num_elements(symtable1) == PG(max_input_vars)) {
00201                                                  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));
00202                                           }
00203                                           MAKE_STD_ZVAL(gpc_element);
00204                                           array_init(gpc_element);
00205                                           zend_symtable_update(symtable1, escaped_index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
00206                                    } else {
00207                                           if (index != escaped_index) {
00208                                                  efree(escaped_index);
00209                                           }
00210                                           zval_dtor(val);
00211                                           efree(var_orig);
00212                                           return;
00213                                    }
00214                             }
00215                             if (index != escaped_index) {
00216                                    efree(escaped_index);
00217                             }
00218                      }
00219                      symtable1 = Z_ARRVAL_PP(gpc_element_p);
00220                      /* ip pointed to the '[' character, now obtain the key */
00221                      index = index_s;
00222                      index_len = new_idx_len;
00223 
00224                      ip++;
00225                      if (*ip == '[') {
00226                             is_array = 1;
00227                             *ip = 0;
00228                      } else {
00229                             goto plain_var;
00230                      }
00231               }
00232        } else {
00233 plain_var:
00234               MAKE_STD_ZVAL(gpc_element);
00235               gpc_element->value = val->value;
00236               Z_TYPE_P(gpc_element) = Z_TYPE_P(val);
00237               if (!index) {
00238                      if (zend_hash_next_index_insert(symtable1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p) == FAILURE) {
00239                             zval_ptr_dtor(&gpc_element);
00240                      }
00241               } else {
00242                      if (PG(magic_quotes_gpc)) { 
00243                             escaped_index = php_addslashes(index, index_len, &index_len, 0 TSRMLS_CC);
00244                      } else {
00245                             escaped_index = index;
00246                      }
00247                      /* 
00248                       * According to rfc2965, more specific paths are listed above the less specific ones.
00249                       * If we encounter a duplicate cookie name, we should skip it, since it is not possible
00250                       * to have the same (plain text) cookie name for the same path and we should not overwrite
00251                       * more specific cookies with the less specific ones.
00252                       */
00253                      if (PG(http_globals)[TRACK_VARS_COOKIE] &&
00254                             symtable1 == Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_COOKIE]) &&
00255                             zend_symtable_exists(symtable1, escaped_index, index_len + 1)) {
00256                             zval_ptr_dtor(&gpc_element);
00257                      } else {
00258                             if (zend_hash_num_elements(symtable1) <= PG(max_input_vars)) {
00259                                    if (zend_hash_num_elements(symtable1) == PG(max_input_vars)) {
00260                                           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));
00261                                    }
00262                                    zend_symtable_update(symtable1, escaped_index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
00263                             } else {
00264                                    zval_ptr_dtor(&gpc_element);
00265                             }
00266                      }
00267                      if (escaped_index != index) {
00268                             efree(escaped_index);
00269                      }
00270               }
00271        }
00272        efree(var_orig);
00273 }
00274 
00275 SAPI_API SAPI_POST_HANDLER_FUNC(php_std_post_handler)
00276 {
00277        char *var, *val, *e, *s, *p;
00278        zval *array_ptr = (zval *) arg;
00279 
00280        if (SG(request_info).post_data == NULL) {
00281               return;
00282        }      
00283 
00284        s = SG(request_info).post_data;
00285        e = s + SG(request_info).post_data_length;
00286 
00287        while (s < e && (p = memchr(s, '&', (e - s)))) {
00288 last_value:
00289               if ((val = memchr(s, '=', (p - s)))) { /* have a value */
00290                      unsigned int val_len, new_val_len;
00291 
00292                      var = s;
00293 
00294                      php_url_decode(var, (val - s));
00295                      val++;
00296                      val_len = php_url_decode(val, (p - val));
00297                      val = estrndup(val, val_len);
00298                      if (sapi_module.input_filter(PARSE_POST, var, &val, val_len, &new_val_len TSRMLS_CC)) {
00299                             php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
00300                      }
00301                      efree(val);
00302               }
00303               s = p + 1;
00304        }
00305        if (s < e) {
00306               p = e;
00307               goto last_value;
00308        }
00309 }
00310 
00311 SAPI_API SAPI_INPUT_FILTER_FUNC(php_default_input_filter)
00312 {
00313        /* TODO: check .ini setting here and apply user-defined input filter */
00314        if(new_val_len) *new_val_len = val_len;
00315        return 1;
00316 }
00317 
00318 SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
00319 {
00320        char *res = NULL, *var, *val, *separator = NULL;
00321        const char *c_var;
00322        zval *array_ptr;
00323        int free_buffer = 0;
00324        char *strtok_buf = NULL;
00325        
00326        switch (arg) {
00327               case PARSE_POST:
00328               case PARSE_GET:
00329               case PARSE_COOKIE:
00330                      ALLOC_ZVAL(array_ptr);
00331                      array_init(array_ptr);
00332                      INIT_PZVAL(array_ptr);
00333                      switch (arg) {
00334                             case PARSE_POST:
00335                                    if (PG(http_globals)[TRACK_VARS_POST]) {
00336                                           zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_POST]);
00337                                    }
00338                                    PG(http_globals)[TRACK_VARS_POST] = array_ptr;
00339                                    break;
00340                             case PARSE_GET:
00341                                    if (PG(http_globals)[TRACK_VARS_GET]) {
00342                                           zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_GET]);
00343                                    }
00344                                    PG(http_globals)[TRACK_VARS_GET] = array_ptr;
00345                                    break;
00346                             case PARSE_COOKIE:
00347                                    if (PG(http_globals)[TRACK_VARS_COOKIE]) {
00348                                           zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_COOKIE]);
00349                                    }
00350                                    PG(http_globals)[TRACK_VARS_COOKIE] = array_ptr;
00351                                    break;
00352                      }
00353                      break;
00354               default:
00355                      array_ptr = destArray;
00356                      break;
00357        }
00358 
00359        if (arg == PARSE_POST) {
00360               sapi_handle_post(array_ptr TSRMLS_CC);
00361               return;
00362        }
00363 
00364        if (arg == PARSE_GET) {            /* GET data */
00365               c_var = SG(request_info).query_string;
00366               if (c_var && *c_var) {
00367                      res = (char *) estrdup(c_var);
00368                      free_buffer = 1;
00369               } else {
00370                      free_buffer = 0;
00371               }
00372        } else if (arg == PARSE_COOKIE) {         /* Cookie data */
00373               c_var = SG(request_info).cookie_data;
00374               if (c_var && *c_var) {
00375                      res = (char *) estrdup(c_var);
00376                      free_buffer = 1;
00377               } else {
00378                      free_buffer = 0;
00379               }
00380        } else if (arg == PARSE_STRING) {         /* String data */
00381               res = str;
00382               free_buffer = 1;
00383        }
00384 
00385        if (!res) {
00386               return;
00387        }
00388 
00389        switch (arg) {
00390               case PARSE_GET:
00391               case PARSE_STRING:
00392                      separator = (char *) estrdup(PG(arg_separator).input);
00393                      break;
00394               case PARSE_COOKIE:
00395                      separator = ";\0";
00396                      break;
00397        }
00398        
00399        var = php_strtok_r(res, separator, &strtok_buf);
00400        
00401        while (var) {
00402               val = strchr(var, '=');
00403 
00404               if (arg == PARSE_COOKIE) {
00405                      /* Remove leading spaces from cookie names, needed for multi-cookie header where ; can be followed by a space */
00406                      while (isspace(*var)) {
00407                             var++;
00408                      }
00409                      if (var == val || *var == '\0') {
00410                             goto next_cookie;
00411                      }
00412               }
00413 
00414               if (val) { /* have a value */
00415                      int val_len;
00416                      unsigned int new_val_len;
00417 
00418                      *val++ = '\0';
00419                      php_url_decode(var, strlen(var));
00420                      val_len = php_url_decode(val, strlen(val));
00421                      val = estrndup(val, val_len);
00422                      if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) {
00423                             php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
00424                      }
00425                      efree(val);
00426               } else {
00427                      int val_len;
00428                      unsigned int new_val_len;
00429 
00430                      php_url_decode(var, strlen(var));
00431                      val_len = 0;
00432                      val = estrndup("", val_len);
00433                      if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len TSRMLS_CC)) {
00434                             php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
00435                      }
00436                      efree(val);
00437               }
00438 next_cookie:
00439               var = php_strtok_r(NULL, separator, &strtok_buf);
00440        }
00441 
00442        if (arg != PARSE_COOKIE) {
00443               efree(separator);
00444        }
00445 
00446        if (free_buffer) {
00447               efree(res);
00448        }
00449 }
00450 
00451 void _php_import_environment_variables(zval *array_ptr TSRMLS_DC)
00452 {
00453        char buf[128];
00454        char **env, *p, *t = buf;
00455        size_t alloc_size = sizeof(buf);
00456        unsigned long nlen; /* ptrdiff_t is not portable */
00457 
00458        /* turn off magic_quotes while importing environment variables */
00459        int magic_quotes_gpc = PG(magic_quotes_gpc);
00460        PG(magic_quotes_gpc) = 0;
00461 
00462        for (env = environ; env != NULL && *env != NULL; env++) {
00463               p = strchr(*env, '=');
00464               if (!p) {                          /* malformed entry? */
00465                      continue;
00466               }
00467               nlen = p - *env;
00468               if (nlen >= alloc_size) {
00469                      alloc_size = nlen + 64;
00470                      t = (t == buf ? emalloc(alloc_size): erealloc(t, alloc_size));
00471               }
00472               memcpy(t, *env, nlen);
00473               t[nlen] = '\0';
00474               php_register_variable(t, p + 1, array_ptr TSRMLS_CC);
00475        }
00476        if (t != buf && t != NULL) {
00477               efree(t);
00478        }
00479        PG(magic_quotes_gpc) = magic_quotes_gpc;
00480 }
00481 
00482 zend_bool php_std_auto_global_callback(char *name, uint name_len TSRMLS_DC)
00483 {
00484        zend_printf("%s\n", name);
00485        return 0; /* don't rearm */
00486 }
00487 
00488 /* {{{ php_build_argv
00489  */
00490 static void php_build_argv(char *s, zval *track_vars_array TSRMLS_DC)
00491 {
00492        zval *arr, *argc, *tmp;
00493        int count = 0;
00494        char *ss, *space;
00495        
00496        if (!(PG(register_globals) || SG(request_info).argc || track_vars_array)) {
00497               return;
00498        }
00499        
00500        ALLOC_INIT_ZVAL(arr);
00501        array_init(arr);
00502 
00503        /* Prepare argv */
00504        if (SG(request_info).argc) { /* are we in cli sapi? */
00505               int i;
00506               for (i = 0; i < SG(request_info).argc; i++) {
00507                      ALLOC_ZVAL(tmp);
00508                      Z_TYPE_P(tmp) = IS_STRING;
00509                      Z_STRLEN_P(tmp) = strlen(SG(request_info).argv[i]);
00510                      Z_STRVAL_P(tmp) = estrndup(SG(request_info).argv[i], Z_STRLEN_P(tmp));
00511                      INIT_PZVAL(tmp);
00512                      if (zend_hash_next_index_insert(Z_ARRVAL_P(arr), &tmp, sizeof(zval *), NULL) == FAILURE) {
00513                             if (Z_TYPE_P(tmp) == IS_STRING) {
00514                                    efree(Z_STRVAL_P(tmp));
00515                             }
00516                      }
00517               }
00518        } else        if (s && *s) {
00519               ss = s;
00520               while (ss) {
00521                      space = strchr(ss, '+');
00522                      if (space) {
00523                             *space = '\0';
00524                      }
00525                      /* auto-type */
00526                      ALLOC_ZVAL(tmp);
00527                      Z_TYPE_P(tmp) = IS_STRING;
00528                      Z_STRLEN_P(tmp) = strlen(ss);
00529                      Z_STRVAL_P(tmp) = estrndup(ss, Z_STRLEN_P(tmp));
00530                      INIT_PZVAL(tmp);
00531                      count++;
00532                      if (zend_hash_next_index_insert(Z_ARRVAL_P(arr), &tmp, sizeof(zval *), NULL) == FAILURE) {
00533                             if (Z_TYPE_P(tmp) == IS_STRING) {
00534                                    efree(Z_STRVAL_P(tmp));
00535                             }
00536                      }
00537                      if (space) {
00538                             *space = '+';
00539                             ss = space + 1;
00540                      } else {
00541                             ss = space;
00542                      }
00543               }
00544        }
00545 
00546        /* prepare argc */
00547        ALLOC_INIT_ZVAL(argc);
00548        if (SG(request_info).argc) {
00549               Z_LVAL_P(argc) = SG(request_info).argc;
00550        } else {
00551               Z_LVAL_P(argc) = count;
00552        }
00553        Z_TYPE_P(argc) = IS_LONG;
00554 
00555        if (PG(register_globals) || SG(request_info).argc) {
00556               Z_ADDREF_P(arr);
00557               Z_ADDREF_P(argc);
00558               zend_hash_update(&EG(symbol_table), "argv", sizeof("argv"), &arr, sizeof(zval *), NULL);
00559               zend_hash_add(&EG(symbol_table), "argc", sizeof("argc"), &argc, sizeof(zval *), NULL);
00560        } 
00561        if (track_vars_array) {
00562               Z_ADDREF_P(arr);
00563               Z_ADDREF_P(argc);
00564               zend_hash_update(Z_ARRVAL_P(track_vars_array), "argv", sizeof("argv"), &arr, sizeof(zval *), NULL);
00565               zend_hash_update(Z_ARRVAL_P(track_vars_array), "argc", sizeof("argc"), &argc, sizeof(zval *), NULL);
00566        }
00567        zval_ptr_dtor(&arr);
00568        zval_ptr_dtor(&argc);
00569 }
00570 /* }}} */
00571 
00572 /* {{{ php_handle_special_queries
00573  */
00574 PHPAPI int php_handle_special_queries(TSRMLS_D)
00575 {
00576        if (PG(expose_php) && SG(request_info).query_string && SG(request_info).query_string[0] == '=') {
00577               if (php_info_logos(SG(request_info).query_string + 1 TSRMLS_CC)) {
00578                      return 1;
00579               } else if (!strcmp(SG(request_info).query_string + 1, PHP_CREDITS_GUID)) {
00580                      php_print_credits(PHP_CREDITS_ALL TSRMLS_CC);
00581                      return 1;
00582               }
00583        }
00584        return 0;
00585 }
00586 /* }}} */
00587 
00588 /* {{{ php_register_server_variables
00589  */
00590 static inline void php_register_server_variables(TSRMLS_D)
00591 {
00592        zval *array_ptr = NULL;
00593        /* turn off magic_quotes while importing server variables */
00594        int magic_quotes_gpc = PG(magic_quotes_gpc);
00595 
00596        ALLOC_ZVAL(array_ptr);
00597        array_init(array_ptr);
00598        INIT_PZVAL(array_ptr);
00599        if (PG(http_globals)[TRACK_VARS_SERVER]) {
00600               zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_SERVER]);
00601        }
00602        PG(http_globals)[TRACK_VARS_SERVER] = array_ptr;
00603        PG(magic_quotes_gpc) = 0;
00604 
00605        /* Server variables */
00606        if (sapi_module.register_server_variables) {
00607               sapi_module.register_server_variables(array_ptr TSRMLS_CC);
00608        }
00609 
00610        /* PHP Authentication support */
00611        if (SG(request_info).auth_user) {
00612               php_register_variable("PHP_AUTH_USER", SG(request_info).auth_user, array_ptr TSRMLS_CC);
00613        }
00614        if (SG(request_info).auth_password) {
00615               php_register_variable("PHP_AUTH_PW", SG(request_info).auth_password, array_ptr TSRMLS_CC);
00616        }
00617        if (SG(request_info).auth_digest) {
00618               php_register_variable("PHP_AUTH_DIGEST", SG(request_info).auth_digest, array_ptr TSRMLS_CC);
00619        }
00620        /* store request init time */
00621        {
00622               zval new_entry;
00623               Z_TYPE(new_entry) = IS_LONG;
00624               Z_LVAL(new_entry) = sapi_get_request_time(TSRMLS_C);
00625               php_register_variable_ex("REQUEST_TIME", &new_entry, array_ptr TSRMLS_CC);
00626        }
00627 
00628        PG(magic_quotes_gpc) = magic_quotes_gpc;
00629 }
00630 /* }}} */
00631 
00632 /* {{{ php_autoglobal_merge
00633  */
00634 static void php_autoglobal_merge(HashTable *dest, HashTable *src TSRMLS_DC)
00635 {
00636        zval **src_entry, **dest_entry;
00637        char *string_key;
00638        uint string_key_len;
00639        ulong num_key;
00640        HashPosition pos;
00641        int key_type;
00642        int globals_check = (PG(register_globals) && (dest == (&EG(symbol_table))));
00643 
00644        zend_hash_internal_pointer_reset_ex(src, &pos);
00645        while (zend_hash_get_current_data_ex(src, (void **)&src_entry, &pos) == SUCCESS) {
00646               key_type = zend_hash_get_current_key_ex(src, &string_key, &string_key_len, &num_key, 0, &pos);
00647               if (Z_TYPE_PP(src_entry) != IS_ARRAY
00648                      || (key_type == HASH_KEY_IS_STRING && zend_hash_find(dest, string_key, string_key_len, (void **) &dest_entry) != SUCCESS)
00649                      || (key_type == HASH_KEY_IS_LONG && zend_hash_index_find(dest, num_key, (void **)&dest_entry) != SUCCESS)
00650                      || Z_TYPE_PP(dest_entry) != IS_ARRAY
00651         ) {
00652                      Z_ADDREF_PP(src_entry);
00653                      if (key_type == HASH_KEY_IS_STRING) {
00654                             /* if register_globals is on and working with main symbol table, prevent overwriting of GLOBALS */
00655                             if (!globals_check || string_key_len != sizeof("GLOBALS") || memcmp(string_key, "GLOBALS", sizeof("GLOBALS") - 1)) {
00656                                    zend_hash_update(dest, string_key, string_key_len, src_entry, sizeof(zval *), NULL);
00657                             } else {
00658                                    Z_DELREF_PP(src_entry);
00659                             }
00660                      } else {
00661                             zend_hash_index_update(dest, num_key, src_entry, sizeof(zval *), NULL);
00662                      }
00663               } else {
00664                      SEPARATE_ZVAL(dest_entry);
00665                      php_autoglobal_merge(Z_ARRVAL_PP(dest_entry), Z_ARRVAL_PP(src_entry) TSRMLS_CC);
00666               }
00667               zend_hash_move_forward_ex(src, &pos);
00668        }
00669 }
00670 /* }}} */
00671 
00672 static zend_bool php_auto_globals_create_server(char *name, uint name_len TSRMLS_DC);
00673 static zend_bool php_auto_globals_create_env(char *name, uint name_len TSRMLS_DC);
00674 static zend_bool php_auto_globals_create_request(char *name, uint name_len TSRMLS_DC);
00675 
00676 /* {{{ php_hash_environment
00677  */
00678 int php_hash_environment(TSRMLS_D)
00679 {
00680        char *p;
00681        unsigned char _gpc_flags[5] = {0, 0, 0, 0, 0};
00682        zend_bool jit_initialization = (PG(auto_globals_jit) && !PG(register_globals) && !PG(register_long_arrays));
00683        struct auto_global_record {
00684               char *name;
00685               uint name_len;
00686               char *long_name;
00687               uint long_name_len;
00688               zend_bool jit_initialization;
00689        } auto_global_records[] = {
00690               { "_POST", sizeof("_POST"), "HTTP_POST_VARS", sizeof("HTTP_POST_VARS"), 0 },
00691               { "_GET", sizeof("_GET"), "HTTP_GET_VARS", sizeof("HTTP_GET_VARS"), 0 },
00692               { "_COOKIE", sizeof("_COOKIE"), "HTTP_COOKIE_VARS", sizeof("HTTP_COOKIE_VARS"), 0 },
00693               { "_SERVER", sizeof("_SERVER"), "HTTP_SERVER_VARS", sizeof("HTTP_SERVER_VARS"), 1 },
00694               { "_ENV", sizeof("_ENV"), "HTTP_ENV_VARS", sizeof("HTTP_ENV_VARS"), 1 },
00695               { "_FILES", sizeof("_FILES"), "HTTP_POST_FILES", sizeof("HTTP_POST_FILES"), 0 },
00696        };
00697        size_t num_track_vars = sizeof(auto_global_records)/sizeof(struct auto_global_record);
00698        size_t i;
00699 
00700        /* jit_initialization = 0; */
00701        for (i=0; i<num_track_vars; i++) {
00702               PG(http_globals)[i] = NULL;
00703        }
00704 
00705        for (p=PG(variables_order); p && *p; p++) {
00706               switch(*p) {
00707                      case 'p':
00708                      case 'P':
00709                             if (!_gpc_flags[0] && !SG(headers_sent) && SG(request_info).request_method && !strcasecmp(SG(request_info).request_method, "POST")) {
00710                                    sapi_module.treat_data(PARSE_POST, NULL, NULL TSRMLS_CC);      /* POST Data */
00711                                    _gpc_flags[0] = 1;
00712                                    if (PG(register_globals)) {
00713                                           php_autoglobal_merge(&EG(symbol_table), Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_POST]) TSRMLS_CC);
00714                                    }
00715                             }
00716                             break;
00717                      case 'c':
00718                      case 'C':
00719                             if (!_gpc_flags[1]) {
00720                                    sapi_module.treat_data(PARSE_COOKIE, NULL, NULL TSRMLS_CC);    /* Cookie Data */
00721                                    _gpc_flags[1] = 1;
00722                                    if (PG(register_globals)) {
00723                                           php_autoglobal_merge(&EG(symbol_table), Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_COOKIE]) TSRMLS_CC);
00724                                    }
00725                             }
00726                             break;
00727                      case 'g':
00728                      case 'G':
00729                             if (!_gpc_flags[2]) {
00730                                    sapi_module.treat_data(PARSE_GET, NULL, NULL TSRMLS_CC);       /* GET Data */
00731                                    _gpc_flags[2] = 1;
00732                                    if (PG(register_globals)) {
00733                                           php_autoglobal_merge(&EG(symbol_table), Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_GET]) TSRMLS_CC);
00734                                    }
00735                             }
00736                             break;
00737                      case 'e':
00738                      case 'E':
00739                             if (!jit_initialization && !_gpc_flags[3]) {
00740                                    zend_auto_global_disable_jit("_ENV", sizeof("_ENV")-1 TSRMLS_CC);
00741                                    php_auto_globals_create_env("_ENV", sizeof("_ENV")-1 TSRMLS_CC);
00742                                    _gpc_flags[3] = 1;
00743                                    if (PG(register_globals)) {
00744                                           php_autoglobal_merge(&EG(symbol_table), Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_ENV]) TSRMLS_CC);
00745                                    }
00746                             }
00747                             break;
00748                      case 's':
00749                      case 'S':
00750                             if (!jit_initialization && !_gpc_flags[4]) {
00751                                    zend_auto_global_disable_jit("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC);
00752                                    php_register_server_variables(TSRMLS_C);
00753                                    _gpc_flags[4] = 1;
00754                                    if (PG(register_globals)) {
00755                                           php_autoglobal_merge(&EG(symbol_table), Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]) TSRMLS_CC);
00756                                    }
00757                             }
00758                             break;
00759               }
00760        }
00761 
00762        /* argv/argc support */
00763        if (PG(register_argc_argv)) {
00764               php_build_argv(SG(request_info).query_string, PG(http_globals)[TRACK_VARS_SERVER] TSRMLS_CC);
00765        }
00766 
00767        for (i=0; i<num_track_vars; i++) {
00768               if (jit_initialization && auto_global_records[i].jit_initialization) {
00769                      continue;
00770               }
00771               if (!PG(http_globals)[i]) {
00772                      ALLOC_ZVAL(PG(http_globals)[i]);
00773                      array_init(PG(http_globals)[i]);
00774                      INIT_PZVAL(PG(http_globals)[i]);
00775               }
00776 
00777               Z_ADDREF_P(PG(http_globals)[i]);
00778               zend_hash_update(&EG(symbol_table), auto_global_records[i].name, auto_global_records[i].name_len, &PG(http_globals)[i], sizeof(zval *), NULL);
00779               if (PG(register_long_arrays)) {
00780                      zend_hash_update(&EG(symbol_table), auto_global_records[i].long_name, auto_global_records[i].long_name_len, &PG(http_globals)[i], sizeof(zval *), NULL);
00781                      Z_ADDREF_P(PG(http_globals)[i]);
00782               }
00783        }
00784 
00785        /* Create _REQUEST */
00786        if (!jit_initialization) {
00787               zend_auto_global_disable_jit("_REQUEST", sizeof("_REQUEST")-1 TSRMLS_CC);
00788               php_auto_globals_create_request("_REQUEST", sizeof("_REQUEST")-1 TSRMLS_CC);
00789        }
00790 
00791        return SUCCESS;
00792 }
00793 /* }}} */
00794 
00795 static zend_bool php_auto_globals_create_server(char *name, uint name_len TSRMLS_DC)
00796 {
00797        if (PG(variables_order) && (strchr(PG(variables_order),'S') || strchr(PG(variables_order),'s'))) {
00798               php_register_server_variables(TSRMLS_C);
00799 
00800               if (PG(register_argc_argv)) {
00801                      if (SG(request_info).argc) {
00802                             zval **argc, **argv;
00803        
00804                             if (zend_hash_find(&EG(symbol_table), "argc", sizeof("argc"), (void**)&argc) == SUCCESS &&
00805                                 zend_hash_find(&EG(symbol_table), "argv", sizeof("argv"), (void**)&argv) == SUCCESS) {
00806                                    Z_ADDREF_PP(argc);
00807                                    Z_ADDREF_PP(argv);
00808                                    zend_hash_update(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]), "argv", sizeof("argv"), argv, sizeof(zval *), NULL);
00809                                    zend_hash_update(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]), "argc", sizeof("argc"), argc, sizeof(zval *), NULL);
00810                             }
00811                      } else {
00812                             php_build_argv(SG(request_info).query_string, PG(http_globals)[TRACK_VARS_SERVER] TSRMLS_CC);
00813                      }
00814               }
00815        
00816        } else {
00817               zval *server_vars=NULL;
00818               ALLOC_ZVAL(server_vars);
00819               array_init(server_vars);
00820               INIT_PZVAL(server_vars);
00821               if (PG(http_globals)[TRACK_VARS_SERVER]) {
00822                      zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_SERVER]);
00823               }
00824               PG(http_globals)[TRACK_VARS_SERVER] = server_vars;
00825        }
00826 
00827        zend_hash_update(&EG(symbol_table), name, name_len + 1, &PG(http_globals)[TRACK_VARS_SERVER], sizeof(zval *), NULL);
00828        Z_ADDREF_P(PG(http_globals)[TRACK_VARS_SERVER]);
00829 
00830        if (PG(register_long_arrays)) {
00831               zend_hash_update(&EG(symbol_table), "HTTP_SERVER_VARS", sizeof("HTTP_SERVER_VARS"), &PG(http_globals)[TRACK_VARS_SERVER], sizeof(zval *), NULL);
00832               Z_ADDREF_P(PG(http_globals)[TRACK_VARS_SERVER]);
00833        }
00834        
00835        return 0; /* don't rearm */
00836 }
00837 
00838 static zend_bool php_auto_globals_create_env(char *name, uint name_len TSRMLS_DC)
00839 {
00840        zval *env_vars = NULL;
00841        ALLOC_ZVAL(env_vars);
00842        array_init(env_vars);
00843        INIT_PZVAL(env_vars);
00844        if (PG(http_globals)[TRACK_VARS_ENV]) {
00845               zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_ENV]);
00846        }
00847        PG(http_globals)[TRACK_VARS_ENV] = env_vars;
00848        
00849        if (PG(variables_order) && (strchr(PG(variables_order),'E') || strchr(PG(variables_order),'e'))) {
00850               php_import_environment_variables(PG(http_globals)[TRACK_VARS_ENV] TSRMLS_CC);
00851        }
00852 
00853        zend_hash_update(&EG(symbol_table), name, name_len + 1, &PG(http_globals)[TRACK_VARS_ENV], sizeof(zval *), NULL);
00854        Z_ADDREF_P(PG(http_globals)[TRACK_VARS_ENV]);
00855 
00856        if (PG(register_long_arrays)) {
00857               zend_hash_update(&EG(symbol_table), "HTTP_ENV_VARS", sizeof("HTTP_ENV_VARS"), &PG(http_globals)[TRACK_VARS_ENV], sizeof(zval *), NULL);
00858               Z_ADDREF_P(PG(http_globals)[TRACK_VARS_ENV]);
00859        }
00860 
00861        return 0; /* don't rearm */
00862 }
00863 
00864 static zend_bool php_auto_globals_create_request(char *name, uint name_len TSRMLS_DC)
00865 {
00866        zval *form_variables;
00867        unsigned char _gpc_flags[3] = {0, 0, 0};
00868        char *p;
00869 
00870        ALLOC_ZVAL(form_variables);
00871        array_init(form_variables);
00872        INIT_PZVAL(form_variables);
00873 
00874        if(PG(request_order) != NULL) {
00875               p = PG(request_order);
00876        } else {
00877               p = PG(variables_order);
00878        }
00879 
00880        for (; p && *p; p++) {
00881               switch (*p) {
00882                      case 'g':
00883                      case 'G':
00884                             if (!_gpc_flags[0]) {
00885                                    php_autoglobal_merge(Z_ARRVAL_P(form_variables), Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_GET]) TSRMLS_CC);
00886                                    _gpc_flags[0] = 1;
00887                             }
00888                             break;
00889                      case 'p':
00890                      case 'P':
00891                             if (!_gpc_flags[1]) {
00892                                    php_autoglobal_merge(Z_ARRVAL_P(form_variables), Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_POST]) TSRMLS_CC);
00893                                    _gpc_flags[1] = 1;
00894                             }
00895                             break;
00896                      case 'c':
00897                      case 'C':
00898                             if (!_gpc_flags[2]) {
00899                                    php_autoglobal_merge(Z_ARRVAL_P(form_variables), Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_COOKIE]) TSRMLS_CC);
00900                                    _gpc_flags[2] = 1;
00901                             }
00902                             break;
00903               }
00904        }
00905 
00906        zend_hash_update(&EG(symbol_table), "_REQUEST", sizeof("_REQUEST"), &form_variables, sizeof(zval *), NULL);
00907        return 0;
00908 }
00909 
00910 void php_startup_auto_globals(TSRMLS_D)
00911 {
00912        zend_register_auto_global("_GET", sizeof("_GET")-1, NULL TSRMLS_CC);
00913        zend_register_auto_global("_POST", sizeof("_POST")-1, NULL TSRMLS_CC);
00914        zend_register_auto_global("_COOKIE", sizeof("_COOKIE")-1, NULL TSRMLS_CC);
00915        zend_register_auto_global("_SERVER", sizeof("_SERVER")-1, php_auto_globals_create_server TSRMLS_CC);
00916        zend_register_auto_global("_ENV", sizeof("_ENV")-1, php_auto_globals_create_env TSRMLS_CC);
00917        zend_register_auto_global("_REQUEST", sizeof("_REQUEST")-1, php_auto_globals_create_request TSRMLS_CC);
00918        zend_register_auto_global("_FILES", sizeof("_FILES")-1, NULL TSRMLS_CC);
00919 }
00920 
00921 /*
00922  * Local variables:
00923  * tab-width: 4
00924  * c-basic-offset: 4
00925  * End:
00926  * vim600: sw=4 ts=4 fdm=marker
00927  * vim<600: sw=4 ts=4
00928  */