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