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