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.

391 lines
10 KiB

22 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 6 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2009 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. | Author: Rui Hirokawa <hirokawa@php.net> |
  16. | Moriyoshi Koizumi <moriyoshi@php.net> |
  17. +----------------------------------------------------------------------+
  18. */
  19. /* $Id$ */
  20. /* {{{ includes */
  21. #ifdef HAVE_CONFIG_H
  22. #include "config.h"
  23. #endif
  24. #include "php.h"
  25. #include "php_ini.h"
  26. #include "php_variables.h"
  27. #include "mbstring.h"
  28. #include "ext/standard/php_string.h"
  29. #include "ext/standard/php_mail.h"
  30. #include "ext/standard/url.h"
  31. #include "main/php_output.h"
  32. #include "ext/standard/info.h"
  33. #include "php_variables.h"
  34. #include "php_globals.h"
  35. #include "rfc1867.h"
  36. #include "php_content_types.h"
  37. #include "SAPI.h"
  38. #include "TSRM.h"
  39. #include "mb_gpc.h"
  40. /* }}} */
  41. #if HAVE_MBSTRING
  42. ZEND_EXTERN_MODULE_GLOBALS(mbstring)
  43. /* {{{ MBSTRING_API SAPI_TREAT_DATA_FUNC(mbstr_treat_data)
  44. * http input processing */
  45. MBSTRING_API SAPI_TREAT_DATA_FUNC(mbstr_treat_data)
  46. {
  47. char *res = NULL, *separator=NULL;
  48. const char *c_var;
  49. zval *array_ptr;
  50. int free_buffer=0;
  51. enum mbfl_no_encoding detected;
  52. php_mb_encoding_handler_info_t info;
  53. {
  54. char *value = zend_ini_string("mbstring.internal_encoding", sizeof("mbstring.internal_encoding"), 0);
  55. _php_mb_ini_mbstring_internal_encoding_set(value, value ? strlen(value): 0 TSRMLS_CC);
  56. }
  57. if (!MBSTRG(encoding_translation)) {
  58. php_default_treat_data(arg, str, destArray TSRMLS_CC);
  59. return;
  60. }
  61. switch (arg) {
  62. case PARSE_POST:
  63. case PARSE_GET:
  64. case PARSE_COOKIE:
  65. ALLOC_ZVAL(array_ptr);
  66. array_init(array_ptr);
  67. INIT_PZVAL(array_ptr);
  68. switch (arg) {
  69. case PARSE_POST:
  70. PG(http_globals)[TRACK_VARS_POST] = array_ptr;
  71. break;
  72. case PARSE_GET:
  73. PG(http_globals)[TRACK_VARS_GET] = array_ptr;
  74. break;
  75. case PARSE_COOKIE:
  76. PG(http_globals)[TRACK_VARS_COOKIE] = array_ptr;
  77. break;
  78. }
  79. break;
  80. default:
  81. array_ptr=destArray;
  82. break;
  83. }
  84. if (arg==PARSE_POST) {
  85. sapi_handle_post(array_ptr TSRMLS_CC);
  86. return;
  87. }
  88. if (arg == PARSE_GET) { /* GET data */
  89. c_var = SG(request_info).query_string;
  90. if (c_var && *c_var) {
  91. res = (char *) estrdup(c_var);
  92. free_buffer = 1;
  93. } else {
  94. free_buffer = 0;
  95. }
  96. } else if (arg == PARSE_COOKIE) { /* Cookie data */
  97. c_var = SG(request_info).cookie_data;
  98. if (c_var && *c_var) {
  99. res = (char *) estrdup(c_var);
  100. free_buffer = 1;
  101. } else {
  102. free_buffer = 0;
  103. }
  104. } else if (arg == PARSE_STRING) { /* String data */
  105. res = str;
  106. free_buffer = 1;
  107. }
  108. if (!res) {
  109. return;
  110. }
  111. switch (arg) {
  112. case PARSE_POST:
  113. case PARSE_GET:
  114. case PARSE_STRING:
  115. separator = (char *) estrdup(PG(arg_separator).input);
  116. break;
  117. case PARSE_COOKIE:
  118. separator = ";\0";
  119. break;
  120. }
  121. switch(arg) {
  122. case PARSE_POST:
  123. MBSTRG(http_input_identify_post) = mbfl_no_encoding_invalid;
  124. break;
  125. case PARSE_GET:
  126. MBSTRG(http_input_identify_get) = mbfl_no_encoding_invalid;
  127. break;
  128. case PARSE_COOKIE:
  129. MBSTRG(http_input_identify_cookie) = mbfl_no_encoding_invalid;
  130. break;
  131. case PARSE_STRING:
  132. MBSTRG(http_input_identify_string) = mbfl_no_encoding_invalid;
  133. break;
  134. }
  135. info.data_type = arg;
  136. info.separator = separator;
  137. info.report_errors = 0;
  138. info.to_encoding = MBSTRG(internal_encoding);
  139. info.to_language = MBSTRG(language);
  140. info.from_encodings = MBSTRG(http_input_list);
  141. info.num_from_encodings = MBSTRG(http_input_list_size);
  142. info.from_language = MBSTRG(language);
  143. MBSTRG(illegalchars) = 0;
  144. detected = _php_mb_encoding_handler_ex(&info, array_ptr, res TSRMLS_CC);
  145. MBSTRG(http_input_identify) = detected;
  146. if (detected != mbfl_no_encoding_invalid) {
  147. switch(arg){
  148. case PARSE_POST:
  149. MBSTRG(http_input_identify_post) = detected;
  150. break;
  151. case PARSE_GET:
  152. MBSTRG(http_input_identify_get) = detected;
  153. break;
  154. case PARSE_COOKIE:
  155. MBSTRG(http_input_identify_cookie) = detected;
  156. break;
  157. case PARSE_STRING:
  158. MBSTRG(http_input_identify_string) = detected;
  159. break;
  160. }
  161. }
  162. if (arg != PARSE_COOKIE) {
  163. efree(separator);
  164. }
  165. if (free_buffer) {
  166. efree(res);
  167. }
  168. }
  169. /* }}} */
  170. /* {{{ mbfl_no_encoding _php_mb_encoding_handler_ex() */
  171. enum mbfl_no_encoding _php_mb_encoding_handler_ex(const php_mb_encoding_handler_info_t *info, zval *arg, char *res TSRMLS_DC)
  172. {
  173. char *var, *val;
  174. const char *s1, *s2;
  175. char *strtok_buf = NULL, **val_list = NULL;
  176. zval *array_ptr = (zval *) arg;
  177. int n, num, *len_list = NULL;
  178. unsigned int val_len, new_val_len;
  179. mbfl_string string, resvar, resval;
  180. enum mbfl_no_encoding from_encoding = mbfl_no_encoding_invalid;
  181. mbfl_encoding_detector *identd = NULL;
  182. mbfl_buffer_converter *convd = NULL;
  183. mbfl_string_init_set(&string, info->to_language, info->to_encoding);
  184. mbfl_string_init_set(&resvar, info->to_language, info->to_encoding);
  185. mbfl_string_init_set(&resval, info->to_language, info->to_encoding);
  186. if (!res || *res == '\0') {
  187. goto out;
  188. }
  189. /* count the variables(separators) contained in the "res".
  190. * separator may contain multiple separator chars.
  191. */
  192. num = 1;
  193. for (s1=res; *s1 != '\0'; s1++) {
  194. for (s2=info->separator; *s2 != '\0'; s2++) {
  195. if (*s1 == *s2) {
  196. num++;
  197. }
  198. }
  199. }
  200. num *= 2; /* need space for variable name and value */
  201. val_list = (char **)ecalloc(num, sizeof(char *));
  202. len_list = (int *)ecalloc(num, sizeof(int));
  203. /* split and decode the query */
  204. n = 0;
  205. strtok_buf = NULL;
  206. var = php_strtok_r(res, info->separator, &strtok_buf);
  207. while (var) {
  208. val = strchr(var, '=');
  209. if (val) { /* have a value */
  210. len_list[n] = php_url_decode(var, val-var);
  211. val_list[n] = var;
  212. n++;
  213. *val++ = '\0';
  214. val_list[n] = val;
  215. len_list[n] = php_url_decode(val, strlen(val));
  216. } else {
  217. len_list[n] = php_url_decode(var, strlen(var));
  218. val_list[n] = var;
  219. n++;
  220. val_list[n] = "";
  221. len_list[n] = 0;
  222. }
  223. n++;
  224. var = php_strtok_r(NULL, info->separator, &strtok_buf);
  225. }
  226. num = n; /* make sure to process initilized vars only */
  227. /* initialize converter */
  228. if (info->num_from_encodings <= 0) {
  229. from_encoding = mbfl_no_encoding_pass;
  230. } else if (info->num_from_encodings == 1) {
  231. from_encoding = info->from_encodings[0];
  232. } else {
  233. /* auto detect */
  234. from_encoding = mbfl_no_encoding_invalid;
  235. identd = mbfl_encoding_detector_new((enum mbfl_no_encoding *)info->from_encodings, info->num_from_encodings, MBSTRG(strict_detection));
  236. if (identd) {
  237. n = 0;
  238. while (n < num) {
  239. string.val = (unsigned char *)val_list[n];
  240. string.len = len_list[n];
  241. if (mbfl_encoding_detector_feed(identd, &string)) {
  242. break;
  243. }
  244. n++;
  245. }
  246. from_encoding = mbfl_encoding_detector_judge(identd);
  247. mbfl_encoding_detector_delete(identd);
  248. }
  249. if (from_encoding == mbfl_no_encoding_invalid) {
  250. if (info->report_errors) {
  251. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to detect encoding");
  252. }
  253. from_encoding = mbfl_no_encoding_pass;
  254. }
  255. }
  256. convd = NULL;
  257. if (from_encoding != mbfl_no_encoding_pass) {
  258. convd = mbfl_buffer_converter_new(from_encoding, info->to_encoding, 0);
  259. if (convd != NULL) {
  260. mbfl_buffer_converter_illegal_mode(convd, MBSTRG(current_filter_illegal_mode));
  261. mbfl_buffer_converter_illegal_substchar(convd, MBSTRG(current_filter_illegal_substchar));
  262. } else {
  263. if (info->report_errors) {
  264. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create converter");
  265. }
  266. goto out;
  267. }
  268. }
  269. /* convert encoding */
  270. string.no_encoding = from_encoding;
  271. n = 0;
  272. while (n < num) {
  273. string.val = (unsigned char *)val_list[n];
  274. string.len = len_list[n];
  275. if (convd != NULL && mbfl_buffer_converter_feed_result(convd, &string, &resvar) != NULL) {
  276. var = (char *)resvar.val;
  277. } else {
  278. var = val_list[n];
  279. }
  280. n++;
  281. string.val = val_list[n];
  282. string.len = len_list[n];
  283. if (convd != NULL && mbfl_buffer_converter_feed_result(convd, &string, &resval) != NULL) {
  284. val = resval.val;
  285. val_len = resval.len;
  286. } else {
  287. val = val_list[n];
  288. val_len = len_list[n];
  289. }
  290. n++;
  291. /* we need val to be emalloc()ed */
  292. val = estrndup(val, val_len);
  293. if (sapi_module.input_filter(info->data_type, var, &val, val_len, &new_val_len TSRMLS_CC)) {
  294. /* add variable to symbol table */
  295. php_register_variable_safe(IS_STRING, ZSTR(var), ZSTR(val), new_val_len, array_ptr TSRMLS_CC);
  296. }
  297. efree(val);
  298. if (convd != NULL){
  299. mbfl_string_clear(&resvar);
  300. mbfl_string_clear(&resval);
  301. }
  302. }
  303. out:
  304. if (convd != NULL) {
  305. MBSTRG(illegalchars) += mbfl_buffer_illegalchars(convd);
  306. mbfl_buffer_converter_delete(convd);
  307. }
  308. if (val_list != NULL) {
  309. efree((void *)val_list);
  310. }
  311. if (len_list != NULL) {
  312. efree((void *)len_list);
  313. }
  314. return from_encoding;
  315. }
  316. /* }}} */
  317. /* {{{ SAPI_POST_HANDLER_FUNC(php_mb_post_handler) */
  318. SAPI_POST_HANDLER_FUNC(php_mb_post_handler)
  319. {
  320. enum mbfl_no_encoding detected;
  321. php_mb_encoding_handler_info_t info;
  322. MBSTRG(http_input_identify_post) = mbfl_no_encoding_invalid;
  323. info.data_type = PARSE_POST;
  324. info.separator = "&";
  325. info.report_errors = 0;
  326. info.to_encoding = MBSTRG(internal_encoding);
  327. info.to_language = MBSTRG(language);
  328. info.from_encodings = MBSTRG(http_input_list);
  329. info.num_from_encodings = MBSTRG(http_input_list_size);
  330. info.from_language = MBSTRG(language);
  331. detected = _php_mb_encoding_handler_ex(&info, arg, SG(request_info).post_data TSRMLS_CC);
  332. MBSTRG(http_input_identify) = detected;
  333. if (detected != mbfl_no_encoding_invalid) {
  334. MBSTRG(http_input_identify_post) = detected;
  335. }
  336. }
  337. /* }}} */
  338. #endif /* HAVE_MBSTRING */
  339. /*
  340. * Local variables:
  341. * tab-width: 4
  342. * c-basic-offset: 4
  343. * End:
  344. * vim600: fdm=marker
  345. * vim: noet sw=4 ts=4
  346. */