You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1038 lines
29 KiB

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