mb_gpc.c 11 KB

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