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: Tsukada Takuya <tsukada@fminn.nagano.nagano.jp> |
16 : | Rui Hirokawa <hirokawa@php.net> |
17 : +----------------------------------------------------------------------+
18 : */
19 :
20 : /* $Id: mbstring.c 288613 2009-09-23 15:22:47Z moriyoshi $ */
21 :
22 : /*
23 : * PHP 4 Multibyte String module "mbstring"
24 : *
25 : * History:
26 : * 2000.5.19 Release php-4.0RC2_jstring-1.0
27 : * 2001.4.1 Release php4_jstring-1.0.91
28 : * 2001.4.30 Release php4_jstring-1.1 (contribute to The PHP Group)
29 : * 2001.5.1 Renamed from jstring to mbstring (hirokawa@php.net)
30 : */
31 :
32 : /*
33 : * PHP3 Internationalization support program.
34 : *
35 : * Copyright (c) 1999,2000 by the PHP3 internationalization team.
36 : * All rights reserved.
37 : *
38 : * See README_PHP3-i18n-ja for more detail.
39 : *
40 : * Authors:
41 : * Hironori Sato <satoh@jpnnet.com>
42 : * Shigeru Kanemoto <sgk@happysize.co.jp>
43 : * Tsukada Takuya <tsukada@fminn.nagano.nagano.jp>
44 : * Rui Hirokawa <rui_hirokawa@ybb.ne.jp>
45 : */
46 :
47 : /* {{{ includes */
48 : #ifdef HAVE_CONFIG_H
49 : #include "config.h"
50 : #endif
51 :
52 : #include "php.h"
53 : #include "php_ini.h"
54 : #include "php_variables.h"
55 : #include "mbstring.h"
56 : #include "ext/standard/php_string.h"
57 : #include "ext/standard/php_mail.h"
58 : #include "ext/standard/exec.h"
59 : #include "ext/standard/php_smart_str.h"
60 : #include "ext/standard/url.h"
61 : #include "main/php_output.h"
62 : #include "ext/standard/info.h"
63 :
64 : #include "libmbfl/mbfl/mbfl_allocators.h"
65 :
66 : #include "php_variables.h"
67 : #include "php_globals.h"
68 : #include "rfc1867.h"
69 : #include "php_content_types.h"
70 : #include "SAPI.h"
71 : #include "php_unicode.h"
72 : #include "TSRM.h"
73 :
74 : #include "mb_gpc.h"
75 :
76 : #ifdef ZEND_MULTIBYTE
77 : #include "zend_multibyte.h"
78 : #endif /* ZEND_MULTIBYTE */
79 :
80 : #if HAVE_MBSTRING
81 : /* }}} */
82 :
83 : /* {{{ prototypes */
84 : ZEND_DECLARE_MODULE_GLOBALS(mbstring)
85 : static PHP_GINIT_FUNCTION(mbstring);
86 : static PHP_GSHUTDOWN_FUNCTION(mbstring);
87 : /* }}} */
88 :
89 : /* {{{ php_mb_default_identify_list */
90 : typedef struct _php_mb_nls_ident_list {
91 : enum mbfl_no_language lang;
92 : const enum mbfl_no_encoding* list;
93 : int list_size;
94 : } php_mb_nls_ident_list;
95 :
96 : static const enum mbfl_no_encoding php_mb_default_identify_list_ja[] = {
97 : mbfl_no_encoding_ascii,
98 : mbfl_no_encoding_jis,
99 : mbfl_no_encoding_utf8,
100 : mbfl_no_encoding_euc_jp,
101 : mbfl_no_encoding_sjis
102 : };
103 :
104 : static const enum mbfl_no_encoding php_mb_default_identify_list_cn[] = {
105 : mbfl_no_encoding_ascii,
106 : mbfl_no_encoding_utf8,
107 : mbfl_no_encoding_euc_cn,
108 : mbfl_no_encoding_cp936
109 : };
110 :
111 : static const enum mbfl_no_encoding php_mb_default_identify_list_tw_hk[] = {
112 : mbfl_no_encoding_ascii,
113 : mbfl_no_encoding_utf8,
114 : mbfl_no_encoding_euc_tw,
115 : mbfl_no_encoding_big5
116 : };
117 :
118 : static const enum mbfl_no_encoding php_mb_default_identify_list_kr[] = {
119 : mbfl_no_encoding_ascii,
120 : mbfl_no_encoding_utf8,
121 : mbfl_no_encoding_euc_kr,
122 : mbfl_no_encoding_uhc
123 : };
124 :
125 : static const enum mbfl_no_encoding php_mb_default_identify_list_ru[] = {
126 : mbfl_no_encoding_ascii,
127 : mbfl_no_encoding_utf8,
128 : mbfl_no_encoding_koi8r,
129 : mbfl_no_encoding_cp1251,
130 : mbfl_no_encoding_cp866
131 : };
132 :
133 : static const enum mbfl_no_encoding php_mb_default_identify_list_hy[] = {
134 : mbfl_no_encoding_ascii,
135 : mbfl_no_encoding_utf8,
136 : mbfl_no_encoding_armscii8
137 : };
138 :
139 : static const enum mbfl_no_encoding php_mb_default_identify_list_tr[] = {
140 : mbfl_no_encoding_ascii,
141 : mbfl_no_encoding_utf8,
142 : mbfl_no_encoding_8859_9
143 : };
144 :
145 : static const enum mbfl_no_encoding php_mb_default_identify_list_neut[] = {
146 : mbfl_no_encoding_ascii,
147 : mbfl_no_encoding_utf8
148 : };
149 :
150 :
151 : static const php_mb_nls_ident_list php_mb_default_identify_list[] = {
152 : { mbfl_no_language_japanese, php_mb_default_identify_list_ja, sizeof(php_mb_default_identify_list_ja) / sizeof(php_mb_default_identify_list_ja[0]) },
153 : { mbfl_no_language_korean, php_mb_default_identify_list_kr, sizeof(php_mb_default_identify_list_kr) / sizeof(php_mb_default_identify_list_kr[0]) },
154 : { mbfl_no_language_traditional_chinese, php_mb_default_identify_list_tw_hk, sizeof(php_mb_default_identify_list_tw_hk) / sizeof(php_mb_default_identify_list_tw_hk[0]) },
155 : { mbfl_no_language_simplified_chinese, php_mb_default_identify_list_cn, sizeof(php_mb_default_identify_list_cn) / sizeof(php_mb_default_identify_list_cn[0]) },
156 : { mbfl_no_language_russian, php_mb_default_identify_list_ru, sizeof(php_mb_default_identify_list_ru) / sizeof(php_mb_default_identify_list_ru[0]) },
157 : { mbfl_no_language_armenian, php_mb_default_identify_list_hy, sizeof(php_mb_default_identify_list_hy) / sizeof(php_mb_default_identify_list_hy[0]) },
158 : { mbfl_no_language_turkish, php_mb_default_identify_list_tr, sizeof(php_mb_default_identify_list_tr) / sizeof(php_mb_default_identify_list_tr[0]) },
159 : { mbfl_no_language_neutral, php_mb_default_identify_list_neut, sizeof(php_mb_default_identify_list_neut) / sizeof(php_mb_default_identify_list_neut[0]) }
160 : };
161 :
162 : /* }}} */
163 :
164 : static
165 : ZEND_BEGIN_ARG_INFO(third_and_rest_force_ref, 1)
166 : ZEND_ARG_PASS_INFO(0)
167 : ZEND_ARG_PASS_INFO(0)
168 : ZEND_END_ARG_INFO()
169 :
170 : /* {{{ mb_overload_def mb_ovld[] */
171 : static const struct mb_overload_def mb_ovld[] = {
172 : {MB_OVERLOAD_MAIL, "mail", "mb_send_mail", "mb_orig_mail"},
173 : {MB_OVERLOAD_STRING, "strlen", "mb_strlen", "mb_orig_strlen"},
174 : {MB_OVERLOAD_STRING, "strpos", "mb_strpos", "mb_orig_strpos"},
175 : {MB_OVERLOAD_STRING, "strrpos", "mb_strrpos", "mb_orig_strrpos"},
176 : {MB_OVERLOAD_STRING, "stripos", "mb_stripos", "mb_orig_stripos"},
177 : {MB_OVERLOAD_STRING, "strripos", "mb_strripos", "mb_orig_stripos"},
178 : {MB_OVERLOAD_STRING, "strstr", "mb_strstr", "mb_orig_strstr"},
179 : {MB_OVERLOAD_STRING, "strrchr", "mb_strrchr", "mb_orig_strrchr"},
180 : {MB_OVERLOAD_STRING, "stristr", "mb_stristr", "mb_orig_stristr"},
181 : {MB_OVERLOAD_STRING, "substr", "mb_substr", "mb_orig_substr"},
182 : {MB_OVERLOAD_STRING, "strtolower", "mb_strtolower", "mb_orig_strtolower"},
183 : {MB_OVERLOAD_STRING, "strtoupper", "mb_strtoupper", "mb_orig_strtoupper"},
184 : {MB_OVERLOAD_STRING, "substr_count", "mb_substr_count", "mb_orig_substr_count"},
185 : #if HAVE_MBREGEX
186 : {MB_OVERLOAD_REGEX, "ereg", "mb_ereg", "mb_orig_ereg"},
187 : {MB_OVERLOAD_REGEX, "eregi", "mb_eregi", "mb_orig_eregi"},
188 : {MB_OVERLOAD_REGEX, "ereg_replace", "mb_ereg_replace", "mb_orig_ereg_replace"},
189 : {MB_OVERLOAD_REGEX, "eregi_replace", "mb_eregi_replace", "mb_orig_eregi_replace"},
190 : {MB_OVERLOAD_REGEX, "split", "mb_split", "mb_orig_split"},
191 : #endif
192 : {0, NULL, NULL, NULL}
193 : };
194 : /* }}} */
195 :
196 : /* {{{ zend_function_entry mbstring_functions[] */
197 : zend_function_entry mbstring_functions[] = {
198 : PHP_FE(mb_convert_case, NULL)
199 : PHP_FE(mb_strtoupper, NULL)
200 : PHP_FE(mb_strtolower, NULL)
201 : PHP_FE(mb_language, NULL)
202 : PHP_FE(mb_internal_encoding, NULL)
203 : PHP_FE(mb_http_input, NULL)
204 : PHP_FE(mb_http_output, NULL)
205 : PHP_FE(mb_detect_order, NULL)
206 : PHP_FE(mb_substitute_character, NULL)
207 : PHP_FE(mb_parse_str, second_arg_force_ref)
208 : PHP_FE(mb_output_handler, NULL)
209 : PHP_FE(mb_preferred_mime_name, NULL)
210 : PHP_FE(mb_strlen, NULL)
211 : PHP_FE(mb_strpos, NULL)
212 : PHP_FE(mb_strrpos, NULL)
213 : PHP_FE(mb_stripos, NULL)
214 : PHP_FE(mb_strripos, NULL)
215 : PHP_FE(mb_strstr, NULL)
216 : PHP_FE(mb_strrchr, NULL)
217 : PHP_FE(mb_stristr, NULL)
218 : PHP_FE(mb_strrichr, NULL)
219 : PHP_FE(mb_substr_count, NULL)
220 : PHP_FE(mb_substr, NULL)
221 : PHP_FE(mb_strcut, NULL)
222 : PHP_FE(mb_strwidth, NULL)
223 : PHP_FE(mb_strimwidth, NULL)
224 : PHP_FE(mb_convert_encoding, NULL)
225 : PHP_FE(mb_detect_encoding, NULL)
226 : PHP_FE(mb_list_encodings, NULL)
227 : PHP_FE(mb_convert_kana, NULL)
228 : PHP_FE(mb_encode_mimeheader, NULL)
229 : PHP_FE(mb_decode_mimeheader, NULL)
230 : PHP_FE(mb_convert_variables, third_and_rest_force_ref)
231 : PHP_FE(mb_encode_numericentity, NULL)
232 : PHP_FE(mb_decode_numericentity, NULL)
233 : PHP_FE(mb_send_mail, NULL)
234 : PHP_FE(mb_get_info, NULL)
235 : PHP_FE(mb_check_encoding, NULL)
236 : #if HAVE_MBREGEX
237 : PHP_MBREGEX_FUNCTION_ENTRIES
238 : #endif
239 : { NULL, NULL, NULL }
240 : };
241 : /* }}} */
242 :
243 : /* {{{ zend_module_entry mbstring_module_entry */
244 : zend_module_entry mbstring_module_entry = {
245 : STANDARD_MODULE_HEADER,
246 : "mbstring",
247 : mbstring_functions,
248 : PHP_MINIT(mbstring),
249 : PHP_MSHUTDOWN(mbstring),
250 : PHP_RINIT(mbstring),
251 : PHP_RSHUTDOWN(mbstring),
252 : PHP_MINFO(mbstring),
253 : NO_VERSION_YET,
254 : PHP_MODULE_GLOBALS(mbstring),
255 : PHP_GINIT(mbstring),
256 : PHP_GSHUTDOWN(mbstring),
257 : NULL,
258 : STANDARD_MODULE_PROPERTIES_EX
259 : };
260 : /* }}} */
261 :
262 : /* {{{ static sapi_post_entry php_post_entries[] */
263 : static sapi_post_entry php_post_entries[] = {
264 : { DEFAULT_POST_CONTENT_TYPE, sizeof(DEFAULT_POST_CONTENT_TYPE)-1, sapi_read_standard_form_data, php_std_post_handler },
265 : { MULTIPART_CONTENT_TYPE, sizeof(MULTIPART_CONTENT_TYPE)-1, NULL, rfc1867_post_handler },
266 : { NULL, 0, NULL, NULL }
267 : };
268 : /* }}} */
269 :
270 : #ifdef COMPILE_DL_MBSTRING
271 : ZEND_GET_MODULE(mbstring)
272 : # ifdef PHP_WIN32
273 : # include "zend_arg_defs.c"
274 : # endif
275 : #endif
276 :
277 : /* {{{ allocators */
278 : static void *_php_mb_allocators_malloc(unsigned int sz)
279 23885 : {
280 23885 : return emalloc(sz);
281 : }
282 :
283 : static void *_php_mb_allocators_realloc(void *ptr, unsigned int sz)
284 4000 : {
285 4000 : return erealloc(ptr, sz);
286 : }
287 :
288 : static void *_php_mb_allocators_calloc(unsigned int nelems, unsigned int szelem)
289 34 : {
290 34 : return ecalloc(nelems, szelem);
291 : }
292 :
293 : static void _php_mb_allocators_free(void *ptr)
294 21617 : {
295 21617 : efree(ptr);
296 21617 : }
297 :
298 : static void *_php_mb_allocators_pmalloc(unsigned int sz)
299 0 : {
300 0 : return pemalloc(sz, 1);
301 : }
302 :
303 : static void *_php_mb_allocators_prealloc(void *ptr, unsigned int sz)
304 0 : {
305 0 : return perealloc(ptr, sz, 1);
306 : }
307 :
308 : static void _php_mb_allocators_pfree(void *ptr)
309 0 : {
310 0 : pefree(ptr, 1);
311 0 : }
312 :
313 : static mbfl_allocators _php_mb_allocators = {
314 : _php_mb_allocators_malloc,
315 : _php_mb_allocators_realloc,
316 : _php_mb_allocators_calloc,
317 : _php_mb_allocators_free,
318 : _php_mb_allocators_pmalloc,
319 : _php_mb_allocators_prealloc,
320 : _php_mb_allocators_pfree
321 : };
322 : /* }}} */
323 :
324 : /* {{{ static sapi_post_entry mbstr_post_entries[] */
325 : static sapi_post_entry mbstr_post_entries[] = {
326 : { DEFAULT_POST_CONTENT_TYPE, sizeof(DEFAULT_POST_CONTENT_TYPE)-1, sapi_read_standard_form_data, php_mb_post_handler },
327 : { MULTIPART_CONTENT_TYPE, sizeof(MULTIPART_CONTENT_TYPE)-1, NULL, rfc1867_post_handler },
328 : { NULL, 0, NULL, NULL }
329 : };
330 : /* }}} */
331 :
332 : /* {{{ static int php_mb_parse_encoding_list()
333 : * Return 0 if input contains any illegal encoding, otherwise 1.
334 : * Even if any illegal encoding is detected the result may contain a list
335 : * of parsed encodings.
336 : */
337 : static int
338 : php_mb_parse_encoding_list(const char *value, int value_length, enum mbfl_no_encoding **return_list, int *return_size, int persistent TSRMLS_DC)
339 97614 : {
340 97614 : int n, l, size, bauto, ret = 1;
341 : char *p, *p1, *p2, *endp, *tmpstr;
342 : enum mbfl_no_encoding no_encoding;
343 : enum mbfl_no_encoding *src, *entry, *list;
344 :
345 97614 : list = NULL;
346 97614 : if (value == NULL || value_length <= 0) {
347 13565 : if (return_list) {
348 13565 : *return_list = NULL;
349 : }
350 13565 : if (return_size) {
351 13565 : *return_size = 0;
352 : }
353 13565 : return 0;
354 : } else {
355 : enum mbfl_no_encoding *identify_list;
356 : int identify_list_size;
357 :
358 84049 : identify_list = MBSTRG(default_detect_order_list);
359 84049 : identify_list_size = MBSTRG(default_detect_order_list_size);
360 :
361 : /* copy the value string for work */
362 84049 : if (value[0]=='"' && value[value_length-1]=='"' && value_length>2) {
363 0 : tmpstr = (char *)estrndup(value+1, value_length-2);
364 0 : value_length -= 2;
365 : }
366 : else
367 84049 : tmpstr = (char *)estrndup(value, value_length);
368 84049 : if (tmpstr == NULL) {
369 0 : return 0;
370 : }
371 : /* count the number of listed encoding names */
372 84049 : endp = tmpstr + value_length;
373 84049 : n = 1;
374 84049 : p1 = tmpstr;
375 168122 : while ((p2 = php_memnstr(p1, ",", 1, endp)) != NULL) {
376 24 : p1 = p2 + 1;
377 24 : n++;
378 : }
379 84049 : size = n + identify_list_size;
380 : /* make list */
381 84049 : list = (enum mbfl_no_encoding *)pecalloc(size, sizeof(int), persistent);
382 84049 : if (list != NULL) {
383 84049 : entry = list;
384 84049 : n = 0;
385 84049 : bauto = 0;
386 84049 : p1 = tmpstr;
387 : do {
388 84073 : p2 = p = php_memnstr(p1, ",", 1, endp);
389 84073 : if (p == NULL) {
390 84049 : p = endp;
391 : }
392 84073 : *p = '\0';
393 : /* trim spaces */
394 168146 : while (p1 < p && (*p1 == ' ' || *p1 == '\t')) {
395 0 : p1++;
396 : }
397 84073 : p--;
398 168146 : while (p > p1 && (*p == ' ' || *p == '\t')) {
399 0 : *p = '\0';
400 0 : p--;
401 : }
402 : /* convert to the encoding number and check encoding */
403 84073 : if (strcasecmp(p1, "auto") == 0) {
404 12 : if (!bauto) {
405 12 : bauto = 1;
406 12 : l = identify_list_size;
407 12 : src = identify_list;
408 81 : while (l > 0) {
409 57 : *entry++ = *src++;
410 57 : l--;
411 57 : n++;
412 : }
413 : }
414 : } else {
415 84061 : no_encoding = mbfl_name2no_encoding(p1);
416 84061 : if (no_encoding != mbfl_no_encoding_invalid) {
417 84059 : *entry++ = no_encoding;
418 84059 : n++;
419 : } else {
420 2 : ret = 0;
421 : }
422 : }
423 84073 : p1 = p2 + 1;
424 84073 : } while (n < size && p2 != NULL);
425 84049 : if (n > 0) {
426 84047 : if (return_list) {
427 16222 : *return_list = list;
428 : } else {
429 67825 : pefree(list, persistent);
430 : }
431 : } else {
432 2 : pefree(list, persistent);
433 2 : if (return_list) {
434 2 : *return_list = NULL;
435 : }
436 2 : ret = 0;
437 : }
438 84049 : if (return_size) {
439 16224 : *return_size = n;
440 : }
441 : } else {
442 0 : if (return_list) {
443 0 : *return_list = NULL;
444 : }
445 0 : if (return_size) {
446 0 : *return_size = 0;
447 : }
448 0 : ret = 0;
449 : }
450 84049 : efree(tmpstr);
451 : }
452 :
453 84049 : return ret;
454 : }
455 : /* }}} */
456 :
457 : /* {{{ MBSTRING_API php_mb_check_encoding_list */
458 67825 : MBSTRING_API int php_mb_check_encoding_list(const char *encoding_list TSRMLS_DC) {
459 67825 : return php_mb_parse_encoding_list(encoding_list, strlen(encoding_list), NULL, NULL, 0 TSRMLS_CC);
460 : }
461 : /* }}} */
462 :
463 : /* {{{ static int php_mb_parse_encoding_array()
464 : * Return 0 if input contains any illegal encoding, otherwise 1.
465 : * Even if any illegal encoding is detected the result may contain a list
466 : * of parsed encodings.
467 : */
468 : static int
469 : php_mb_parse_encoding_array(zval *array, enum mbfl_no_encoding **return_list, int *return_size, int persistent TSRMLS_DC)
470 5 : {
471 : zval **hash_entry;
472 : HashTable *target_hash;
473 5 : int i, n, l, size, bauto,ret = 1;
474 : enum mbfl_no_encoding no_encoding;
475 : enum mbfl_no_encoding *src, *list, *entry;
476 :
477 5 : list = NULL;
478 5 : if (Z_TYPE_P(array) == IS_ARRAY) {
479 : enum mbfl_no_encoding *identify_list;
480 : int identify_list_size;
481 :
482 5 : identify_list = MBSTRG(default_detect_order_list);
483 5 : identify_list_size = MBSTRG(default_detect_order_list_size);
484 :
485 5 : target_hash = Z_ARRVAL_P(array);
486 5 : zend_hash_internal_pointer_reset(target_hash);
487 5 : i = zend_hash_num_elements(target_hash);
488 5 : size = i + identify_list_size;
489 5 : list = (enum mbfl_no_encoding *)pecalloc(size, sizeof(int), persistent);
490 5 : if (list != NULL) {
491 5 : entry = list;
492 5 : bauto = 0;
493 5 : n = 0;
494 31 : while (i > 0) {
495 21 : if (zend_hash_get_current_data(target_hash, (void **) &hash_entry) == FAILURE) {
496 0 : break;
497 : }
498 21 : convert_to_string_ex(hash_entry);
499 21 : if (strcasecmp(Z_STRVAL_PP(hash_entry), "auto") == 0) {
500 0 : if (!bauto) {
501 0 : bauto = 1;
502 0 : l = identify_list_size;
503 0 : src = identify_list;
504 0 : while (l > 0) {
505 0 : *entry++ = *src++;
506 0 : l--;
507 0 : n++;
508 : }
509 : }
510 : } else {
511 21 : no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(hash_entry));
512 21 : if (no_encoding != mbfl_no_encoding_invalid) {
513 20 : *entry++ = no_encoding;
514 20 : n++;
515 : } else {
516 1 : ret = 0;
517 : }
518 : }
519 21 : zend_hash_move_forward(target_hash);
520 21 : i--;
521 : }
522 5 : if (n > 0) {
523 5 : if (return_list) {
524 5 : *return_list = list;
525 : } else {
526 0 : pefree(list, persistent);
527 : }
528 : } else {
529 0 : pefree(list, persistent);
530 0 : if (return_list) {
531 0 : *return_list = NULL;
532 : }
533 0 : ret = 0;
534 : }
535 5 : if (return_size) {
536 5 : *return_size = n;
537 : }
538 : } else {
539 0 : if (return_list) {
540 0 : *return_list = NULL;
541 : }
542 0 : if (return_size) {
543 0 : *return_size = 0;
544 : }
545 0 : ret = 0;
546 : }
547 : }
548 :
549 5 : return ret;
550 : }
551 : /* }}} */
552 :
553 : /* {{{ php_mb_nls_get_default_detect_order_list */
554 : static int php_mb_nls_get_default_detect_order_list(enum mbfl_no_language lang, enum mbfl_no_encoding **plist, int* plist_size)
555 13593 : {
556 : size_t i;
557 :
558 13593 : *plist = (enum mbfl_no_encoding *) php_mb_default_identify_list_neut;
559 13593 : *plist_size = sizeof(php_mb_default_identify_list_neut) / sizeof(php_mb_default_identify_list_neut[0]);
560 :
561 108606 : for (i = 0; i < sizeof(php_mb_default_identify_list) / sizeof(php_mb_default_identify_list[0]); i++) {
562 108602 : if (php_mb_default_identify_list[i].lang == lang) {
563 13589 : *plist = (enum mbfl_no_encoding *)php_mb_default_identify_list[i].list;
564 13589 : *plist_size = php_mb_default_identify_list[i].list_size;
565 13589 : return 1;
566 : }
567 : }
568 4 : return 0;
569 : }
570 : /* }}} */
571 :
572 : /* {{{ php.ini directive handler */
573 : static PHP_INI_MH(OnUpdate_mbstring_language)
574 13593 : {
575 : enum mbfl_no_language no_language;
576 :
577 13593 : no_language = mbfl_name2no_language(new_value);
578 13593 : if (no_language == mbfl_no_language_invalid) {
579 0 : MBSTRG(language) = mbfl_no_language_neutral;
580 0 : return FAILURE;
581 : }
582 13593 : MBSTRG(language) = no_language;
583 13593 : php_mb_nls_get_default_detect_order_list(no_language, &MBSTRG(default_detect_order_list), &MBSTRG(default_detect_order_list_size));
584 13593 : return SUCCESS;
585 : }
586 : /* }}} */
587 :
588 : /* {{{ static PHP_INI_MH(OnUpdate_mbstring_detect_order) */
589 : static PHP_INI_MH(OnUpdate_mbstring_detect_order)
590 13565 : {
591 : enum mbfl_no_encoding *list;
592 : int size;
593 :
594 13565 : if (php_mb_parse_encoding_list(new_value, new_value_length, &list, &size, 1 TSRMLS_CC)) {
595 0 : if (MBSTRG(detect_order_list)) {
596 0 : free(MBSTRG(detect_order_list));
597 : }
598 0 : MBSTRG(detect_order_list) = list;
599 0 : MBSTRG(detect_order_list_size) = size;
600 : } else {
601 13565 : if (MBSTRG(detect_order_list)) {
602 0 : free(MBSTRG(detect_order_list));
603 0 : MBSTRG(detect_order_list) = NULL;
604 : }
605 13565 : return FAILURE;
606 : }
607 :
608 0 : return SUCCESS;
609 : }
610 : /* }}} */
611 :
612 : /* {{{ static PHP_INI_MH(OnUpdate_mbstring_http_input) */
613 : static PHP_INI_MH(OnUpdate_mbstring_http_input)
614 13565 : {
615 : enum mbfl_no_encoding *list;
616 : int size;
617 :
618 13565 : if (php_mb_parse_encoding_list(new_value, new_value_length, &list, &size, 1 TSRMLS_CC)) {
619 13565 : if (MBSTRG(http_input_list)) {
620 0 : free(MBSTRG(http_input_list));
621 : }
622 13565 : MBSTRG(http_input_list) = list;
623 13565 : MBSTRG(http_input_list_size) = size;
624 : } else {
625 0 : if (MBSTRG(http_input_list)) {
626 0 : free(MBSTRG(http_input_list));
627 0 : MBSTRG(http_input_list) = NULL;
628 : }
629 0 : MBSTRG(http_input_list_size) = 0;
630 0 : return FAILURE;
631 : }
632 :
633 13565 : return SUCCESS;
634 : }
635 : /* }}} */
636 :
637 : /* {{{ static PHP_INI_MH(OnUpdate_mbstring_http_output) */
638 : static PHP_INI_MH(OnUpdate_mbstring_http_output)
639 13565 : {
640 : enum mbfl_no_encoding no_encoding;
641 :
642 13565 : no_encoding = mbfl_name2no_encoding(new_value);
643 13565 : if (no_encoding != mbfl_no_encoding_invalid) {
644 13565 : MBSTRG(http_output_encoding) = no_encoding;
645 13565 : MBSTRG(current_http_output_encoding) = no_encoding;
646 : } else {
647 0 : MBSTRG(http_output_encoding) = mbfl_no_encoding_pass;
648 0 : MBSTRG(current_http_output_encoding) = mbfl_no_encoding_pass;
649 0 : if (new_value != NULL && new_value_length > 0) {
650 0 : return FAILURE;
651 : }
652 : }
653 :
654 13565 : return SUCCESS;
655 : }
656 : /* }}} */
657 :
658 : /* {{{ static _php_mb_ini_mbstring_internal_encoding_set */
659 : int _php_mb_ini_mbstring_internal_encoding_set(const char *new_value, uint new_value_length TSRMLS_DC)
660 40696 : {
661 : enum mbfl_no_encoding no_encoding;
662 40696 : const char *enc_name = NULL;
663 40696 : uint enc_name_len = 0;
664 :
665 40696 : no_encoding = new_value ? mbfl_name2no_encoding(new_value):
666 : mbfl_no_encoding_invalid;
667 40696 : if (no_encoding != mbfl_no_encoding_invalid) {
668 115 : enc_name = new_value;
669 115 : enc_name_len = new_value_length;
670 : } else {
671 40581 : switch (MBSTRG(language)) {
672 : case mbfl_no_language_uni:
673 0 : enc_name = "UTF-8";
674 0 : enc_name_len = sizeof("UTF-8") - 1;
675 0 : break;
676 : case mbfl_no_language_japanese:
677 30 : enc_name = "EUC-JP";
678 30 : enc_name_len = sizeof("EUC-JP") - 1;
679 30 : break;
680 : case mbfl_no_language_korean:
681 0 : enc_name = "EUC-KR";
682 0 : enc_name_len = sizeof("EUC-KR") - 1;
683 0 : break;
684 : case mbfl_no_language_simplified_chinese:
685 0 : enc_name = "EUC-CN";
686 0 : enc_name_len = sizeof("EUC-CN") - 1;
687 0 : break;
688 : case mbfl_no_language_traditional_chinese:
689 0 : enc_name = "EUC-TW";
690 0 : enc_name_len = sizeof("EUC-TW") - 1;
691 0 : break;
692 : case mbfl_no_language_russian:
693 0 : enc_name = "KOI8-R";
694 0 : enc_name_len = sizeof("KOI8-R") - 1;
695 0 : break;
696 : case mbfl_no_language_german:
697 0 : enc_name = "ISO-8859-15";
698 0 : enc_name_len = sizeof("ISO-8859-15") - 1;
699 0 : break;
700 : case mbfl_no_language_armenian:
701 0 : enc_name = "ArmSCII-8";
702 0 : enc_name_len = sizeof("ArmSCII-8") - 1;
703 0 : break;
704 : case mbfl_no_language_turkish:
705 0 : enc_name = "ISO-8859-9";
706 0 : enc_name_len = sizeof("ISO-8859-9") - 1;
707 0 : break;
708 : default:
709 40551 : enc_name = "ISO-8859-1";
710 40551 : enc_name_len = sizeof("ISO-8859-1") - 1;
711 : break;
712 : }
713 40581 : no_encoding = mbfl_name2no_encoding(enc_name);
714 : }
715 40696 : MBSTRG(internal_encoding) = no_encoding;
716 40696 : MBSTRG(current_internal_encoding) = no_encoding;
717 : #if HAVE_MBREGEX
718 : {
719 : OnigEncoding mbctype;
720 40696 : mbctype = php_mb_regex_name2mbctype(enc_name);
721 40696 : if (mbctype == ONIG_ENCODING_UNDEF) {
722 42 : mbctype = ONIG_ENCODING_EUC_JP;
723 : }
724 40696 : MBSTRG(current_mbctype) = MBSTRG(default_mbctype) = mbctype;
725 : }
726 : #endif
727 : #ifdef ZEND_MULTIBYTE
728 : zend_multibyte_set_internal_encoding((char *)enc_name, enc_name_len TSRMLS_CC);
729 : #endif /* ZEND_MULTIBYTE */
730 :
731 40696 : return SUCCESS;
732 : }
733 : /* }}} */
734 :
735 : /* {{{ static PHP_INI_MH(OnUpdate_mbstring_internal_encoding) */
736 : static PHP_INI_MH(OnUpdate_mbstring_internal_encoding)
737 13567 : {
738 13567 : if (stage == PHP_INI_STAGE_STARTUP || stage == PHP_INI_STAGE_SHUTDOWN
739 : || stage == PHP_INI_STAGE_RUNTIME) {
740 13566 : return _php_mb_ini_mbstring_internal_encoding_set(new_value, new_value_length TSRMLS_CC);
741 : } else {
742 : /* the corresponding mbstring globals needs to be set according to the
743 : * ini value in the later stage because it never falls back to the
744 : * default value if 1. no value for mbstring.internal_encoding is given,
745 : * 2. mbstring.language directive is processed in per-dir or runtime
746 : * context and 3. call to the handler for mbstring.language is done
747 : * after mbstring.internal_encoding is handled. */
748 1 : return SUCCESS;
749 : }
750 : }
751 : /* }}} */
752 :
753 : #ifdef ZEND_MULTIBYTE
754 : /* {{{ static PHP_INI_MH(OnUpdate_mbstring_script_encoding) */
755 : static PHP_INI_MH(OnUpdate_mbstring_script_encoding)
756 : {
757 : int *list, size;
758 :
759 : if (php_mb_parse_encoding_list(new_value, new_value_length, &list, &size, 1 TSRMLS_CC)) {
760 : if (MBSTRG(script_encoding_list) != NULL) {
761 : free(MBSTRG(script_encoding_list));
762 : }
763 : MBSTRG(script_encoding_list) = list;
764 : MBSTRG(script_encoding_list_size) = size;
765 : } else {
766 : if (MBSTRG(script_encoding_list) != NULL) {
767 : free(MBSTRG(script_encoding_list));
768 : }
769 : MBSTRG(script_encoding_list) = NULL;
770 : MBSTRG(script_encoding_list_size) = 0;
771 : return FAILURE;
772 : }
773 :
774 : return SUCCESS;
775 : }
776 : /* }}} */
777 : #endif /* ZEND_MULTIBYTE */
778 :
779 : /* {{{ static PHP_INI_MH(OnUpdate_mbstring_substitute_character) */
780 : static PHP_INI_MH(OnUpdate_mbstring_substitute_character)
781 13565 : {
782 : int c;
783 13565 : char *endptr = NULL;
784 :
785 13565 : if (new_value != NULL) {
786 0 : if (strcasecmp("none", new_value) == 0) {
787 0 : MBSTRG(filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE;
788 0 : MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE;
789 0 : } else if (strcasecmp("long", new_value) == 0) {
790 0 : MBSTRG(filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG;
791 0 : MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG;
792 0 : } else if (strcasecmp("entity", new_value) == 0) {
793 0 : MBSTRG(filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_ENTITY;
794 0 : MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_ENTITY;
795 : } else {
796 0 : MBSTRG(filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
797 0 : MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
798 0 : if (new_value_length >0) {
799 0 : c = strtol(new_value, &endptr, 0);
800 0 : if (*endptr == '\0') {
801 0 : MBSTRG(filter_illegal_substchar) = c;
802 0 : MBSTRG(current_filter_illegal_substchar) = c;
803 : }
804 : }
805 : }
806 : } else {
807 13565 : MBSTRG(filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
808 13565 : MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
809 13565 : MBSTRG(filter_illegal_substchar) = 0x3f; /* '?' */
810 13565 : MBSTRG(current_filter_illegal_substchar) = 0x3f; /* '?' */
811 : }
812 :
813 13565 : return SUCCESS;
814 : }
815 : /* }}} */
816 :
817 : /* {{{ static PHP_INI_MH(OnUpdate_mbstring_encoding_translation) */
818 : static PHP_INI_MH(OnUpdate_mbstring_encoding_translation)
819 13565 : {
820 13565 : if (new_value == NULL) {
821 0 : return FAILURE;
822 : }
823 :
824 13565 : OnUpdateBool(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
825 :
826 13565 : if (MBSTRG(encoding_translation)) {
827 2 : sapi_unregister_post_entry(php_post_entries TSRMLS_CC);
828 2 : sapi_register_post_entries(mbstr_post_entries TSRMLS_CC);
829 : } else {
830 13563 : sapi_unregister_post_entry(mbstr_post_entries TSRMLS_CC);
831 13563 : sapi_register_post_entries(php_post_entries TSRMLS_CC);
832 : }
833 :
834 13565 : return SUCCESS;
835 : }
836 : /* }}} */
837 :
838 : /* {{{ php.ini directive registration */
839 : PHP_INI_BEGIN()
840 : PHP_INI_ENTRY("mbstring.language", "neutral", PHP_INI_ALL, OnUpdate_mbstring_language)
841 : PHP_INI_ENTRY("mbstring.detect_order", NULL, PHP_INI_ALL, OnUpdate_mbstring_detect_order)
842 : PHP_INI_ENTRY("mbstring.http_input", "pass", PHP_INI_ALL, OnUpdate_mbstring_http_input)
843 : PHP_INI_ENTRY("mbstring.http_output", "pass", PHP_INI_ALL, OnUpdate_mbstring_http_output)
844 : PHP_INI_ENTRY("mbstring.internal_encoding", NULL, PHP_INI_ALL, OnUpdate_mbstring_internal_encoding)
845 : #ifdef ZEND_MULTIBYTE
846 : PHP_INI_ENTRY("mbstring.script_encoding", NULL, PHP_INI_ALL, OnUpdate_mbstring_script_encoding)
847 : #endif /* ZEND_MULTIBYTE */
848 : PHP_INI_ENTRY("mbstring.substitute_character", NULL, PHP_INI_ALL, OnUpdate_mbstring_substitute_character)
849 : STD_PHP_INI_ENTRY("mbstring.func_overload", "0",
850 : PHP_INI_SYSTEM, OnUpdateLong, func_overload, zend_mbstring_globals, mbstring_globals)
851 :
852 : STD_PHP_INI_BOOLEAN("mbstring.encoding_translation", "0",
853 : PHP_INI_SYSTEM | PHP_INI_PERDIR, OnUpdate_mbstring_encoding_translation,
854 : encoding_translation, zend_mbstring_globals, mbstring_globals)
855 :
856 : STD_PHP_INI_BOOLEAN("mbstring.strict_detection", "0",
857 : PHP_INI_ALL, OnUpdateLong, strict_detection, zend_mbstring_globals, mbstring_globals)
858 : PHP_INI_END()
859 : /* }}} */
860 :
861 : /* {{{ module global initialize handler */
862 : static PHP_GINIT_FUNCTION(mbstring)
863 13565 : {
864 13565 : mbstring_globals->language = mbfl_no_language_uni;
865 13565 : mbstring_globals->internal_encoding = mbfl_no_encoding_invalid;
866 13565 : mbstring_globals->current_internal_encoding = mbstring_globals->internal_encoding;
867 : #ifdef ZEND_MULTIBYTE
868 : mbstring_globals->script_encoding_list = NULL;
869 : mbstring_globals->script_encoding_list_size = 0;
870 : #endif /* ZEND_MULTIBYTE */
871 13565 : mbstring_globals->http_output_encoding = mbfl_no_encoding_pass;
872 13565 : mbstring_globals->current_http_output_encoding = mbfl_no_encoding_pass;
873 13565 : mbstring_globals->http_input_identify = mbfl_no_encoding_invalid;
874 13565 : mbstring_globals->http_input_identify_get = mbfl_no_encoding_invalid;
875 13565 : mbstring_globals->http_input_identify_post = mbfl_no_encoding_invalid;
876 13565 : mbstring_globals->http_input_identify_cookie = mbfl_no_encoding_invalid;
877 13565 : mbstring_globals->http_input_identify_string = mbfl_no_encoding_invalid;
878 13565 : mbstring_globals->http_input_list = NULL;
879 13565 : mbstring_globals->http_input_list_size = 0;
880 13565 : mbstring_globals->detect_order_list = NULL;
881 13565 : mbstring_globals->detect_order_list_size = 0;
882 13565 : mbstring_globals->current_detect_order_list = NULL;
883 13565 : mbstring_globals->current_detect_order_list_size = 0;
884 13565 : mbstring_globals->default_detect_order_list = (enum mbfl_no_encoding *) php_mb_default_identify_list_neut;
885 13565 : mbstring_globals->default_detect_order_list_size = sizeof(php_mb_default_identify_list_neut) / sizeof(php_mb_default_identify_list_neut[0]);
886 13565 : mbstring_globals->filter_illegal_mode = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
887 13565 : mbstring_globals->filter_illegal_substchar = 0x3f; /* '?' */
888 13565 : mbstring_globals->current_filter_illegal_mode = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
889 13565 : mbstring_globals->current_filter_illegal_substchar = 0x3f; /* '?' */
890 13565 : mbstring_globals->illegalchars = 0;
891 13565 : mbstring_globals->func_overload = 0;
892 13565 : mbstring_globals->encoding_translation = 0;
893 13565 : mbstring_globals->strict_detection = 0;
894 13565 : mbstring_globals->outconv = NULL;
895 : #if HAVE_MBREGEX
896 13565 : _php_mb_regex_globals_ctor(mbstring_globals TSRMLS_CC);
897 : #endif
898 13565 : }
899 : /* }}} */
900 :
901 : /* {{{ PHP_GSHUTDOWN_FUNCTION */
902 : static PHP_GSHUTDOWN_FUNCTION(mbstring)
903 13597 : {
904 13597 : if (mbstring_globals->http_input_list) {
905 13597 : free(mbstring_globals->http_input_list);
906 : }
907 : #ifdef ZEND_MULTIBYTE
908 : if (mbstring_globals->script_encoding_list) {
909 : free(mbstring_globals->script_encoding_list);
910 : }
911 : #endif /* ZEND_MULTIBYTE */
912 13597 : if (mbstring_globals->detect_order_list) {
913 0 : free(mbstring_globals->detect_order_list);
914 : }
915 :
916 : #if HAVE_MBREGEX
917 13597 : _php_mb_regex_globals_dtor(mbstring_globals TSRMLS_CC);
918 : #endif
919 13597 : }
920 : /* }}} */
921 :
922 : /* {{{ PHP_MINIT_FUNCTION(mbstring) */
923 : PHP_MINIT_FUNCTION(mbstring)
924 13565 : {
925 13565 : __mbfl_allocators = &_php_mb_allocators;
926 :
927 13565 : REGISTER_INI_ENTRIES();
928 :
929 : /* This is a global handler. Should not be set in a per-request handler. */
930 13565 : sapi_register_treat_data(mbstr_treat_data);
931 :
932 : /* Post handlers are stored in the thread-local context. */
933 13565 : if (MBSTRG(encoding_translation)) {
934 2 : sapi_register_post_entries(mbstr_post_entries TSRMLS_CC);
935 : }
936 :
937 13565 : REGISTER_LONG_CONSTANT("MB_OVERLOAD_MAIL", MB_OVERLOAD_MAIL, CONST_CS | CONST_PERSISTENT);
938 13565 : REGISTER_LONG_CONSTANT("MB_OVERLOAD_STRING", MB_OVERLOAD_STRING, CONST_CS | CONST_PERSISTENT);
939 13565 : REGISTER_LONG_CONSTANT("MB_OVERLOAD_REGEX", MB_OVERLOAD_REGEX, CONST_CS | CONST_PERSISTENT);
940 :
941 13565 : REGISTER_LONG_CONSTANT("MB_CASE_UPPER", PHP_UNICODE_CASE_UPPER, CONST_CS | CONST_PERSISTENT);
942 13565 : REGISTER_LONG_CONSTANT("MB_CASE_LOWER", PHP_UNICODE_CASE_LOWER, CONST_CS | CONST_PERSISTENT);
943 13565 : REGISTER_LONG_CONSTANT("MB_CASE_TITLE", PHP_UNICODE_CASE_TITLE, CONST_CS | CONST_PERSISTENT);
944 :
945 : #if HAVE_MBREGEX
946 13565 : PHP_MINIT(mb_regex) (INIT_FUNC_ARGS_PASSTHRU);
947 : #endif
948 13565 : return SUCCESS;
949 : }
950 : /* }}} */
951 :
952 : /* {{{ PHP_MSHUTDOWN_FUNCTION(mbstring) */
953 : PHP_MSHUTDOWN_FUNCTION(mbstring)
954 13597 : {
955 13597 : UNREGISTER_INI_ENTRIES();
956 :
957 : #if HAVE_MBREGEX
958 13597 : PHP_MSHUTDOWN(mb_regex) (INIT_FUNC_ARGS_PASSTHRU);
959 : #endif
960 :
961 13597 : return SUCCESS;
962 : }
963 : /* }}} */
964 :
965 : /* {{{ PHP_RINIT_FUNCTION(mbstring) */
966 : PHP_RINIT_FUNCTION(mbstring)
967 13551 : {
968 : int n;
969 13551 : enum mbfl_no_encoding *list=NULL, *entry;
970 : zend_function *func, *orig;
971 : const struct mb_overload_def *p;
972 :
973 13551 : MBSTRG(current_internal_encoding) = MBSTRG(internal_encoding);
974 13551 : MBSTRG(current_http_output_encoding) = MBSTRG(http_output_encoding);
975 13551 : MBSTRG(current_filter_illegal_mode) = MBSTRG(filter_illegal_mode);
976 13551 : MBSTRG(current_filter_illegal_substchar) = MBSTRG(filter_illegal_substchar);
977 :
978 13551 : MBSTRG(illegalchars) = 0;
979 :
980 13551 : n = 0;
981 13551 : if (MBSTRG(detect_order_list)) {
982 0 : list = MBSTRG(detect_order_list);
983 0 : n = MBSTRG(detect_order_list_size);
984 : }
985 13551 : if (n <= 0) {
986 13551 : list = MBSTRG(default_detect_order_list);
987 13551 : n = MBSTRG(default_detect_order_list_size);
988 : }
989 13551 : entry = (enum mbfl_no_encoding *)safe_emalloc(n, sizeof(int), 0);
990 13551 : MBSTRG(current_detect_order_list) = entry;
991 13551 : MBSTRG(current_detect_order_list_size) = n;
992 54246 : while (n > 0) {
993 27144 : *entry++ = *list++;
994 27144 : n--;
995 : }
996 :
997 : /* override original function. */
998 13551 : if (MBSTRG(func_overload)){
999 4 : p = &(mb_ovld[0]);
1000 :
1001 80 : while (p->type > 0) {
1002 72 : if ((MBSTRG(func_overload) & p->type) == p->type &&
1003 : zend_hash_find(EG(function_table), p->save_func,
1004 : strlen(p->save_func)+1, (void **)&orig) != SUCCESS) {
1005 :
1006 68 : zend_hash_find(EG(function_table), p->ovld_func, strlen(p->ovld_func)+1 , (void **)&func);
1007 :
1008 68 : if (zend_hash_find(EG(function_table), p->orig_func, strlen(p->orig_func)+1, (void **)&orig) != SUCCESS) {
1009 0 : php_error_docref("ref.mbstring" TSRMLS_CC, E_WARNING, "mbstring couldn't find function %s.", p->orig_func);
1010 0 : return FAILURE;
1011 : } else {
1012 68 : zend_hash_add(EG(function_table), p->save_func, strlen(p->save_func)+1, orig, sizeof(zend_function), NULL);
1013 :
1014 68 : if (zend_hash_update(EG(function_table), p->orig_func, strlen(p->orig_func)+1, func, sizeof(zend_function),
1015 : NULL) == FAILURE) {
1016 0 : php_error_docref("ref.mbstring" TSRMLS_CC, E_WARNING, "mbstring couldn't replace function %s.", p->orig_func);
1017 0 : return FAILURE;
1018 : }
1019 : }
1020 : }
1021 72 : p++;
1022 : }
1023 : }
1024 : #if HAVE_MBREGEX
1025 13551 : PHP_RINIT(mb_regex) (INIT_FUNC_ARGS_PASSTHRU);
1026 : #endif
1027 : #ifdef ZEND_MULTIBYTE
1028 : php_mb_set_zend_encoding(TSRMLS_C);
1029 : #endif /* ZEND_MULTIBYTE */
1030 :
1031 13551 : return SUCCESS;
1032 : }
1033 : /* }}} */
1034 :
1035 : /* {{{ PHP_RSHUTDOWN_FUNCTION(mbstring) */
1036 : PHP_RSHUTDOWN_FUNCTION(mbstring)
1037 13584 : {
1038 : const struct mb_overload_def *p;
1039 : zend_function *orig;
1040 :
1041 13584 : if (MBSTRG(current_detect_order_list) != NULL) {
1042 13584 : efree(MBSTRG(current_detect_order_list));
1043 13584 : MBSTRG(current_detect_order_list) = NULL;
1044 13584 : MBSTRG(current_detect_order_list_size) = 0;
1045 : }
1046 13584 : if (MBSTRG(outconv) != NULL) {
1047 0 : MBSTRG(illegalchars) += mbfl_buffer_illegalchars(MBSTRG(outconv));
1048 0 : mbfl_buffer_converter_delete(MBSTRG(outconv));
1049 0 : MBSTRG(outconv) = NULL;
1050 : }
1051 :
1052 : /* clear http input identification. */
1053 13584 : MBSTRG(http_input_identify) = mbfl_no_encoding_invalid;
1054 13584 : MBSTRG(http_input_identify_post) = mbfl_no_encoding_invalid;
1055 13584 : MBSTRG(http_input_identify_get) = mbfl_no_encoding_invalid;
1056 13584 : MBSTRG(http_input_identify_cookie) = mbfl_no_encoding_invalid;
1057 13584 : MBSTRG(http_input_identify_string) = mbfl_no_encoding_invalid;
1058 :
1059 : /* clear overloaded function. */
1060 13584 : if (MBSTRG(func_overload)){
1061 4 : p = &(mb_ovld[0]);
1062 80 : while (p->type > 0) {
1063 72 : if ((MBSTRG(func_overload) & p->type) == p->type &&
1064 : zend_hash_find(EG(function_table), p->save_func,
1065 : strlen(p->save_func)+1, (void **)&orig) == SUCCESS) {
1066 :
1067 68 : zend_hash_update(EG(function_table), p->orig_func, strlen(p->orig_func)+1, orig, sizeof(zend_function), NULL);
1068 68 : zend_hash_del(EG(function_table), p->save_func, strlen(p->save_func)+1);
1069 : }
1070 72 : p++;
1071 : }
1072 : }
1073 :
1074 : #if HAVE_MBREGEX
1075 13584 : PHP_RSHUTDOWN(mb_regex) (INIT_FUNC_ARGS_PASSTHRU);
1076 : #endif
1077 :
1078 13584 : return SUCCESS;
1079 : }
1080 : /* }}} */
1081 :
1082 : /* {{{ PHP_MINFO_FUNCTION(mbstring) */
1083 : PHP_MINFO_FUNCTION(mbstring)
1084 6 : {
1085 6 : php_info_print_table_start();
1086 6 : php_info_print_table_row(2, "Multibyte Support", "enabled");
1087 6 : php_info_print_table_row(2, "Multibyte string engine", "libmbfl");
1088 6 : if (MBSTRG(encoding_translation)) {
1089 0 : php_info_print_table_row(2, "HTTP input encoding translation", "enabled");
1090 : }
1091 : #if defined(HAVE_MBREGEX)
1092 : {
1093 : char buf[32];
1094 6 : php_info_print_table_row(2, "Multibyte (japanese) regex support", "enabled");
1095 6 : snprintf(buf, sizeof(buf), "%d.%d.%d",
1096 : ONIGURUMA_VERSION_MAJOR,ONIGURUMA_VERSION_MINOR,ONIGURUMA_VERSION_TEENY);
1097 6 : php_info_print_table_row(2, "Multibyte regex (oniguruma) version", buf);
1098 : #ifdef USE_COMBINATION_EXPLOSION_CHECK
1099 6 : php_info_print_table_row(2, "Multibyte regex (oniguruma) backtrack check", "On");
1100 : #else /* USE_COMBINATION_EXPLOSION_CHECK */
1101 : php_info_print_table_row(2, "Multibyte regex (oniguruma) backtrack check", "Off");
1102 : #endif /* USE_COMBINATION_EXPLOSION_CHECK */
1103 : }
1104 : #endif
1105 6 : php_info_print_table_end();
1106 :
1107 6 : php_info_print_table_start();
1108 6 : php_info_print_table_header(1, "mbstring extension makes use of \"streamable kanji code filter and converter\", which is distributed under the GNU Lesser General Public License version 2.1.");
1109 6 : php_info_print_table_end();
1110 :
1111 6 : DISPLAY_INI_ENTRIES();
1112 6 : }
1113 : /* }}} */
1114 :
1115 : /* {{{ proto string mb_language([string language])
1116 : Sets the current language or Returns the current language as a string */
1117 : PHP_FUNCTION(mb_language)
1118 28 : {
1119 28 : char *name = NULL;
1120 28 : int name_len = 0;
1121 :
1122 28 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len) == FAILURE) {
1123 0 : return;
1124 : }
1125 28 : if (name == NULL) {
1126 14 : RETVAL_STRING((char *)mbfl_no_language2name(MBSTRG(language)), 1);
1127 : } else {
1128 14 : if (FAILURE == zend_alter_ini_entry(
1129 : "mbstring.language", sizeof("mbstring.language"),
1130 : name, name_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME)) {
1131 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown language \"%s\"", name);
1132 0 : RETVAL_FALSE;
1133 : } else {
1134 14 : RETVAL_TRUE;
1135 : }
1136 : }
1137 : }
1138 : /* }}} */
1139 :
1140 : /* {{{ proto string mb_internal_encoding([string encoding])
1141 : Sets the current internal encoding or Returns the current internal encoding as a string */
1142 : PHP_FUNCTION(mb_internal_encoding)
1143 313 : {
1144 313 : char *name = NULL;
1145 : int name_len;
1146 : enum mbfl_no_encoding no_encoding;
1147 :
1148 313 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len) == FAILURE) {
1149 4 : RETURN_FALSE;
1150 : }
1151 309 : if (name == NULL) {
1152 141 : name = (char *)mbfl_no_encoding2name(MBSTRG(current_internal_encoding));
1153 141 : if (name != NULL) {
1154 141 : RETURN_STRING(name, 1);
1155 : } else {
1156 0 : RETURN_FALSE;
1157 : }
1158 : } else {
1159 168 : no_encoding = mbfl_name2no_encoding(name);
1160 168 : if (no_encoding == mbfl_no_encoding_invalid) {
1161 21 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", name);
1162 21 : RETURN_FALSE;
1163 : } else {
1164 147 : MBSTRG(current_internal_encoding) = no_encoding;
1165 : #ifdef ZEND_MULTIBYTE
1166 : /* TODO: make independent from mbstring.encoding_translation? */
1167 : if (MBSTRG(encoding_translation)) {
1168 : zend_multibyte_set_internal_encoding(name, name_len TSRMLS_CC);
1169 : }
1170 : #endif /* ZEND_MULTIBYTE */
1171 147 : RETURN_TRUE;
1172 : }
1173 : }
1174 : }
1175 : /* }}} */
1176 :
1177 : /* {{{ proto mixed mb_http_input([string type])
1178 : Returns the input encoding */
1179 : PHP_FUNCTION(mb_http_input)
1180 2 : {
1181 2 : char *typ = NULL;
1182 : int typ_len;
1183 : int retname, n;
1184 : char *name, *list, *temp;
1185 : enum mbfl_no_encoding *entry;
1186 2 : enum mbfl_no_encoding result = mbfl_no_encoding_invalid;
1187 :
1188 2 : retname = 1;
1189 2 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &typ, &typ_len) == FAILURE) {
1190 0 : RETURN_FALSE;
1191 : }
1192 2 : if (typ == NULL) {
1193 1 : result = MBSTRG(http_input_identify);
1194 : } else {
1195 1 : switch (*typ) {
1196 : case 'G':
1197 : case 'g':
1198 0 : result = MBSTRG(http_input_identify_get);
1199 0 : break;
1200 : case 'P':
1201 : case 'p':
1202 0 : result = MBSTRG(http_input_identify_post);
1203 0 : break;
1204 : case 'C':
1205 : case 'c':
1206 0 : result = MBSTRG(http_input_identify_cookie);
1207 0 : break;
1208 : case 'S':
1209 : case 's':
1210 0 : result = MBSTRG(http_input_identify_string);
1211 0 : break;
1212 : case 'I':
1213 : case 'i':
1214 0 : array_init(return_value);
1215 0 : entry = MBSTRG(http_input_list);
1216 0 : n = MBSTRG(http_input_list_size);
1217 0 : while (n > 0) {
1218 0 : name = (char *)mbfl_no_encoding2name(*entry);
1219 0 : if (name) {
1220 0 : add_next_index_string(return_value, name, 1);
1221 : }
1222 0 : entry++;
1223 0 : n--;
1224 : }
1225 0 : retname = 0;
1226 0 : break;
1227 : case 'L':
1228 : case 'l':
1229 1 : entry = MBSTRG(http_input_list);
1230 1 : n = MBSTRG(http_input_list_size);
1231 1 : list = NULL;
1232 3 : while (n > 0) {
1233 1 : name = (char *)mbfl_no_encoding2name(*entry);
1234 1 : if (name) {
1235 1 : if (list) {
1236 0 : temp = list;
1237 0 : spprintf(&list, 0, "%s,%s", temp, name);
1238 0 : efree(temp);
1239 0 : if (!list) {
1240 0 : break;
1241 : }
1242 : } else {
1243 1 : list = estrdup(name);
1244 : }
1245 : }
1246 1 : entry++;
1247 1 : n--;
1248 : }
1249 1 : if (!list) {
1250 0 : RETURN_FALSE;
1251 : }
1252 1 : RETVAL_STRING(list, 0);
1253 1 : retname = 0;
1254 1 : break;
1255 : default:
1256 0 : result = MBSTRG(http_input_identify);
1257 : break;
1258 : }
1259 : }
1260 :
1261 2 : if (retname) {
1262 2 : if (result != mbfl_no_encoding_invalid &&
1263 : (name = (char *)mbfl_no_encoding2name(result)) != NULL) {
1264 1 : RETVAL_STRING(name, 1);
1265 : } else {
1266 0 : RETVAL_FALSE;
1267 : }
1268 : }
1269 : }
1270 : /* }}} */
1271 :
1272 : /* {{{ proto string mb_http_output([string encoding])
1273 : Sets the current output_encoding or returns the current output_encoding as a string */
1274 : PHP_FUNCTION(mb_http_output)
1275 18 : {
1276 18 : char *name = NULL;
1277 : int name_len;
1278 : enum mbfl_no_encoding no_encoding;
1279 :
1280 18 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", (char **)&name, &name_len) == FAILURE) {
1281 2 : RETURN_FALSE;
1282 : }
1283 :
1284 16 : if (name == NULL) {
1285 9 : name = (char *)mbfl_no_encoding2name(MBSTRG(current_http_output_encoding));
1286 9 : if (name != NULL) {
1287 9 : RETURN_STRING(name, 1);
1288 : } else {
1289 0 : RETURN_FALSE;
1290 : }
1291 : } else {
1292 7 : no_encoding = mbfl_name2no_encoding(name);
1293 7 : if (no_encoding == mbfl_no_encoding_invalid) {
1294 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", name);
1295 1 : RETURN_FALSE;
1296 : } else {
1297 6 : MBSTRG(current_http_output_encoding) = no_encoding;
1298 6 : RETURN_TRUE;
1299 : }
1300 : }
1301 : }
1302 : /* }}} */
1303 :
1304 : /* {{{ proto bool|array mb_detect_order([mixed encoding-list])
1305 : Sets the current detect_order or Return the current detect_order as a array */
1306 : PHP_FUNCTION(mb_detect_order)
1307 12 : {
1308 : zval **arg1;
1309 : int n, size;
1310 : enum mbfl_no_encoding *list, *entry;
1311 : char *name;
1312 :
1313 12 : if (ZEND_NUM_ARGS() == 0) {
1314 5 : array_init(return_value);
1315 5 : entry = MBSTRG(current_detect_order_list);
1316 5 : n = MBSTRG(current_detect_order_list_size);
1317 31 : while (n > 0) {
1318 21 : name = (char *)mbfl_no_encoding2name(*entry);
1319 21 : if (name) {
1320 21 : add_next_index_string(return_value, name, 1);
1321 : }
1322 21 : entry++;
1323 21 : n--;
1324 : }
1325 12 : } else if (ZEND_NUM_ARGS() == 1 && zend_get_parameters_ex(1, &arg1) != FAILURE) {
1326 7 : list = NULL;
1327 7 : size = 0;
1328 7 : switch (Z_TYPE_PP(arg1)) {
1329 : case IS_ARRAY:
1330 2 : if (!php_mb_parse_encoding_array(*arg1, &list, &size, 0 TSRMLS_CC)) {
1331 1 : if (list) {
1332 1 : efree(list);
1333 : }
1334 1 : RETURN_FALSE;
1335 : }
1336 1 : break;
1337 : default:
1338 5 : convert_to_string_ex(arg1);
1339 5 : if (!php_mb_parse_encoding_list(Z_STRVAL_PP(arg1), Z_STRLEN_PP(arg1), &list, &size, 0 TSRMLS_CC)) {
1340 1 : if (list) {
1341 0 : efree(list);
1342 : }
1343 1 : RETURN_FALSE;
1344 : }
1345 : break;
1346 : }
1347 5 : if (list == NULL) {
1348 0 : RETVAL_FALSE;
1349 : } else {
1350 5 : if (MBSTRG(current_detect_order_list)) {
1351 5 : efree(MBSTRG(current_detect_order_list));
1352 : }
1353 5 : MBSTRG(current_detect_order_list) = list;
1354 5 : MBSTRG(current_detect_order_list_size) = size;
1355 5 : RETVAL_TRUE;
1356 : }
1357 : } else {
1358 0 : WRONG_PARAM_COUNT;
1359 : }
1360 : }
1361 : /* }}} */
1362 :
1363 : /* {{{ proto mixed mb_substitute_character([mixed substchar])
1364 : Sets the current substitute_character or returns the current substitute_character */
1365 : PHP_FUNCTION(mb_substitute_character)
1366 50 : {
1367 : zval **arg1;
1368 :
1369 50 : if (ZEND_NUM_ARGS() == 0) {
1370 8 : if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
1371 2 : RETVAL_STRING("none", 1);
1372 6 : } else if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG) {
1373 1 : RETVAL_STRING("long", 1);
1374 5 : } else if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_ENTITY) {
1375 1 : RETVAL_STRING("entity", 1);
1376 : } else {
1377 4 : RETVAL_LONG(MBSTRG(current_filter_illegal_substchar));
1378 : }
1379 83 : } else if (ZEND_NUM_ARGS() == 1 && zend_get_parameters_ex(1, &arg1) != FAILURE) {
1380 41 : RETVAL_TRUE;
1381 41 : switch (Z_TYPE_PP(arg1)) {
1382 : case IS_STRING:
1383 13 : if (strcasecmp("none", Z_STRVAL_PP(arg1)) == 0) {
1384 3 : MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE;
1385 10 : } else if (strcasecmp("long", Z_STRVAL_PP(arg1)) == 0) {
1386 1 : MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG;
1387 9 : } else if (strcasecmp("entity", Z_STRVAL_PP(arg1)) == 0) {
1388 1 : MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_ENTITY;
1389 : } else {
1390 8 : convert_to_long_ex(arg1);
1391 8 : if (Z_LVAL_PP(arg1)< 0xffff && Z_LVAL_PP(arg1)> 0x0) {
1392 0 : MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
1393 0 : MBSTRG(current_filter_illegal_substchar) = Z_LVAL_PP(arg1);
1394 : } else {
1395 8 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown character.");
1396 8 : RETVAL_FALSE;
1397 : }
1398 : }
1399 13 : break;
1400 : default:
1401 28 : convert_to_long_ex(arg1);
1402 43 : if (Z_LVAL_PP(arg1)< 0xffff && Z_LVAL_PP(arg1)> 0x0) {
1403 15 : MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
1404 15 : MBSTRG(current_filter_illegal_substchar) = Z_LVAL_PP(arg1);
1405 : } else {
1406 13 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown character.");
1407 13 : RETVAL_FALSE;
1408 : }
1409 : break;
1410 : }
1411 : } else {
1412 1 : WRONG_PARAM_COUNT;
1413 : }
1414 : }
1415 : /* }}} */
1416 :
1417 : /* {{{ proto string mb_preferred_mime_name(string encoding)
1418 : Return the preferred MIME name (charset) as a string */
1419 : PHP_FUNCTION(mb_preferred_mime_name)
1420 10 : {
1421 : enum mbfl_no_encoding no_encoding;
1422 10 : char *name = NULL;
1423 : int name_len;
1424 :
1425 10 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
1426 0 : return;
1427 : } else {
1428 10 : no_encoding = mbfl_name2no_encoding(name);
1429 10 : if (no_encoding == mbfl_no_encoding_invalid) {
1430 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", name);
1431 1 : RETVAL_FALSE;
1432 : } else {
1433 9 : const char *preferred_name = mbfl_no2preferred_mime_name(no_encoding);
1434 9 : if (preferred_name == NULL || *preferred_name == '\0') {
1435 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "No MIME preferred name corresponding to \"%s\"", name);
1436 0 : RETVAL_FALSE;
1437 : } else {
1438 9 : RETVAL_STRING((char *)preferred_name, 1);
1439 : }
1440 : }
1441 : }
1442 : }
1443 : /* }}} */
1444 :
1445 : #define IS_SJIS1(c) ((((c)>=0x81 && (c)<=0x9f) || ((c)>=0xe0 && (c)<=0xf5)) ? 1 : 0)
1446 : #define IS_SJIS2(c) ((((c)>=0x40 && (c)<=0x7e) || ((c)>=0x80 && (c)<=0xfc)) ? 1 : 0)
1447 :
1448 : /* {{{ proto bool mb_parse_str(string encoded_string [, array result])
1449 : Parses GET/POST/COOKIE data and sets global variables */
1450 : PHP_FUNCTION(mb_parse_str)
1451 16 : {
1452 16 : zval *track_vars_array = NULL;
1453 16 : char *encstr = NULL;
1454 : int encstr_len;
1455 : php_mb_encoding_handler_info_t info;
1456 : enum mbfl_no_encoding detected;
1457 :
1458 16 : track_vars_array = NULL;
1459 16 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &encstr, &encstr_len, &track_vars_array) == FAILURE) {
1460 0 : return;
1461 : }
1462 :
1463 : /* Clear out the array */
1464 16 : if (track_vars_array != NULL) {
1465 8 : zval_dtor(track_vars_array);
1466 8 : array_init(track_vars_array);
1467 : }
1468 :
1469 16 : encstr = estrndup(encstr, encstr_len);
1470 :
1471 16 : info.data_type = PARSE_STRING;
1472 16 : info.separator = PG(arg_separator).input;
1473 16 : info.force_register_globals = (track_vars_array == NULL);
1474 16 : info.report_errors = 1;
1475 16 : info.to_encoding = MBSTRG(current_internal_encoding);
1476 16 : info.to_language = MBSTRG(language);
1477 16 : info.from_encodings = MBSTRG(http_input_list);
1478 16 : info.num_from_encodings = MBSTRG(http_input_list_size);
1479 16 : info.from_language = MBSTRG(language);
1480 :
1481 16 : detected = _php_mb_encoding_handler_ex(&info, track_vars_array, encstr TSRMLS_CC);
1482 :
1483 16 : MBSTRG(http_input_identify) = detected;
1484 :
1485 16 : RETVAL_BOOL(detected != mbfl_no_encoding_invalid);
1486 :
1487 16 : if (encstr != NULL) efree(encstr);
1488 : }
1489 : /* }}} */
1490 :
1491 : /* {{{ proto string mb_output_handler(string contents, int status)
1492 : Returns string in output buffer converted to the http_output encoding */
1493 : PHP_FUNCTION(mb_output_handler)
1494 5 : {
1495 : char *arg_string;
1496 : int arg_string_len;
1497 : long arg_status;
1498 : mbfl_string string, result;
1499 : const char *charset;
1500 : char *p;
1501 : enum mbfl_no_encoding encoding;
1502 : int last_feed, len;
1503 5 : unsigned char send_text_mimetype = 0;
1504 5 : char *s, *mimetype = NULL;
1505 :
1506 5 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &arg_string, &arg_string_len, &arg_status) == FAILURE) {
1507 0 : return;
1508 : }
1509 :
1510 5 : encoding = MBSTRG(current_http_output_encoding);
1511 :
1512 : /* start phase only */
1513 5 : if ((arg_status & PHP_OUTPUT_HANDLER_START) != 0) {
1514 : /* delete the converter just in case. */
1515 5 : if (MBSTRG(outconv)) {
1516 0 : MBSTRG(illegalchars) += mbfl_buffer_illegalchars(MBSTRG(outconv));
1517 0 : mbfl_buffer_converter_delete(MBSTRG(outconv));
1518 0 : MBSTRG(outconv) = NULL;
1519 : }
1520 5 : if (encoding == mbfl_no_encoding_pass) {
1521 0 : RETURN_STRINGL(arg_string, arg_string_len, 1);
1522 : }
1523 :
1524 : /* analyze mime type */
1525 5 : if (SG(sapi_headers).mimetype &&
1526 : strncmp(SG(sapi_headers).mimetype, "text/", 5) == 0) {
1527 0 : if ((s = strchr(SG(sapi_headers).mimetype,';')) == NULL){
1528 0 : mimetype = estrdup(SG(sapi_headers).mimetype);
1529 : } else {
1530 0 : mimetype = estrndup(SG(sapi_headers).mimetype,s-SG(sapi_headers).mimetype);
1531 : }
1532 0 : send_text_mimetype = 1;
1533 5 : } else if (SG(sapi_headers).send_default_content_type) {
1534 5 : mimetype = SG(default_mimetype) ? SG(default_mimetype) : SAPI_DEFAULT_MIMETYPE;
1535 : }
1536 :
1537 : /* if content-type is not yet set, set it and activate the converter */
1538 5 : if (SG(sapi_headers).send_default_content_type || send_text_mimetype) {
1539 5 : charset = mbfl_no2preferred_mime_name(encoding);
1540 5 : if (charset) {
1541 5 : len = spprintf( &p, 0, "Content-Type: %s; charset=%s", mimetype, charset );
1542 5 : if (sapi_add_header(p, len, 0) != FAILURE) {
1543 5 : SG(sapi_headers).send_default_content_type = 0;
1544 : }
1545 : }
1546 : /* activate the converter */
1547 5 : MBSTRG(outconv) = mbfl_buffer_converter_new(MBSTRG(current_internal_encoding), encoding, 0);
1548 5 : if (send_text_mimetype){
1549 0 : efree(mimetype);
1550 : }
1551 : }
1552 : }
1553 :
1554 : /* just return if the converter is not activated. */
1555 5 : if (MBSTRG(outconv) == NULL) {
1556 0 : RETURN_STRINGL(arg_string, arg_string_len, 1);
1557 : }
1558 :
1559 : /* flag */
1560 5 : last_feed = ((arg_status & PHP_OUTPUT_HANDLER_END) != 0);
1561 : /* mode */
1562 5 : mbfl_buffer_converter_illegal_mode(MBSTRG(outconv), MBSTRG(current_filter_illegal_mode));
1563 5 : mbfl_buffer_converter_illegal_substchar(MBSTRG(outconv), MBSTRG(current_filter_illegal_substchar));
1564 :
1565 : /* feed the string */
1566 5 : mbfl_string_init(&string);
1567 5 : string.no_language = MBSTRG(language);
1568 5 : string.no_encoding = MBSTRG(current_internal_encoding);
1569 5 : string.val = (unsigned char *)arg_string;
1570 5 : string.len = arg_string_len;
1571 5 : mbfl_buffer_converter_feed(MBSTRG(outconv), &string);
1572 5 : if (last_feed) {
1573 5 : mbfl_buffer_converter_flush(MBSTRG(outconv));
1574 : }
1575 : /* get the converter output, and return it */
1576 5 : mbfl_buffer_converter_result(MBSTRG(outconv), &result);
1577 5 : RETVAL_STRINGL((char *)result.val, result.len, 0); /* the string is already strdup()'ed */
1578 :
1579 : /* delete the converter if it is the last feed. */
1580 5 : if (last_feed) {
1581 5 : MBSTRG(illegalchars) += mbfl_buffer_illegalchars(MBSTRG(outconv));
1582 5 : mbfl_buffer_converter_delete(MBSTRG(outconv));
1583 5 : MBSTRG(outconv) = NULL;
1584 : }
1585 : }
1586 : /* }}} */
1587 :
1588 : /* {{{ proto int mb_strlen(string str [, string encoding])
1589 : Get character numbers of a string */
1590 : PHP_FUNCTION(mb_strlen)
1591 225 : {
1592 : int n;
1593 : mbfl_string string;
1594 225 : char *enc_name = NULL;
1595 : int enc_name_len;
1596 :
1597 225 : mbfl_string_init(&string);
1598 :
1599 225 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", (char **)&string.val, &string.len, &enc_name, &enc_name_len) == FAILURE) {
1600 4 : RETURN_FALSE;
1601 : }
1602 :
1603 221 : string.no_language = MBSTRG(language);
1604 221 : if (enc_name == NULL) {
1605 3 : string.no_encoding = MBSTRG(current_internal_encoding);
1606 : } else {
1607 218 : string.no_encoding = mbfl_name2no_encoding(enc_name);
1608 218 : if (string.no_encoding == mbfl_no_encoding_invalid) {
1609 21 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
1610 21 : RETURN_FALSE;
1611 : }
1612 : }
1613 :
1614 200 : n = mbfl_strlen(&string);
1615 200 : if (n >= 0) {
1616 200 : RETVAL_LONG(n);
1617 : } else {
1618 0 : RETVAL_FALSE;
1619 : }
1620 : }
1621 : /* }}} */
1622 :
1623 : /* {{{ proto int mb_strpos(string haystack, string needle [, int offset [, string encoding]])
1624 : Find position of first occurrence of a string within another */
1625 : PHP_FUNCTION(mb_strpos)
1626 180 : {
1627 180 : int n, reverse = 0;
1628 : long offset;
1629 : mbfl_string haystack, needle;
1630 180 : char *enc_name = NULL;
1631 : int enc_name_len;
1632 :
1633 180 : mbfl_string_init(&haystack);
1634 180 : mbfl_string_init(&needle);
1635 180 : haystack.no_language = MBSTRG(language);
1636 180 : haystack.no_encoding = MBSTRG(current_internal_encoding);
1637 180 : needle.no_language = MBSTRG(language);
1638 180 : needle.no_encoding = MBSTRG(current_internal_encoding);
1639 180 : offset = 0;
1640 :
1641 180 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ls", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &offset, &enc_name, &enc_name_len) == FAILURE) {
1642 16 : RETURN_FALSE;
1643 : }
1644 :
1645 164 : if (enc_name != NULL) {
1646 123 : haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(enc_name);
1647 123 : if (haystack.no_encoding == mbfl_no_encoding_invalid) {
1648 20 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
1649 20 : RETURN_FALSE;
1650 : }
1651 : }
1652 :
1653 144 : if (offset < 0 || offset > mbfl_strlen(&haystack)) {
1654 32 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset not contained in string");
1655 32 : RETURN_FALSE;
1656 : }
1657 112 : if (needle.len == 0) {
1658 8 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter");
1659 8 : RETURN_FALSE;
1660 : }
1661 :
1662 104 : n = mbfl_strpos(&haystack, &needle, offset, reverse);
1663 104 : if (n >= 0) {
1664 51 : RETVAL_LONG(n);
1665 : } else {
1666 53 : switch (-n) {
1667 : case 1:
1668 53 : break;
1669 : case 2:
1670 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Needle has not positive length");
1671 0 : break;
1672 : case 4:
1673 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding or conversion error");
1674 0 : break;
1675 : case 8:
1676 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Argument is empty");
1677 0 : break;
1678 : default:
1679 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error in mb_strpos");
1680 : break;
1681 : }
1682 53 : RETVAL_FALSE;
1683 : }
1684 : }
1685 : /* }}} */
1686 :
1687 : /* {{{ proto int mb_strrpos(string haystack, string needle [, int offset [, string encoding]])
1688 : Find position of last occurrence of a string within another */
1689 : PHP_FUNCTION(mb_strrpos)
1690 120 : {
1691 : int n;
1692 : mbfl_string haystack, needle;
1693 120 : char *enc_name = NULL;
1694 : int enc_name_len;
1695 : zval **zoffset;
1696 120 : long offset = 0, str_flg;
1697 120 : char *enc_name2 = NULL;
1698 : int enc_name_len2;
1699 :
1700 120 : mbfl_string_init(&haystack);
1701 120 : mbfl_string_init(&needle);
1702 120 : haystack.no_language = MBSTRG(language);
1703 120 : haystack.no_encoding = MBSTRG(current_internal_encoding);
1704 120 : needle.no_language = MBSTRG(language);
1705 120 : needle.no_encoding = MBSTRG(current_internal_encoding);
1706 :
1707 120 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|Zs", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &zoffset, &enc_name, &enc_name_len) == FAILURE) {
1708 5 : RETURN_FALSE;
1709 : }
1710 :
1711 115 : if(ZEND_NUM_ARGS() >= 3) {
1712 112 : if (Z_TYPE_PP(zoffset) == IS_STRING) {
1713 6 : enc_name2 = Z_STRVAL_PP(zoffset);
1714 6 : enc_name_len2 = Z_STRLEN_PP(zoffset);
1715 6 : str_flg = 1;
1716 :
1717 6 : if (enc_name2 != NULL) {
1718 6 : switch (*enc_name2) {
1719 : case '0':
1720 : case '1':
1721 : case '2':
1722 : case '3':
1723 : case '4':
1724 : case '5':
1725 : case '6':
1726 : case '7':
1727 : case '8':
1728 : case '9':
1729 : case ' ':
1730 : case '-':
1731 : case '.':
1732 0 : break;
1733 : default :
1734 6 : str_flg = 0;
1735 : break;
1736 : }
1737 : }
1738 :
1739 6 : if(str_flg) {
1740 0 : convert_to_long_ex(zoffset);
1741 0 : offset = Z_LVAL_PP(zoffset);
1742 : } else {
1743 6 : enc_name = enc_name2;
1744 6 : enc_name_len = enc_name_len2;
1745 : }
1746 : } else {
1747 106 : convert_to_long_ex(zoffset);
1748 106 : offset = Z_LVAL_PP(zoffset);
1749 : }
1750 : }
1751 :
1752 115 : if (enc_name != NULL) {
1753 99 : haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(enc_name);
1754 99 : if (haystack.no_encoding == mbfl_no_encoding_invalid) {
1755 20 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
1756 20 : RETURN_FALSE;
1757 : }
1758 : }
1759 :
1760 95 : if (haystack.len <= 0) {
1761 8 : RETURN_FALSE;
1762 : }
1763 87 : if (needle.len <= 0) {
1764 8 : RETURN_FALSE;
1765 : }
1766 :
1767 : {
1768 79 : int haystack_char_len = mbfl_strlen(&haystack);
1769 79 : if ((offset > 0 && offset > haystack_char_len) ||
1770 : (offset < 0 && -offset > haystack_char_len)) {
1771 8 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset is greater than the length of haystack string");
1772 8 : RETURN_FALSE;
1773 : }
1774 : }
1775 :
1776 71 : n = mbfl_strpos(&haystack, &needle, offset, 1);
1777 71 : if (n >= 0) {
1778 41 : RETVAL_LONG(n);
1779 : } else {
1780 30 : RETVAL_FALSE;
1781 : }
1782 : }
1783 : /* }}} */
1784 :
1785 : /* {{{ proto int mb_stripos(string haystack, string needle [, int offset [, string encoding]])
1786 : Finds position of first occurrence of a string within another, case insensitive */
1787 : PHP_FUNCTION(mb_stripos)
1788 258 : {
1789 : int n;
1790 : long offset;
1791 : char *old_haystack, *old_needle;
1792 258 : char *from_encoding = (char*)mbfl_no2preferred_mime_name(MBSTRG(current_internal_encoding));
1793 : int old_haystack_len, old_needle_len, from_encoding_len;
1794 258 : n = -1;
1795 258 : offset = 0;
1796 :
1797 258 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ls", &old_haystack, &old_haystack_len, &old_needle, &old_needle_len, &offset, &from_encoding, &from_encoding_len ) == FAILURE) {
1798 16 : RETURN_FALSE;
1799 : }
1800 :
1801 242 : n = php_mb_stripos(0, old_haystack, old_haystack_len, old_needle, old_needle_len, offset, from_encoding TSRMLS_CC);
1802 :
1803 242 : if (n >= 0) {
1804 115 : RETVAL_LONG(n);
1805 : } else {
1806 127 : RETVAL_FALSE;
1807 : }
1808 : }
1809 : /* }}} */
1810 :
1811 : /* {{{ proto int mb_strripos(string haystack, string needle [, int offset [, string encoding]])
1812 : Finds position of last occurrence of a string within another, case insensitive */
1813 : PHP_FUNCTION(mb_strripos)
1814 220 : {
1815 : int n;
1816 : long offset;
1817 : char *old_haystack, *old_needle;
1818 220 : char *from_encoding = (char*)mbfl_no2preferred_mime_name(MBSTRG(current_internal_encoding));
1819 : int old_haystack_len, old_needle_len, from_encoding_len;
1820 220 : n = -1;
1821 220 : offset = 0;
1822 :
1823 220 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ls", &old_haystack, &old_haystack_len, &old_needle, &old_needle_len, &offset, &from_encoding, &from_encoding_len ) == FAILURE) {
1824 12 : RETURN_FALSE;
1825 : }
1826 :
1827 208 : n = php_mb_stripos(1, old_haystack, old_haystack_len, old_needle, old_needle_len, offset, from_encoding TSRMLS_CC);
1828 :
1829 208 : if (n >= 0) {
1830 80 : RETVAL_LONG(n);
1831 : } else {
1832 128 : RETVAL_FALSE;
1833 : }
1834 : }
1835 : /* }}} */
1836 :
1837 : /* {{{ proto string mb_strstr(string haystack, string needle[, bool part[, string encoding]])
1838 : Finds first occurrence of a string within another */
1839 : PHP_FUNCTION(mb_strstr)
1840 129 : {
1841 : int n, len, mblen;
1842 129 : mbfl_string haystack, needle, result, *ret = NULL;
1843 129 : char *enc_name = NULL;
1844 : int enc_name_len;
1845 129 : zend_bool part = 0;
1846 :
1847 129 : mbfl_string_init(&haystack);
1848 129 : mbfl_string_init(&needle);
1849 129 : haystack.no_language = MBSTRG(language);
1850 129 : haystack.no_encoding = MBSTRG(current_internal_encoding);
1851 129 : needle.no_language = MBSTRG(language);
1852 129 : needle.no_encoding = MBSTRG(current_internal_encoding);
1853 :
1854 129 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|bs", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &part, &enc_name, &enc_name_len) == FAILURE) {
1855 27 : RETURN_FALSE;
1856 : }
1857 :
1858 102 : if (enc_name != NULL) {
1859 86 : haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(enc_name);
1860 86 : if (haystack.no_encoding == mbfl_no_encoding_invalid) {
1861 21 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
1862 21 : RETURN_FALSE;
1863 : }
1864 : }
1865 :
1866 81 : if (needle.len <= 0) {
1867 8 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter");
1868 8 : RETURN_FALSE;
1869 : }
1870 73 : n = mbfl_strpos(&haystack, &needle, 0, 0);
1871 73 : if (n >= 0) {
1872 35 : mblen = mbfl_strlen(&haystack);
1873 35 : if (part) {
1874 18 : ret = mbfl_substr(&haystack, &result, 0, n);
1875 18 : if (ret != NULL) {
1876 18 : RETVAL_STRINGL((char *)ret->val, ret->len, 0);
1877 : } else {
1878 0 : RETVAL_FALSE;
1879 : }
1880 : } else {
1881 17 : len = (mblen - n);
1882 17 : ret = mbfl_substr(&haystack, &result, n, len);
1883 17 : if (ret != NULL) {
1884 17 : RETVAL_STRINGL((char *)ret->val, ret->len, 0);
1885 : } else {
1886 0 : RETVAL_FALSE;
1887 : }
1888 : }
1889 : } else {
1890 38 : RETVAL_FALSE;
1891 : }
1892 : }
1893 : /* }}} */
1894 :
1895 : /* {{{ proto string mb_strrchr(string haystack, string needle[, bool part[, string encoding]])
1896 : Finds the last occurrence of a character in a string within another */
1897 : PHP_FUNCTION(mb_strrchr)
1898 129 : {
1899 : int n, len, mblen;
1900 129 : mbfl_string haystack, needle, result, *ret = NULL;
1901 129 : char *enc_name = NULL;
1902 : int enc_name_len;
1903 129 : zend_bool part = 0;
1904 :
1905 129 : mbfl_string_init(&haystack);
1906 129 : mbfl_string_init(&needle);
1907 129 : haystack.no_language = MBSTRG(language);
1908 129 : haystack.no_encoding = MBSTRG(current_internal_encoding);
1909 129 : needle.no_language = MBSTRG(language);
1910 129 : needle.no_encoding = MBSTRG(current_internal_encoding);
1911 :
1912 129 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|bs", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &part, &enc_name, &enc_name_len) == FAILURE) {
1913 27 : RETURN_FALSE;
1914 : }
1915 :
1916 102 : if (enc_name != NULL) {
1917 86 : haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(enc_name);
1918 86 : if (haystack.no_encoding == mbfl_no_encoding_invalid) {
1919 21 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
1920 21 : RETURN_FALSE;
1921 : }
1922 : }
1923 :
1924 81 : if (haystack.len <= 0) {
1925 8 : RETURN_FALSE;
1926 : }
1927 73 : if (needle.len <= 0) {
1928 8 : RETURN_FALSE;
1929 : }
1930 65 : n = mbfl_strpos(&haystack, &needle, 0, 1);
1931 65 : if (n >= 0) {
1932 35 : mblen = mbfl_strlen(&haystack);
1933 35 : if (part) {
1934 18 : ret = mbfl_substr(&haystack, &result, 0, n);
1935 18 : if (ret != NULL) {
1936 18 : RETVAL_STRINGL((char *)ret->val, ret->len, 0);
1937 : } else {
1938 0 : RETVAL_FALSE;
1939 : }
1940 : } else {
1941 17 : len = (mblen - n);
1942 17 : ret = mbfl_substr(&haystack, &result, n, len);
1943 17 : if (ret != NULL) {
1944 17 : RETVAL_STRINGL((char *)ret->val, ret->len, 0);
1945 : } else {
1946 0 : RETVAL_FALSE;
1947 : }
1948 : }
1949 : } else {
1950 30 : RETVAL_FALSE;
1951 : }
1952 : }
1953 : /* }}} */
1954 :
1955 : /* {{{ proto string mb_stristr(string haystack, string needle[, bool part[, string encoding]])
1956 : Finds first occurrence of a string within another, case insensitive */
1957 : PHP_FUNCTION(mb_stristr)
1958 131 : {
1959 131 : zend_bool part = 0;
1960 : int n, from_encoding_len, len, mblen;
1961 131 : mbfl_string haystack, needle, result, *ret = NULL;
1962 131 : char *from_encoding = (char*)mbfl_no2preferred_mime_name(MBSTRG(current_internal_encoding));
1963 131 : mbfl_string_init(&haystack);
1964 131 : mbfl_string_init(&needle);
1965 131 : haystack.no_language = MBSTRG(language);
1966 131 : haystack.no_encoding = MBSTRG(current_internal_encoding);
1967 131 : needle.no_language = MBSTRG(language);
1968 131 : needle.no_encoding = MBSTRG(current_internal_encoding);
1969 :
1970 :
1971 131 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|bs", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &part, &from_encoding, &from_encoding_len) == FAILURE) {
1972 27 : RETURN_FALSE;
1973 : }
1974 :
1975 104 : if(!needle.len){
1976 8 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter");
1977 8 : RETURN_FALSE;
1978 : }
1979 :
1980 96 : haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(from_encoding);
1981 96 : if (haystack.no_encoding == mbfl_no_encoding_invalid) {
1982 21 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", from_encoding);
1983 21 : RETURN_FALSE;
1984 : }
1985 :
1986 75 : n = php_mb_stripos(0, haystack.val, haystack.len, needle.val, needle.len, 0, from_encoding TSRMLS_CC);
1987 :
1988 75 : if (n <0) {
1989 34 : RETURN_FALSE;
1990 : }
1991 :
1992 41 : mblen = mbfl_strlen(&haystack);
1993 :
1994 41 : if (part) {
1995 22 : ret = mbfl_substr(&haystack, &result, 0, n);
1996 22 : if (ret != NULL) {
1997 22 : RETVAL_STRINGL((char *)ret->val, ret->len, 0);
1998 : } else {
1999 0 : RETVAL_FALSE;
2000 : }
2001 : } else {
2002 19 : len = (mblen - n);
2003 19 : ret = mbfl_substr(&haystack, &result, n, len);
2004 19 : if (ret != NULL) {
2005 19 : RETVAL_STRINGL((char *)ret->val, ret->len, 0);
2006 : } else {
2007 0 : RETVAL_FALSE;
2008 : }
2009 : }
2010 : }
2011 : /* }}} */
2012 :
2013 : /* {{{ proto string mb_strrichr(string haystack, string needle[, bool part[, string encoding]])
2014 : Finds the last occurrence of a character in a string within another, case insensitive */
2015 : PHP_FUNCTION(mb_strrichr)
2016 131 : {
2017 131 : zend_bool part = 0;
2018 : int n, from_encoding_len, len, mblen;
2019 131 : mbfl_string haystack, needle, result, *ret = NULL;
2020 131 : char *from_encoding = (char*)mbfl_no2preferred_mime_name(MBSTRG(current_internal_encoding));
2021 131 : mbfl_string_init(&haystack);
2022 131 : mbfl_string_init(&needle);
2023 131 : haystack.no_language = MBSTRG(language);
2024 131 : haystack.no_encoding = MBSTRG(current_internal_encoding);
2025 131 : needle.no_language = MBSTRG(language);
2026 131 : needle.no_encoding = MBSTRG(current_internal_encoding);
2027 :
2028 :
2029 131 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|bs", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &part, &from_encoding, &from_encoding_len) == FAILURE) {
2030 27 : RETURN_FALSE;
2031 : }
2032 :
2033 104 : haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(from_encoding);
2034 104 : if (haystack.no_encoding == mbfl_no_encoding_invalid) {
2035 21 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", from_encoding);
2036 21 : RETURN_FALSE;
2037 : }
2038 :
2039 83 : n = php_mb_stripos(1, haystack.val, haystack.len, needle.val, needle.len, 0, from_encoding TSRMLS_CC);
2040 :
2041 83 : if (n <0) {
2042 42 : RETURN_FALSE;
2043 : }
2044 :
2045 41 : mblen = mbfl_strlen(&haystack);
2046 :
2047 41 : if (part) {
2048 22 : ret = mbfl_substr(&haystack, &result, 0, n);
2049 22 : if (ret != NULL) {
2050 22 : RETVAL_STRINGL((char *)ret->val, ret->len, 0);
2051 : } else {
2052 0 : RETVAL_FALSE;
2053 : }
2054 : } else {
2055 19 : len = (mblen - n);
2056 19 : ret = mbfl_substr(&haystack, &result, n, len);
2057 19 : if (ret != NULL) {
2058 19 : RETVAL_STRINGL((char *)ret->val, ret->len, 0);
2059 : } else {
2060 0 : RETVAL_FALSE;
2061 : }
2062 : }
2063 : }
2064 : /* }}} */
2065 :
2066 : /* {{{ proto int mb_substr_count(string haystack, string needle [, string encoding])
2067 : Count the number of substring occurrences */
2068 : PHP_FUNCTION(mb_substr_count)
2069 100 : {
2070 : int n;
2071 : mbfl_string haystack, needle;
2072 100 : char *enc_name = NULL;
2073 : int enc_name_len;
2074 :
2075 100 : mbfl_string_init(&haystack);
2076 100 : mbfl_string_init(&needle);
2077 100 : haystack.no_language = MBSTRG(language);
2078 100 : haystack.no_encoding = MBSTRG(current_internal_encoding);
2079 100 : needle.no_language = MBSTRG(language);
2080 100 : needle.no_encoding = MBSTRG(current_internal_encoding);
2081 :
2082 100 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &enc_name, &enc_name_len) == FAILURE) {
2083 5 : return;
2084 : }
2085 :
2086 95 : if (enc_name != NULL) {
2087 27 : haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(enc_name);
2088 27 : if (haystack.no_encoding == mbfl_no_encoding_invalid) {
2089 20 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
2090 20 : RETURN_FALSE;
2091 : }
2092 : }
2093 :
2094 75 : if (needle.len <= 0) {
2095 10 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty substring");
2096 10 : RETURN_FALSE;
2097 : }
2098 :
2099 65 : n = mbfl_substr_count(&haystack, &needle);
2100 65 : if (n >= 0) {
2101 65 : RETVAL_LONG(n);
2102 : } else {
2103 0 : RETVAL_FALSE;
2104 : }
2105 : }
2106 : /* }}} */
2107 :
2108 : /* {{{ proto string mb_substr(string str, int start [, int length [, string encoding]])
2109 : Returns part of a string */
2110 : PHP_FUNCTION(mb_substr)
2111 275 : {
2112 : zval **arg1, **arg2, **arg3, **arg4;
2113 : int argc, from, len, mblen;
2114 : mbfl_string string, result, *ret;
2115 :
2116 275 : mbfl_string_init(&string);
2117 275 : string.no_language = MBSTRG(language);
2118 275 : string.no_encoding = MBSTRG(current_internal_encoding);
2119 :
2120 275 : argc = ZEND_NUM_ARGS();
2121 275 : switch (argc) {
2122 : case 2:
2123 1 : if (zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
2124 0 : WRONG_PARAM_COUNT;
2125 : }
2126 1 : break;
2127 : case 3:
2128 77 : if (zend_get_parameters_ex(3, &arg1, &arg2, &arg3) == FAILURE) {
2129 0 : WRONG_PARAM_COUNT;
2130 : }
2131 77 : break;
2132 : case 4:
2133 195 : if (zend_get_parameters_ex(4, &arg1, &arg2, &arg3, &arg4) == FAILURE) {
2134 0 : WRONG_PARAM_COUNT;
2135 : }
2136 195 : convert_to_string_ex(arg4);
2137 195 : string.no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(arg4));
2138 195 : if (string.no_encoding == mbfl_no_encoding_invalid) {
2139 21 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", Z_STRVAL_PP(arg4));
2140 21 : RETURN_FALSE;
2141 : }
2142 174 : break;
2143 : default:
2144 2 : WRONG_PARAM_COUNT;
2145 : }
2146 :
2147 252 : convert_to_string_ex(arg1);
2148 252 : string.val = (unsigned char *)Z_STRVAL_PP(arg1);
2149 252 : string.len = Z_STRLEN_PP(arg1);
2150 :
2151 252 : convert_to_long_ex(arg2);
2152 252 : from = Z_LVAL_PP(arg2);
2153 252 : if (argc >= 3) {
2154 251 : convert_to_long_ex(arg3);
2155 251 : len = Z_LVAL_PP(arg3);
2156 : } else {
2157 1 : len = Z_STRLEN_PP(arg1);
2158 : }
2159 :
2160 : /* measures length */
2161 252 : mblen = 0;
2162 252 : if (from < 0 || len < 0) {
2163 49 : mblen = mbfl_strlen(&string);
2164 : }
2165 :
2166 : /* if "from" position is negative, count start position from the end
2167 : * of the string
2168 : */
2169 252 : if (from < 0) {
2170 25 : from = mblen + from;
2171 25 : if (from < 0) {
2172 17 : from = 0;
2173 : }
2174 : }
2175 :
2176 : /* if "length" position is negative, set it to the length
2177 : * needed to stop that many chars from the end of the string
2178 : */
2179 252 : if (len < 0) {
2180 24 : len = (mblen - from) + len;
2181 24 : if (len < 0) {
2182 16 : len = 0;
2183 : }
2184 : }
2185 :
2186 252 : if (((MBSTRG(func_overload) & MB_OVERLOAD_STRING) == MB_OVERLOAD_STRING)
2187 : && (from >= mbfl_strlen(&string))) {
2188 0 : RETURN_FALSE;
2189 : }
2190 :
2191 252 : ret = mbfl_substr(&string, &result, from, len);
2192 252 : if (ret != NULL) {
2193 252 : RETVAL_STRINGL((char *)ret->val, ret->len, 0); /* the string is already strdup()'ed */
2194 : } else {
2195 0 : RETVAL_FALSE;
2196 : }
2197 : }
2198 : /* }}} */
2199 :
2200 : /* {{{ proto string mb_strcut(string str, int start [, int length [, string encoding]])
2201 : Returns part of a string */
2202 : PHP_FUNCTION(mb_strcut)
2203 10 : {
2204 : zval **arg1, **arg2, **arg3, **arg4;
2205 : int argc, from, len;
2206 : mbfl_string string, result, *ret;
2207 :
2208 10 : mbfl_string_init(&string);
2209 10 : string.no_language = MBSTRG(language);
2210 10 : string.no_encoding = MBSTRG(current_internal_encoding);
2211 :
2212 10 : argc = ZEND_NUM_ARGS();
2213 10 : switch (argc) {
2214 : case 2:
2215 0 : if (zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) {
2216 0 : WRONG_PARAM_COUNT;
2217 : }
2218 0 : break;
2219 : case 3:
2220 0 : if (zend_get_parameters_ex(3, &arg1, &arg2, &arg3) == FAILURE) {
2221 0 : WRONG_PARAM_COUNT;
2222 : }
2223 0 : break;
2224 : case 4:
2225 10 : if (zend_get_parameters_ex(4, &arg1, &arg2, &arg3, &arg4) == FAILURE) {
2226 0 : WRONG_PARAM_COUNT;
2227 : }
2228 10 : convert_to_string_ex(arg4);
2229 10 : string.no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(arg4));
2230 10 : if (string.no_encoding == mbfl_no_encoding_invalid) {
2231 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", Z_STRVAL_PP(arg4));
2232 0 : RETURN_FALSE;
2233 : }
2234 10 : break;
2235 : default:
2236 0 : WRONG_PARAM_COUNT;
2237 : }
2238 :
2239 10 : convert_to_string_ex(arg1);
2240 10 : string.val = Z_STRVAL_PP(arg1);
2241 10 : string.len = Z_STRLEN_PP(arg1);
2242 :
2243 10 : convert_to_long_ex(arg2);
2244 10 : from = Z_LVAL_PP(arg2);
2245 10 : if (argc >= 3) {
2246 10 : convert_to_long_ex(arg3);
2247 10 : len = Z_LVAL_PP(arg3);
2248 : } else {
2249 0 : len = Z_STRLEN_PP(arg1);
2250 : }
2251 :
2252 : /* if "from" position is negative, count start position from the end
2253 : * of the string
2254 : */
2255 10 : if (from < 0) {
2256 1 : from = Z_STRLEN_PP(arg1) + from;
2257 1 : if (from < 0) {
2258 1 : from = 0;
2259 : }
2260 : }
2261 :
2262 : /* if "length" position is negative, set it to the length
2263 : * needed to stop that many chars from the end of the string
2264 : */
2265 10 : if (len < 0) {
2266 0 : len = (Z_STRLEN_PP(arg1) - from) + len;
2267 0 : if (len < 0) {
2268 0 : len = 0;
2269 : }
2270 : }
2271 :
2272 10 : if (from > Z_STRLEN_PP(arg1)) {
2273 2 : RETURN_FALSE;
2274 : }
2275 :
2276 8 : ret = mbfl_strcut(&string, &result, from, len);
2277 8 : if (ret != NULL) {
2278 8 : RETVAL_STRINGL(ret->val, ret->len, 0); /* the string is already strdup()'ed */
2279 : } else {
2280 0 : RETVAL_FALSE;
2281 : }
2282 : }
2283 : /* }}} */
2284 :
2285 : /* {{{ proto int mb_strwidth(string str [, string encoding])
2286 : Gets terminal width of a string */
2287 : PHP_FUNCTION(mb_strwidth)
2288 8257 : {
2289 : int n;
2290 : mbfl_string string;
2291 8257 : char *enc_name = NULL;
2292 : int enc_name_len;
2293 :
2294 8257 : mbfl_string_init(&string);
2295 :
2296 8257 : string.no_language = MBSTRG(language);
2297 8257 : string.no_encoding = MBSTRG(current_internal_encoding);
2298 :
2299 8257 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", (char **)&string.val, &string.len, &enc_name, &enc_name_len) == FAILURE) {
2300 0 : return;
2301 : }
2302 :
2303 8257 : if (enc_name != NULL) {
2304 8257 : string.no_encoding = mbfl_name2no_encoding(enc_name);
2305 8257 : if (string.no_encoding == mbfl_no_encoding_invalid) {
2306 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
2307 0 : RETURN_FALSE;
2308 : }
2309 : }
2310 :
2311 8257 : n = mbfl_strwidth(&string);
2312 8257 : if (n >= 0) {
2313 8257 : RETVAL_LONG(n);
2314 : } else {
2315 0 : RETVAL_FALSE;
2316 : }
2317 : }
2318 : /* }}} */
2319 :
2320 : /* {{{ proto string mb_strimwidth(string str, int start, int width [, string trimmarker [, string encoding]])
2321 : Trim the string in terminal width */
2322 : PHP_FUNCTION(mb_strimwidth)
2323 8 : {
2324 : zval **arg1, **arg2, **arg3, **arg4, **arg5;
2325 : int from, width;
2326 : mbfl_string string, result, marker, *ret;
2327 :
2328 8 : mbfl_string_init(&string);
2329 8 : mbfl_string_init(&marker);
2330 8 : string.no_language = MBSTRG(language);
2331 8 : string.no_encoding = MBSTRG(current_internal_encoding);
2332 8 : marker.no_language = MBSTRG(language);
2333 8 : marker.no_encoding = MBSTRG(current_internal_encoding);
2334 8 : marker.val = NULL;
2335 8 : marker.len = 0;
2336 :
2337 8 : switch (ZEND_NUM_ARGS()) {
2338 : case 3:
2339 0 : if (zend_get_parameters_ex(3, &arg1, &arg2, &arg3) == FAILURE) {
2340 0 : WRONG_PARAM_COUNT;
2341 : }
2342 0 : break;
2343 : case 4:
2344 0 : if (zend_get_parameters_ex(4, &arg1, &arg2, &arg3, &arg4) == FAILURE) {
2345 0 : WRONG_PARAM_COUNT;
2346 : }
2347 0 : break;
2348 : case 5:
2349 8 : if (zend_get_parameters_ex(5, &arg1, &arg2, &arg3, &arg4, &arg5) == FAILURE) {
2350 0 : WRONG_PARAM_COUNT;
2351 : }
2352 8 : convert_to_string_ex(arg5);
2353 8 : string.no_encoding = marker.no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(arg5));
2354 8 : if (string.no_encoding == mbfl_no_encoding_invalid) {
2355 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", Z_STRVAL_PP(arg5));
2356 0 : RETURN_FALSE;
2357 : }
2358 8 : break;
2359 : default:
2360 0 : WRONG_PARAM_COUNT;
2361 : }
2362 :
2363 8 : convert_to_string_ex(arg1);
2364 8 : string.val = (unsigned char *)Z_STRVAL_PP(arg1);
2365 8 : string.len = Z_STRLEN_PP(arg1);
2366 :
2367 8 : convert_to_long_ex(arg2);
2368 8 : from = Z_LVAL_PP(arg2);
2369 8 : if (from < 0 || from > Z_STRLEN_PP(arg1)) {
2370 3 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Start position is out of range");
2371 3 : RETURN_FALSE;
2372 : }
2373 :
2374 5 : convert_to_long_ex(arg3);
2375 5 : width = Z_LVAL_PP(arg3);
2376 :
2377 5 : if (width < 0) {
2378 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Width is negative value");
2379 0 : RETURN_FALSE;
2380 : }
2381 :
2382 5 : if (ZEND_NUM_ARGS() >= 4) {
2383 5 : convert_to_string_ex(arg4);
2384 5 : marker.val = (unsigned char *)Z_STRVAL_PP(arg4);
2385 5 : marker.len = Z_STRLEN_PP(arg4);
2386 : }
2387 :
2388 5 : ret = mbfl_strimwidth(&string, &marker, &result, from, width);
2389 5 : if (ret != NULL) {
2390 5 : RETVAL_STRINGL((char *)ret->val, ret->len, 0); /* the string is already strdup()'ed */
2391 : } else {
2392 0 : RETVAL_FALSE;
2393 : }
2394 : }
2395 : /* }}} */
2396 :
2397 : /* {{{ MBSTRING_API char *php_mb_convert_encoding() */
2398 : MBSTRING_API char * php_mb_convert_encoding(char *input, size_t length, char *_to_encoding, char *_from_encodings, size_t *output_len TSRMLS_DC)
2399 2651 : {
2400 : mbfl_string string, result, *ret;
2401 : enum mbfl_no_encoding from_encoding, to_encoding;
2402 : mbfl_buffer_converter *convd;
2403 : int size, *list;
2404 2651 : char *output=NULL;
2405 :
2406 2651 : if (output_len) {
2407 2651 : *output_len = 0;
2408 : }
2409 2651 : if (!input) {
2410 0 : return NULL;
2411 : }
2412 : /* new encoding */
2413 5280 : if (_to_encoding && strlen(_to_encoding)) {
2414 2643 : to_encoding = mbfl_name2no_encoding(_to_encoding);
2415 2643 : if (to_encoding == mbfl_no_encoding_invalid) {
2416 14 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", _to_encoding);
2417 14 : return NULL;
2418 : }
2419 : } else {
2420 8 : to_encoding = MBSTRG(current_internal_encoding);
2421 : }
2422 :
2423 : /* initialize string */
2424 2637 : mbfl_string_init(&string);
2425 2637 : mbfl_string_init(&result);
2426 2637 : from_encoding = MBSTRG(current_internal_encoding);
2427 2637 : string.no_encoding = from_encoding;
2428 2637 : string.no_language = MBSTRG(language);
2429 2637 : string.val = (unsigned char *)input;
2430 2637 : string.len = length;
2431 :
2432 : /* pre-conversion encoding */
2433 2637 : if (_from_encodings) {
2434 2626 : list = NULL;
2435 2626 : size = 0;
2436 2626 : php_mb_parse_encoding_list(_from_encodings, strlen(_from_encodings), &list, &size, 0 TSRMLS_CC);
2437 2626 : if (size == 1) {
2438 2617 : from_encoding = *list;
2439 2617 : string.no_encoding = from_encoding;
2440 9 : } else if (size > 1) {
2441 : /* auto detect */
2442 9 : from_encoding = mbfl_identify_encoding_no(&string, list, size, MBSTRG(strict_detection));
2443 9 : if (from_encoding != mbfl_no_encoding_invalid) {
2444 9 : string.no_encoding = from_encoding;
2445 : } else {
2446 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to detect character encoding");
2447 0 : from_encoding = mbfl_no_encoding_pass;
2448 0 : to_encoding = from_encoding;
2449 0 : string.no_encoding = from_encoding;
2450 : }
2451 : } else {
2452 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal character encoding specified");
2453 : }
2454 2626 : if (list != NULL) {
2455 2626 : efree((void *)list);
2456 : }
2457 : }
2458 :
2459 : /* initialize converter */
2460 2637 : convd = mbfl_buffer_converter_new(from_encoding, to_encoding, string.len);
2461 2637 : if (convd == NULL) {
2462 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create character encoding converter");
2463 0 : return NULL;
2464 : }
2465 2637 : mbfl_buffer_converter_illegal_mode(convd, MBSTRG(current_filter_illegal_mode));
2466 2637 : mbfl_buffer_converter_illegal_substchar(convd, MBSTRG(current_filter_illegal_substchar));
2467 :
2468 : /* do it */
2469 2637 : ret = mbfl_buffer_converter_feed_result(convd, &string, &result);
2470 2637 : if (ret) {
2471 2637 : if (output_len) {
2472 2637 : *output_len = ret->len;
2473 : }
2474 2637 : output = (char *)ret->val;
2475 : }
2476 :
2477 2637 : MBSTRG(illegalchars) += mbfl_buffer_illegalchars(convd);
2478 2637 : mbfl_buffer_converter_delete(convd);
2479 2637 : return output;
2480 : }
2481 : /* }}} */
2482 :
2483 : /* {{{ proto string mb_convert_encoding(string str, string to-encoding [, mixed from-encoding])
2484 : Returns converted string in desired encoding */
2485 : PHP_FUNCTION(mb_convert_encoding)
2486 292 : {
2487 : zval **arg_str, **arg_new, **arg_old;
2488 : int i;
2489 : size_t size, l, n;
2490 292 : char *_from_encodings, *ret, *s_free = NULL;
2491 :
2492 : zval **hash_entry;
2493 : HashTable *target_hash;
2494 :
2495 292 : _from_encodings = NULL;
2496 292 : if (ZEND_NUM_ARGS() == 2) {
2497 12 : if (zend_get_parameters_ex(2, &arg_str, &arg_new) == FAILURE) {
2498 0 : WRONG_PARAM_COUNT;
2499 : }
2500 280 : } else if (ZEND_NUM_ARGS() == 3) {
2501 279 : if (zend_get_parameters_ex(3, &arg_str, &arg_new, &arg_old) == FAILURE) {
2502 0 : WRONG_PARAM_COUNT;
2503 : }
2504 279 : switch (Z_TYPE_PP(arg_old)) {
2505 : case IS_ARRAY:
2506 :
2507 3 : target_hash = Z_ARRVAL_PP(arg_old);
2508 3 : zend_hash_internal_pointer_reset(target_hash);
2509 3 : i = zend_hash_num_elements(target_hash);
2510 3 : _from_encodings = NULL;
2511 18 : while (i > 0) {
2512 12 : if (zend_hash_get_current_data(target_hash, (void **) &hash_entry) == FAILURE) {
2513 0 : break;
2514 : }
2515 12 : convert_to_string_ex(hash_entry);
2516 12 : if ( _from_encodings) {
2517 9 : l = strlen(_from_encodings);
2518 9 : n = strlen(Z_STRVAL_PP(hash_entry));
2519 9 : _from_encodings = erealloc(_from_encodings, l+n+2);
2520 9 : strcpy(_from_encodings+l,",");
2521 9 : strcpy(_from_encodings+l+1,Z_STRVAL_PP(hash_entry));
2522 : } else {
2523 3 : _from_encodings = estrdup(Z_STRVAL_PP(hash_entry));
2524 : }
2525 12 : zend_hash_move_forward(target_hash);
2526 12 : i--;
2527 : }
2528 3 : if (_from_encodings != NULL && !strlen(_from_encodings)) {
2529 0 : efree(_from_encodings);
2530 0 : _from_encodings = NULL;
2531 : }
2532 3 : s_free = _from_encodings;
2533 3 : break;
2534 : default:
2535 276 : convert_to_string_ex(arg_old);
2536 276 : _from_encodings = Z_STRVAL_PP(arg_old);
2537 : break;
2538 : }
2539 : } else {
2540 1 : WRONG_PARAM_COUNT;
2541 : }
2542 :
2543 : /* new encoding */
2544 291 : convert_to_string_ex(arg_str);
2545 291 : convert_to_string_ex(arg_new);
2546 291 : ret = php_mb_convert_encoding( Z_STRVAL_PP(arg_str), Z_STRLEN_PP(arg_str), Z_STRVAL_PP(arg_new), _from_encodings, &size TSRMLS_CC);
2547 291 : if (ret != NULL) {
2548 277 : RETVAL_STRINGL(ret, size, 0); /* the string is already strdup()'ed */
2549 : } else {
2550 14 : RETVAL_FALSE;
2551 : }
2552 291 : if ( s_free) {
2553 3 : efree(s_free);
2554 : }
2555 : }
2556 : /* }}} */
2557 :
2558 : /* {{{ proto string mb_convert_case(string sourcestring, int mode [, string encoding])
2559 : Returns a case-folded version of sourcestring */
2560 : PHP_FUNCTION(mb_convert_case)
2561 1 : {
2562 1 : char *str, *from_encoding = (char*)mbfl_no2preferred_mime_name(MBSTRG(current_internal_encoding));
2563 : int str_len, from_encoding_len;
2564 1 : long case_mode = 0;
2565 : char *newstr;
2566 : size_t ret_len;
2567 :
2568 1 : RETVAL_FALSE;
2569 1 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|s!", &str, &str_len,
2570 : &case_mode, &from_encoding, &from_encoding_len) == FAILURE)
2571 0 : RETURN_FALSE;
2572 :
2573 1 : newstr = php_unicode_convert_case(case_mode, str, (size_t) str_len, &ret_len, from_encoding TSRMLS_CC);
2574 :
2575 1 : if (newstr) {
2576 1 : RETVAL_STRINGL(newstr, ret_len, 0);
2577 : }
2578 : }
2579 : /* }}} */
2580 :
2581 : /* {{{ proto string mb_strtoupper(string sourcestring [, string encoding])
2582 : * Returns a uppercased version of sourcestring
2583 : */
2584 : PHP_FUNCTION(mb_strtoupper)
2585 65 : {
2586 65 : char *str, *from_encoding = (char*)mbfl_no2preferred_mime_name(MBSTRG(current_internal_encoding));
2587 : int str_len, from_encoding_len;
2588 : char *newstr;
2589 : size_t ret_len;
2590 :
2591 65 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!", &str, &str_len,
2592 : &from_encoding, &from_encoding_len) == FAILURE) {
2593 4 : return;
2594 : }
2595 61 : newstr = php_unicode_convert_case(PHP_UNICODE_CASE_UPPER, str, (size_t) str_len, &ret_len, from_encoding TSRMLS_CC);
2596 :
2597 61 : if (newstr) {
2598 36 : RETURN_STRINGL(newstr, ret_len, 0);
2599 : }
2600 25 : RETURN_FALSE;
2601 : }
2602 : /* }}} */
2603 :
2604 : /* {{{ proto string mb_strtolower(string sourcestring [, string encoding])
2605 : * Returns a lowercased version of sourcestring
2606 : */
2607 : PHP_FUNCTION(mb_strtolower)
2608 65 : {
2609 65 : char *str, *from_encoding = (char*)mbfl_no2preferred_mime_name(MBSTRG(current_internal_encoding));
2610 : int str_len, from_encoding_len;
2611 : char *newstr;
2612 : size_t ret_len;
2613 :
2614 65 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!", &str, &str_len,
2615 : &from_encoding, &from_encoding_len) == FAILURE) {
2616 4 : return;
2617 : }
2618 61 : newstr = php_unicode_convert_case(PHP_UNICODE_CASE_LOWER, str, (size_t) str_len, &ret_len, from_encoding TSRMLS_CC);
2619 :
2620 61 : if (newstr) {
2621 36 : RETURN_STRINGL(newstr, ret_len, 0);
2622 : }
2623 25 : RETURN_FALSE;
2624 : }
2625 : /* }}} */
2626 :
2627 : /* {{{ proto string mb_detect_encoding(string str [, mixed encoding_list [, bool strict]])
2628 : Encodings of the given string is returned (as a string) */
2629 : PHP_FUNCTION(mb_detect_encoding)
2630 18 : {
2631 : zval **arg_str, **arg_list, **arg_strict;
2632 : mbfl_string string;
2633 : const char *ret;
2634 : enum mbfl_no_encoding *elist;
2635 18 : int size, *list, strict = 0;
2636 :
2637 18 : if (ZEND_NUM_ARGS() == 1) {
2638 3 : if (zend_get_parameters_ex(1, &arg_str) == FAILURE) {
2639 0 : WRONG_PARAM_COUNT;
2640 : }
2641 15 : } else if (ZEND_NUM_ARGS() == 2) {
2642 10 : if (zend_get_parameters_ex(2, &arg_str, &arg_list) == FAILURE) {
2643 0 : WRONG_PARAM_COUNT;
2644 : }
2645 5 : } else if (ZEND_NUM_ARGS() == 3) {
2646 4 : if (zend_get_parameters_ex(3, &arg_str, &arg_list, &arg_strict) == FAILURE) {
2647 0 : WRONG_PARAM_COUNT;
2648 : }
2649 : } else {
2650 1 : WRONG_PARAM_COUNT;
2651 : }
2652 :
2653 : /* make encoding list */
2654 17 : list = NULL;
2655 17 : size = 0;
2656 17 : if (ZEND_NUM_ARGS() >= 2 && Z_STRVAL_PP(arg_list)) {
2657 14 : switch (Z_TYPE_PP(arg_list)) {
2658 : case IS_ARRAY:
2659 3 : if (!php_mb_parse_encoding_array(*arg_list, &list, &size, 0 TSRMLS_CC)) {
2660 0 : if (list) {
2661 0 : efree(list);
2662 0 : list = NULL;
2663 0 : size = 0;
2664 : }
2665 : }
2666 3 : break;
2667 : default:
2668 11 : convert_to_string_ex(arg_list);
2669 11 : if (!php_mb_parse_encoding_list(Z_STRVAL_PP(arg_list), Z_STRLEN_PP(arg_list), &list, &size, 0 TSRMLS_CC)) {
2670 1 : if (list) {
2671 0 : efree(list);
2672 0 : list = NULL;
2673 0 : size = 0;
2674 : }
2675 : }
2676 : break;
2677 : }
2678 14 : if (size <= 0) {
2679 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal argument");
2680 : }
2681 : }
2682 :
2683 17 : if (ZEND_NUM_ARGS() == 3) {
2684 4 : convert_to_long_ex(arg_strict);
2685 4 : strict = Z_LVAL_PP(arg_strict);
2686 : }
2687 : else {
2688 13 : strict = MBSTRG(strict_detection);
2689 : }
2690 :
2691 30 : if (size > 0 && list != NULL) {
2692 13 : elist = list;
2693 : } else {
2694 4 : elist = MBSTRG(current_detect_order_list);
2695 4 : size = MBSTRG(current_detect_order_list_size);
2696 : }
2697 :
2698 17 : convert_to_string_ex(arg_str);
2699 17 : mbfl_string_init(&string);
2700 17 : string.no_language = MBSTRG(language);
2701 17 : string.val = (unsigned char *)Z_STRVAL_PP(arg_str);
2702 17 : string.len = Z_STRLEN_PP(arg_str);
2703 17 : ret = mbfl_identify_encoding_name(&string, elist, size, strict);
2704 17 : if (list != NULL) {
2705 13 : efree((void *)list);
2706 : }
2707 17 : if (ret != NULL) {
2708 15 : RETVAL_STRING((char *)ret, 1);
2709 : } else {
2710 2 : RETVAL_FALSE;
2711 : }
2712 : }
2713 : /* }}} */
2714 :
2715 : /* {{{ proto mixed mb_list_encodings()
2716 : Returns an array of all supported entity encodings */
2717 : PHP_FUNCTION(mb_list_encodings)
2718 0 : {
2719 : const mbfl_encoding **encodings;
2720 : const mbfl_encoding *encoding;
2721 : int i;
2722 :
2723 0 : array_init(return_value);
2724 0 : i = 0;
2725 0 : encodings = mbfl_get_supported_encodings();
2726 0 : while ((encoding = encodings[i++]) != NULL) {
2727 0 : add_next_index_string(return_value, (char *) encoding->name, 1);
2728 : }
2729 0 : }
2730 : /* }}} */
2731 :
2732 : /* {{{ proto string mb_encode_mimeheader(string str [, string charset [, string transfer-encoding [, string linefeed [, int indent]]]])
2733 : Converts the string to MIME "encoded-word" in the format of =?charset?(B|Q)?encoded_string?= */
2734 : PHP_FUNCTION(mb_encode_mimeheader)
2735 341 : {
2736 : enum mbfl_no_encoding charset, transenc;
2737 : mbfl_string string, result, *ret;
2738 341 : char *charset_name = NULL;
2739 : int charset_name_len;
2740 341 : char *trans_enc_name = NULL;
2741 : int trans_enc_name_len;
2742 341 : char *linefeed = "\r\n";
2743 : int linefeed_len;
2744 341 : long indent = 0;
2745 :
2746 341 : mbfl_string_init(&string);
2747 341 : string.no_language = MBSTRG(language);
2748 341 : string.no_encoding = MBSTRG(current_internal_encoding);
2749 :
2750 341 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sssl", (char **)&string.val, &string.len, &charset_name, &charset_name_len, &trans_enc_name, &trans_enc_name_len, &linefeed, &linefeed_len, &indent) == FAILURE) {
2751 11 : return;
2752 : }
2753 :
2754 330 : charset = mbfl_no_encoding_pass;
2755 330 : transenc = mbfl_no_encoding_base64;
2756 :
2757 330 : if (charset_name != NULL) {
2758 330 : charset = mbfl_name2no_encoding(charset_name);
2759 330 : if (charset == mbfl_no_encoding_invalid) {
2760 19 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", charset_name);
2761 19 : RETURN_FALSE;
2762 : }
2763 : } else {
2764 0 : const mbfl_language *lang = mbfl_no2language(MBSTRG(language));
2765 0 : if (lang != NULL) {
2766 0 : charset = lang->mail_charset;
2767 0 : transenc = lang->mail_header_encoding;
2768 : }
2769 : }
2770 :
2771 311 : if (trans_enc_name != NULL) {
2772 490 : if (*trans_enc_name == 'B' || *trans_enc_name == 'b') {
2773 179 : transenc = mbfl_no_encoding_base64;
2774 132 : } else if (*trans_enc_name == 'Q' || *trans_enc_name == 'q') {
2775 109 : transenc = mbfl_no_encoding_qprint;
2776 : }
2777 : }
2778 :
2779 311 : mbfl_string_init(&result);
2780 311 : ret = mbfl_mime_header_encode(&string, &result, charset, transenc, linefeed, indent);
2781 311 : if (ret != NULL) {
2782 311 : RETVAL_STRINGL((char *)ret->val, ret->len, 0) /* the string is already strdup()'ed */
2783 : } else {
2784 0 : RETVAL_FALSE;
2785 : }
2786 : }
2787 : /* }}} */
2788 :
2789 : /* {{{ proto string mb_decode_mimeheader(string string)
2790 : Decodes the MIME "encoded-word" in the string */
2791 : PHP_FUNCTION(mb_decode_mimeheader)
2792 39 : {
2793 : mbfl_string string, result, *ret;
2794 :
2795 39 : mbfl_string_init(&string);
2796 39 : string.no_language = MBSTRG(language);
2797 39 : string.no_encoding = MBSTRG(current_internal_encoding);
2798 :
2799 39 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", (char **)&string.val, &string.len) == FAILURE) {
2800 8 : return;
2801 : }
2802 :
2803 31 : mbfl_string_init(&result);
2804 31 : ret = mbfl_mime_header_decode(&string, &result, MBSTRG(current_internal_encoding));
2805 31 : if (ret != NULL) {
2806 31 : RETVAL_STRINGL((char *)ret->val, ret->len, 0) /* the string is already strdup()'ed */
2807 : } else {
2808 0 : RETVAL_FALSE;
2809 : }
2810 : }
2811 : /* }}} */
2812 :
2813 : /* {{{ proto string mb_convert_kana(string str [, string option] [, string encoding])
2814 : Conversion between full-width character and half-width character (Japanese) */
2815 : PHP_FUNCTION(mb_convert_kana)
2816 0 : {
2817 : int opt, i;
2818 : mbfl_string string, result, *ret;
2819 0 : char *optstr = NULL;
2820 : int optstr_len;
2821 0 : char *encname = NULL;
2822 : int encname_len;
2823 :
2824 0 : mbfl_string_init(&string);
2825 0 : string.no_language = MBSTRG(language);
2826 0 : string.no_encoding = MBSTRG(current_internal_encoding);
2827 :
2828 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ss", (char **)&string.val, &string.len, &optstr, &optstr_len, &encname, &encname_len) == FAILURE) {
2829 0 : return;
2830 : }
2831 :
2832 : /* option */
2833 0 : if (optstr != NULL) {
2834 0 : char *p = optstr;
2835 0 : int n = optstr_len;
2836 0 : i = 0;
2837 0 : opt = 0;
2838 0 : while (i < n) {
2839 0 : i++;
2840 0 : switch (*p++) {
2841 : case 'A':
2842 0 : opt |= 0x1;
2843 0 : break;
2844 : case 'a':
2845 0 : opt |= 0x10;
2846 0 : break;
2847 : case 'R':
2848 0 : opt |= 0x2;
2849 0 : break;
2850 : case 'r':
2851 0 : opt |= 0x20;
2852 0 : break;
2853 : case 'N':
2854 0 : opt |= 0x4;
2855 0 : break;
2856 : case 'n':
2857 0 : opt |= 0x40;
2858 0 : break;
2859 : case 'S':
2860 0 : opt |= 0x8;
2861 0 : break;
2862 : case 's':
2863 0 : opt |= 0x80;
2864 0 : break;
2865 : case 'K':
2866 0 : opt |= 0x100;
2867 0 : break;
2868 : case 'k':
2869 0 : opt |= 0x1000;
2870 0 : break;
2871 : case 'H':
2872 0 : opt |= 0x200;
2873 0 : break;
2874 : case 'h':
2875 0 : opt |= 0x2000;
2876 0 : break;
2877 : case 'V':
2878 0 : opt |= 0x800;
2879 0 : break;
2880 : case 'C':
2881 0 : opt |= 0x10000;
2882 0 : break;
2883 : case 'c':
2884 0 : opt |= 0x20000;
2885 0 : break;
2886 : case 'M':
2887 0 : opt |= 0x100000;
2888 0 : break;
2889 : case 'm':
2890 0 : opt |= 0x200000;
2891 : break;
2892 : }
2893 : }
2894 : } else {
2895 0 : opt = 0x900;
2896 : }
2897 :
2898 : /* encoding */
2899 0 : if (encname != NULL) {
2900 0 : string.no_encoding = mbfl_name2no_encoding(encname);
2901 0 : if (string.no_encoding == mbfl_no_encoding_invalid) {
2902 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", encname);
2903 0 : RETURN_FALSE;
2904 : }
2905 : }
2906 :
2907 0 : ret = mbfl_ja_jp_hantozen(&string, &result, opt);
2908 0 : if (ret != NULL) {
2909 0 : RETVAL_STRINGL((char *)ret->val, ret->len, 0); /* the string is already strdup()'ed */
2910 : } else {
2911 0 : RETVAL_FALSE;
2912 : }
2913 : }
2914 : /* }}} */
2915 :
2916 : #define PHP_MBSTR_STACK_BLOCK_SIZE 32
2917 :
2918 : /* {{{ proto string mb_convert_variables(string to-encoding, mixed from-encoding [, mixed ...])
2919 : Converts the string resource in variables to desired encoding */
2920 : PHP_FUNCTION(mb_convert_variables)
2921 17 : {
2922 : zval ***args, ***stack, **var, **hash_entry;
2923 : HashTable *target_hash;
2924 : mbfl_string string, result, *ret;
2925 : enum mbfl_no_encoding from_encoding, to_encoding;
2926 : mbfl_encoding_detector *identd;
2927 : mbfl_buffer_converter *convd;
2928 : int n, argc, stack_level, stack_max, elistsz;
2929 : enum mbfl_no_encoding *elist;
2930 : char *name;
2931 : void *ptmp;
2932 :
2933 17 : argc = ZEND_NUM_ARGS();
2934 17 : if (argc < 3) {
2935 0 : WRONG_PARAM_COUNT;
2936 : }
2937 17 : args = (zval ***)ecalloc(argc, sizeof(zval **));
2938 17 : if (zend_get_parameters_array_ex(argc, args) == FAILURE) {
2939 0 : efree((void *)args);
2940 0 : WRONG_PARAM_COUNT;
2941 : }
2942 :
2943 : /* new encoding */
2944 17 : convert_to_string_ex(args[0]);
2945 17 : to_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(args[0]));
2946 17 : if (to_encoding == mbfl_no_encoding_invalid) {
2947 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", Z_STRVAL_PP(args[0]));
2948 0 : efree((void *)args);
2949 0 : RETURN_FALSE;
2950 : }
2951 :
2952 : /* initialize string */
2953 17 : mbfl_string_init(&string);
2954 17 : mbfl_string_init(&result);
2955 17 : from_encoding = MBSTRG(current_internal_encoding);
2956 17 : string.no_encoding = from_encoding;
2957 17 : string.no_language = MBSTRG(language);
2958 :
2959 : /* pre-conversion encoding */
2960 17 : elist = NULL;
2961 17 : elistsz = 0;
2962 17 : switch (Z_TYPE_PP(args[1])) {
2963 : case IS_ARRAY:
2964 0 : php_mb_parse_encoding_array(*args[1], &elist, &elistsz, 0 TSRMLS_CC);
2965 0 : break;
2966 : default:
2967 17 : convert_to_string_ex(args[1]);
2968 17 : php_mb_parse_encoding_list(Z_STRVAL_PP(args[1]), Z_STRLEN_PP(args[1]), &elist, &elistsz, 0 TSRMLS_CC);
2969 : break;
2970 : }
2971 17 : if (elistsz <= 0) {
2972 0 : from_encoding = mbfl_no_encoding_pass;
2973 17 : } else if (elistsz == 1) {
2974 11 : from_encoding = *elist;
2975 : } else {
2976 : /* auto detect */
2977 6 : from_encoding = mbfl_no_encoding_invalid;
2978 6 : stack_max = PHP_MBSTR_STACK_BLOCK_SIZE;
2979 6 : stack = (zval ***)safe_emalloc(stack_max, sizeof(zval **), 0);
2980 6 : stack_level = 0;
2981 6 : identd = mbfl_encoding_detector_new(elist, elistsz, MBSTRG(strict_detection));
2982 6 : if (identd != NULL) {
2983 6 : n = 2;
2984 12 : while (n < argc || stack_level > 0) {
2985 6 : if (stack_level <= 0) {
2986 6 : var = args[n++];
2987 6 : if (Z_TYPE_PP(var) == IS_ARRAY || Z_TYPE_PP(var) == IS_OBJECT) {
2988 4 : target_hash = HASH_OF(*var);
2989 4 : if (target_hash != NULL) {
2990 4 : zend_hash_internal_pointer_reset(target_hash);
2991 : }
2992 : }
2993 : } else {
2994 0 : stack_level--;
2995 0 : var = stack[stack_level];
2996 : }
2997 6 : if (Z_TYPE_PP(var) == IS_ARRAY || Z_TYPE_PP(var) == IS_OBJECT) {
2998 4 : target_hash = HASH_OF(*var);
2999 4 : if (target_hash != NULL) {
3000 8 : while (zend_hash_get_current_data(target_hash, (void **) &hash_entry) != FAILURE) {
3001 4 : zend_hash_move_forward(target_hash);
3002 4 : if (Z_TYPE_PP(hash_entry) == IS_ARRAY || Z_TYPE_PP(hash_entry) == IS_OBJECT) {
3003 0 : if (stack_level >= stack_max) {
3004 0 : stack_max += PHP_MBSTR_STACK_BLOCK_SIZE;
3005 0 : ptmp = erealloc(stack, sizeof(zval **)*stack_max);
3006 0 : stack = (zval ***)ptmp;
3007 : }
3008 0 : stack[stack_level] = var;
3009 0 : stack_level++;
3010 0 : var = hash_entry;
3011 0 : target_hash = HASH_OF(*var);
3012 0 : if (target_hash != NULL) {
3013 0 : zend_hash_internal_pointer_reset(target_hash);
3014 0 : continue;
3015 : }
3016 4 : } else if (Z_TYPE_PP(hash_entry) == IS_STRING) {
3017 4 : string.val = (unsigned char *)Z_STRVAL_PP(hash_entry);
3018 4 : string.len = Z_STRLEN_PP(hash_entry);
3019 4 : if (mbfl_encoding_detector_feed(identd, &string)) {
3020 4 : goto detect_end; /* complete detecting */
3021 : }
3022 : }
3023 : }
3024 : }
3025 2 : } else if (Z_TYPE_PP(var) == IS_STRING) {
3026 2 : string.val = (unsigned char *)Z_STRVAL_PP(var);
3027 2 : string.len = Z_STRLEN_PP(var);
3028 2 : if (mbfl_encoding_detector_feed(identd, &string)) {
3029 2 : goto detect_end; /* complete detecting */
3030 : }
3031 : }
3032 : }
3033 6 : detect_end:
3034 6 : from_encoding = mbfl_encoding_detector_judge(identd);
3035 6 : mbfl_encoding_detector_delete(identd);
3036 : }
3037 6 : efree(stack);
3038 :
3039 6 : if (from_encoding == mbfl_no_encoding_invalid) {
3040 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to detect encoding");
3041 0 : from_encoding = mbfl_no_encoding_pass;
3042 : }
3043 : }
3044 17 : if (elist != NULL) {
3045 17 : efree((void *)elist);
3046 : }
3047 : /* create converter */
3048 17 : convd = NULL;
3049 17 : if (from_encoding != mbfl_no_encoding_pass) {
3050 17 : convd = mbfl_buffer_converter_new(from_encoding, to_encoding, 0);
3051 17 : if (convd == NULL) {
3052 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create converter");
3053 0 : RETURN_FALSE;
3054 : }
3055 17 : mbfl_buffer_converter_illegal_mode(convd, MBSTRG(current_filter_illegal_mode));
3056 17 : mbfl_buffer_converter_illegal_substchar(convd, MBSTRG(current_filter_illegal_substchar));
3057 : }
3058 :
3059 : /* convert */
3060 17 : if (convd != NULL) {
3061 17 : stack_max = PHP_MBSTR_STACK_BLOCK_SIZE;
3062 17 : stack = (zval ***)safe_emalloc(stack_max, sizeof(zval **), 0);
3063 17 : stack_level = 0;
3064 17 : n = 2;
3065 58 : while (n < argc || stack_level > 0) {
3066 24 : if (stack_level <= 0) {
3067 23 : var = args[n++];
3068 23 : if (Z_TYPE_PP(var) == IS_ARRAY || Z_TYPE_PP(var) == IS_OBJECT) {
3069 11 : target_hash = HASH_OF(*var);
3070 11 : if (target_hash != NULL) {
3071 11 : zend_hash_internal_pointer_reset(target_hash);
3072 : }
3073 : }
3074 : } else {
3075 1 : stack_level--;
3076 1 : var = stack[stack_level];
3077 : }
3078 36 : if (Z_TYPE_PP(var) == IS_ARRAY || Z_TYPE_PP(var) == IS_OBJECT) {
3079 12 : target_hash = HASH_OF(*var);
3080 12 : if (target_hash != NULL) {
3081 48 : while (zend_hash_get_current_data(target_hash, (void **) &hash_entry) != FAILURE) {
3082 24 : zend_hash_move_forward(target_hash);
3083 24 : if (Z_TYPE_PP(hash_entry) == IS_ARRAY || Z_TYPE_PP(hash_entry) == IS_OBJECT) {
3084 1 : if (stack_level >= stack_max) {
3085 0 : stack_max += PHP_MBSTR_STACK_BLOCK_SIZE;
3086 0 : ptmp = erealloc(stack, sizeof(zval **)*stack_max);
3087 0 : stack = (zval ***)ptmp;
3088 : }
3089 1 : stack[stack_level] = var;
3090 1 : stack_level++;
3091 1 : var = hash_entry;
3092 1 : SEPARATE_ZVAL(hash_entry);
3093 1 : target_hash = HASH_OF(*var);
3094 1 : if (target_hash != NULL) {
3095 1 : zend_hash_internal_pointer_reset(target_hash);
3096 1 : continue;
3097 : }
3098 23 : } else if (Z_TYPE_PP(hash_entry) == IS_STRING) {
3099 23 : string.val = (unsigned char *)Z_STRVAL_PP(hash_entry);
3100 23 : string.len = Z_STRLEN_PP(hash_entry);
3101 23 : ret = mbfl_buffer_converter_feed_result(convd, &string, &result);
3102 23 : if (ret != NULL) {
3103 23 : if ((*hash_entry)->refcount > 1) {
3104 14 : ZVAL_DELREF(*hash_entry);
3105 14 : MAKE_STD_ZVAL(*hash_entry);
3106 : } else {
3107 9 : zval_dtor(*hash_entry);
3108 : }
3109 23 : ZVAL_STRINGL(*hash_entry, ret->val, ret->len, 0);
3110 : }
3111 : }
3112 : }
3113 : }
3114 12 : } else if (Z_TYPE_PP(var) == IS_STRING) {
3115 12 : string.val = (unsigned char *)Z_STRVAL_PP(var);
3116 12 : string.len = Z_STRLEN_PP(var);
3117 12 : ret = mbfl_buffer_converter_feed_result(convd, &string, &result);
3118 12 : if (ret != NULL) {
3119 12 : zval_dtor(*var);
3120 12 : ZVAL_STRINGL(*var, ret->val, ret->len, 0);
3121 : }
3122 : }
3123 : }
3124 17 : efree(stack);
3125 :
3126 17 : MBSTRG(illegalchars) += mbfl_buffer_illegalchars(convd);
3127 17 : mbfl_buffer_converter_delete(convd);
3128 : }
3129 :
3130 17 : efree((void *)args);
3131 :
3132 17 : name = (char *)mbfl_no_encoding2name(from_encoding);
3133 17 : if (name != NULL) {
3134 17 : RETURN_STRING(name, 1);
3135 : } else {
3136 0 : RETURN_FALSE;
3137 : }
3138 : }
3139 : /* }}} */
3140 :
3141 : /* {{{ HTML numeric entity */
3142 : /* {{{ static void php_mb_numericentity_exec() */
3143 : static void
3144 : php_mb_numericentity_exec(INTERNAL_FUNCTION_PARAMETERS, int type)
3145 0 : {
3146 : zval **arg1, **arg2, **arg3, **hash_entry;
3147 : HashTable *target_hash;
3148 0 : int argc, i, *convmap, *mapelm, mapsize=0;
3149 : mbfl_string string, result, *ret;
3150 : enum mbfl_no_encoding no_encoding;
3151 :
3152 0 : argc = ZEND_NUM_ARGS();
3153 0 : if ((argc == 2 && zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) ||
3154 : (argc == 3 && zend_get_parameters_ex(3, &arg1, &arg2, &arg3) == FAILURE) ||
3155 : argc < 2 || argc > 3) {
3156 0 : WRONG_PARAM_COUNT;
3157 : }
3158 :
3159 0 : convert_to_string_ex(arg1);
3160 0 : mbfl_string_init(&string);
3161 0 : string.no_language = MBSTRG(language);
3162 0 : string.no_encoding = MBSTRG(current_internal_encoding);
3163 0 : string.val = (unsigned char *)Z_STRVAL_PP(arg1);
3164 0 : string.len = Z_STRLEN_PP(arg1);
3165 :
3166 : /* encoding */
3167 0 : if (argc == 3) {
3168 0 : convert_to_string_ex(arg3);
3169 0 : no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(arg3));
3170 0 : if (no_encoding == mbfl_no_encoding_invalid) {
3171 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", Z_STRVAL_PP(arg3));
3172 0 : RETURN_FALSE;
3173 : } else {
3174 0 : string.no_encoding = no_encoding;
3175 : }
3176 : }
3177 :
3178 : /* conversion map */
3179 0 : convmap = NULL;
3180 0 : if (Z_TYPE_PP(arg2) == IS_ARRAY){
3181 0 : target_hash = Z_ARRVAL_PP(arg2);
3182 0 : zend_hash_internal_pointer_reset(target_hash);
3183 0 : i = zend_hash_num_elements(target_hash);
3184 0 : if (i > 0) {
3185 0 : convmap = (int *)safe_emalloc(i, sizeof(int), 0);
3186 0 : mapelm = convmap;
3187 0 : mapsize = 0;
3188 0 : while (i > 0) {
3189 0 : if (zend_hash_get_current_data(target_hash, (void **) &hash_entry) == FAILURE) {
3190 0 : break;
3191 : }
3192 0 : convert_to_long_ex(hash_entry);
3193 0 : *mapelm++ = Z_LVAL_PP(hash_entry);
3194 0 : mapsize++;
3195 0 : i--;
3196 0 : zend_hash_move_forward(target_hash);
3197 : }
3198 : }
3199 : }
3200 0 : if (convmap == NULL) {
3201 0 : RETURN_FALSE;
3202 : }
3203 0 : mapsize /= 4;
3204 :
3205 0 : ret = mbfl_html_numeric_entity(&string, &result, convmap, mapsize, type);
3206 0 : if (ret != NULL) {
3207 0 : RETVAL_STRINGL((char *)ret->val, ret->len, 0);
3208 : } else {
3209 0 : RETVAL_FALSE;
3210 : }
3211 0 : efree((void *)convmap);
3212 : }
3213 : /* }}} */
3214 :
3215 : /* {{{ proto string mb_encode_numericentity(string string, array convmap [, string encoding])
3216 : Converts specified characters to HTML numeric entities */
3217 : PHP_FUNCTION(mb_encode_numericentity)
3218 0 : {
3219 0 : php_mb_numericentity_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
3220 0 : }
3221 : /* }}} */
3222 :
3223 : /* {{{ proto string mb_decode_numericentity(string string, array convmap [, string encoding])
3224 : Converts HTML numeric entities to character code */
3225 : PHP_FUNCTION(mb_decode_numericentity)
3226 0 : {
3227 0 : php_mb_numericentity_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
3228 0 : }
3229 : /* }}} */
3230 : /* }}} */
3231 :
3232 : /* {{{ proto int mb_send_mail(string to, string subject, string message [, string additional_headers [, string additional_parameters]])
3233 : * Sends an email message with MIME scheme
3234 : */
3235 :
3236 : #define SKIP_LONG_HEADER_SEP_MBSTRING(str, pos) \
3237 : if (str[pos] == '\r' && str[pos + 1] == '\n' && (str[pos + 2] == ' ' || str[pos + 2] == '\t')) { \
3238 : pos += 2; \
3239 : while (str[pos + 1] == ' ' || str[pos + 1] == '\t') { \
3240 : pos++; \
3241 : } \
3242 : continue; \
3243 : }
3244 :
3245 : #define MAIL_ASCIIZ_CHECK_MBSTRING(str, len) \
3246 : pp = str; \
3247 : ee = pp + len; \
3248 : while ((pp = memchr(pp, '\0', (ee - pp)))) { \
3249 : *pp = ' '; \
3250 : } \
3251 :
3252 : #define APPEND_ONE_CHAR(ch) do { \
3253 : if (token.a > 0) { \
3254 : smart_str_appendc(&token, ch); \
3255 : } else {\
3256 : token.len++; \
3257 : } \
3258 : } while (0)
3259 :
3260 : #define SEPARATE_SMART_STR(str) do {\
3261 : if ((str)->a == 0) { \
3262 : char *tmp_ptr; \
3263 : (str)->a = 1; \
3264 : while ((str)->a < (str)->len) { \
3265 : (str)->a <<= 1; \
3266 : } \
3267 : tmp_ptr = emalloc((str)->a + 1); \
3268 : memcpy(tmp_ptr, (str)->c, (str)->len); \
3269 : (str)->c = tmp_ptr; \
3270 : } \
3271 : } while (0)
3272 :
3273 : static void my_smart_str_dtor(smart_str *s)
3274 0 : {
3275 0 : if (s->a > 0) {
3276 0 : smart_str_free(s);
3277 : }
3278 0 : }
3279 :
3280 : static int _php_mbstr_parse_mail_headers(HashTable *ht, const char *str, size_t str_len)
3281 0 : {
3282 : const char *ps;
3283 : size_t icnt;
3284 0 : int state = 0;
3285 0 : int crlf_state = -1;
3286 :
3287 0 : smart_str token = { 0, 0, 0 };
3288 0 : smart_str fld_name = { 0, 0, 0 }, fld_val = { 0, 0, 0 };
3289 :
3290 0 : ps = str;
3291 0 : icnt = str_len;
3292 :
3293 : /*
3294 : * C o n t e n t - T y p e : t e x t / h t m l \r\n
3295 : * ^ ^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^^^^^^^^^^^^^^^ ^^^^
3296 : * state 0 1 2 3
3297 : *
3298 : * C o n t e n t - T y p e : t e x t / h t m l \r\n
3299 : * ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^
3300 : * crlf_state -1 0 1 -1
3301 : *
3302 : */
3303 :
3304 0 : while (icnt > 0) {
3305 0 : switch (*ps) {
3306 : case ':':
3307 0 : if (crlf_state == 1) {
3308 0 : APPEND_ONE_CHAR('\r');
3309 : }
3310 :
3311 0 : if (state == 0 || state == 1) {
3312 0 : fld_name = token;
3313 :
3314 0 : state = 2;
3315 : } else {
3316 0 : APPEND_ONE_CHAR(*ps);
3317 : }
3318 :
3319 0 : crlf_state = 0;
3320 0 : break;
3321 :
3322 : case '\n':
3323 0 : if (crlf_state == -1) {
3324 0 : goto out;
3325 : }
3326 0 : crlf_state = -1;
3327 0 : break;
3328 :
3329 : case '\r':
3330 0 : if (crlf_state == 1) {
3331 0 : APPEND_ONE_CHAR('\r');
3332 : } else {
3333 0 : crlf_state = 1;
3334 : }
3335 0 : break;
3336 :
3337 : case ' ': case '\t':
3338 0 : if (crlf_state == -1) {
3339 0 : if (state == 3) {
3340 : /* continuing from the previous line */
3341 0 : SEPARATE_SMART_STR(&token);
3342 0 : state = 4;
3343 : } else {
3344 : /* simply skipping this new line */
3345 0 : state = 5;
3346 : }
3347 : } else {
3348 0 : if (crlf_state == 1) {
3349 0 : APPEND_ONE_CHAR('\r');
3350 : }
3351 0 : if (state == 1 || state == 3) {
3352 0 : APPEND_ONE_CHAR(*ps);
3353 : }
3354 : }
3355 0 : crlf_state = 0;
3356 0 : break;
3357 :
3358 : default:
3359 0 : switch (state) {
3360 : case 0:
3361 0 : token.c = (char *)ps;
3362 0 : token.len = 0;
3363 0 : token.a = 0;
3364 0 : state = 1;
3365 0 : break;
3366 :
3367 : case 2:
3368 0 : if (crlf_state != -1) {
3369 0 : token.c = (char *)ps;
3370 0 : token.len = 0;
3371 0 : token.a = 0;
3372 :
3373 0 : state = 3;
3374 0 : break;
3375 : }
3376 : /* break is missing intentionally */
3377 :
3378 : case 3:
3379 0 : if (crlf_state == -1) {
3380 0 : fld_val = token;
3381 :
3382 0 : if (fld_name.c != NULL && fld_val.c != NULL) {
3383 : char *dummy;
3384 :
3385 : /* FIXME: some locale free implementation is
3386 : * really required here,,, */
3387 0 : SEPARATE_SMART_STR(&fld_name);
3388 0 : php_strtoupper(fld_name.c, fld_name.len);
3389 :
3390 0 : zend_hash_update(ht, (char *)fld_name.c, fld_name.len, &fld_val, sizeof(smart_str), (void **)&dummy);
3391 :
3392 0 : my_smart_str_dtor(&fld_name);
3393 : }
3394 :
3395 0 : memset(&fld_name, 0, sizeof(smart_str));
3396 0 : memset(&fld_val, 0, sizeof(smart_str));
3397 :
3398 0 : token.c = (char *)ps;
3399 0 : token.len = 0;
3400 0 : token.a = 0;
3401 :
3402 0 : state = 1;
3403 : }
3404 0 : break;
3405 :
3406 : case 4:
3407 0 : APPEND_ONE_CHAR(' ');
3408 0 : state = 3;
3409 : break;
3410 : }
3411 :
3412 0 : if (crlf_state == 1) {
3413 0 : APPEND_ONE_CHAR('\r');
3414 : }
3415 :
3416 0 : APPEND_ONE_CHAR(*ps);
3417 :
3418 0 : crlf_state = 0;
3419 : break;
3420 : }
3421 0 : ps++, icnt--;
3422 : }
3423 0 : out:
3424 0 : if (state == 2) {
3425 0 : token.c = "";
3426 0 : token.len = 0;
3427 0 : token.a = 0;
3428 :
3429 0 : state = 3;
3430 : }
3431 0 : if (state == 3) {
3432 0 : fld_val = token;
3433 :
3434 0 : if (fld_name.c != NULL && fld_val.c != NULL) {
3435 : void *dummy;
3436 :
3437 : /* FIXME: some locale free implementation is
3438 : * really required here,,, */
3439 0 : SEPARATE_SMART_STR(&fld_name);
3440 0 : php_strtoupper(fld_name.c, fld_name.len);
3441 :
3442 0 : zend_hash_update(ht, (char *)fld_name.c, fld_name.len, &fld_val, sizeof(smart_str), (void **)&dummy);
3443 :
3444 0 : my_smart_str_dtor(&fld_name);
3445 : }
3446 : }
3447 0 : return state;
3448 : }
3449 :
3450 : PHP_FUNCTION(mb_send_mail)
3451 14 : {
3452 : int n;
3453 14 : char *to=NULL;
3454 : int to_len;
3455 14 : char *message=NULL;
3456 : int message_len;
3457 14 : char *headers=NULL;
3458 : int headers_len;
3459 14 : char *subject=NULL;
3460 : int subject_len;
3461 14 : char *extra_cmd=NULL;
3462 : int extra_cmd_len;
3463 : int i;
3464 14 : char *to_r = NULL;
3465 14 : char *force_extra_parameters = INI_STR("mail.force_extra_parameters");
3466 : struct {
3467 : int cnt_type:1;
3468 : int cnt_trans_enc:1;
3469 14 : } suppressed_hdrs = { 0, 0 };
3470 :
3471 14 : char *message_buf=NULL, *subject_buf=NULL, *p;
3472 : mbfl_string orig_str, conv_str;
3473 : mbfl_string *pstr; /* pointer to mbfl string for return value */
3474 : enum mbfl_no_encoding
3475 : tran_cs, /* transfar text charset */
3476 : head_enc, /* header transfar encoding */
3477 : body_enc; /* body transfar encoding */
3478 : mbfl_memory_device device; /* automatic allocateable buffer for additional header */
3479 : const mbfl_language *lang;
3480 14 : int err = 0;
3481 : HashTable ht_headers;
3482 : smart_str *s;
3483 : extern void mbfl_memory_device_unput(mbfl_memory_device *device);
3484 : char *pp, *ee;
3485 :
3486 14 : if (PG(safe_mode) && (ZEND_NUM_ARGS() == 5)) {
3487 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "SAFE MODE Restriction in effect. The fifth parameter is disabled in SAFE MODE.");
3488 0 : RETURN_FALSE;
3489 : }
3490 :
3491 : /* initialize */
3492 14 : mbfl_memory_device_init(&device, 0, 0);
3493 14 : mbfl_string_init(&orig_str);
3494 14 : mbfl_string_init(&conv_str);
3495 :
3496 : /* character-set, transfer-encoding */
3497 14 : tran_cs = mbfl_no_encoding_utf8;
3498 14 : head_enc = mbfl_no_encoding_base64;
3499 14 : body_enc = mbfl_no_encoding_base64;
3500 14 : lang = mbfl_no2language(MBSTRG(language));
3501 14 : if (lang != NULL) {
3502 14 : tran_cs = lang->mail_charset;
3503 14 : head_enc = lang->mail_header_encoding;
3504 14 : body_enc = lang->mail_body_encoding;
3505 : }
3506 :
3507 14 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|ss", &to, &to_len, &subject, &subject_len, &message, &message_len, &headers, &headers_len, &extra_cmd, &extra_cmd_len) == FAILURE) {
3508 0 : return;
3509 : }
3510 :
3511 : /* ASCIIZ check */
3512 14 : MAIL_ASCIIZ_CHECK_MBSTRING(to, to_len);
3513 14 : MAIL_ASCIIZ_CHECK_MBSTRING(subject, subject_len);
3514 14 : MAIL_ASCIIZ_CHECK_MBSTRING(message, message_len);
3515 14 : if (headers) {
3516 0 : MAIL_ASCIIZ_CHECK_MBSTRING(headers, headers_len);
3517 : }
3518 14 : if (extra_cmd) {
3519 0 : MAIL_ASCIIZ_CHECK_MBSTRING(extra_cmd, extra_cmd_len);
3520 : }
3521 :
3522 14 : zend_hash_init(&ht_headers, 0, NULL, (dtor_func_t) my_smart_str_dtor, 0);
3523 :
3524 14 : if (headers != NULL) {
3525 0 : _php_mbstr_parse_mail_headers(&ht_headers, headers, headers_len);
3526 : }
3527 :
3528 14 : if (zend_hash_find(&ht_headers, "CONTENT-TYPE", sizeof("CONTENT-TYPE") - 1, (void **)&s) == SUCCESS) {
3529 : char *tmp;
3530 : char *param_name;
3531 0 : char *charset = NULL;
3532 :
3533 0 : SEPARATE_SMART_STR(s);
3534 0 : smart_str_0(s);
3535 :
3536 0 : p = strchr(s->c, ';');
3537 :
3538 0 : if (p != NULL) {
3539 : /* skipping the padded spaces */
3540 : do {
3541 0 : ++p;
3542 0 : } while (*p == ' ' || *p == '\t');
3543 :
3544 0 : if (*p != '\0') {
3545 0 : if ((param_name = php_strtok_r(p, "= ", &tmp)) != NULL) {
3546 0 : if (strcasecmp(param_name, "charset") == 0) {
3547 0 : enum mbfl_no_encoding _tran_cs = tran_cs;
3548 :
3549 0 : charset = php_strtok_r(NULL, "= \"", &tmp);
3550 0 : if (charset != NULL) {
3551 0 : _tran_cs = mbfl_name2no_encoding(charset);
3552 : }
3553 :
3554 0 : if (_tran_cs == mbfl_no_encoding_invalid) {
3555 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported charset \"%s\" - will be regarded as ascii", charset);
3556 0 : _tran_cs = mbfl_no_encoding_ascii;
3557 : }
3558 0 : tran_cs = _tran_cs;
3559 : }
3560 : }
3561 : }
3562 : }
3563 0 : suppressed_hdrs.cnt_type = 1;
3564 : }
3565 :
3566 14 : if (zend_hash_find(&ht_headers, "CONTENT-TRANSFER-ENCODING", sizeof("CONTENT-TRANSFER-ENCODING") - 1, (void **)&s) == SUCCESS) {
3567 : enum mbfl_no_encoding _body_enc;
3568 0 : SEPARATE_SMART_STR(s);
3569 0 : smart_str_0(s);
3570 :
3571 0 : _body_enc = mbfl_name2no_encoding(s->c);
3572 0 : switch (_body_enc) {
3573 : case mbfl_no_encoding_base64:
3574 : case mbfl_no_encoding_7bit:
3575 : case mbfl_no_encoding_8bit:
3576 0 : body_enc = _body_enc;
3577 0 : break;
3578 :
3579 : default:
3580 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported transfer encoding \"%s\" - will be regarded as 8bit", s->c);
3581 0 : body_enc = mbfl_no_encoding_8bit;
3582 : break;
3583 : }
3584 0 : suppressed_hdrs.cnt_trans_enc = 1;
3585 : }
3586 :
3587 : /* To: */
3588 14 : if (to != NULL) {
3589 14 : if (to_len > 0) {
3590 14 : to_r = estrndup(to, to_len);
3591 14 : for (; to_len; to_len--) {
3592 14 : if (!isspace((unsigned char) to_r[to_len - 1])) {
3593 14 : break;
3594 : }
3595 0 : to_r[to_len - 1] = '\0';
3596 : }
3597 280 : for (i = 0; to_r[i]; i++) {
3598 266 : if (iscntrl((unsigned char) to_r[i])) {
3599 : /* According to RFC 822, section 3.1.1 long headers may be separated into
3600 : * parts using CRLF followed at least one linear-white-space character ('\t' or ' ').
3601 : * To prevent these separators from being replaced with a space, we use the
3602 : * SKIP_LONG_HEADER_SEP_MBSTRING to skip over them.
3603 : */
3604 0 : SKIP_LONG_HEADER_SEP_MBSTRING(to_r, i);
3605 0 : to_r[i] = ' ';
3606 : }
3607 : }
3608 : } else {
3609 0 : to_r = to;
3610 : }
3611 : } else {
3612 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing To: field");
3613 0 : err = 1;
3614 : }
3615 :
3616 : /* Subject: */
3617 28 : if (subject != NULL && subject_len >= 0) {
3618 14 : orig_str.no_language = MBSTRG(language);
3619 14 : orig_str.val = (unsigned char *)subject;
3620 14 : orig_str.len = subject_len;
3621 14 : orig_str.no_encoding = MBSTRG(current_internal_encoding);
3622 14 : if (orig_str.no_encoding == mbfl_no_encoding_invalid
3623 : || orig_str.no_encoding == mbfl_no_encoding_pass) {
3624 1 : orig_str.no_encoding = mbfl_identify_encoding_no(&orig_str, MBSTRG(current_detect_order_list), MBSTRG(current_detect_order_list_size), MBSTRG(strict_detection));
3625 : }
3626 14 : pstr = mbfl_mime_header_encode(&orig_str, &conv_str, tran_cs, head_enc, "\n", sizeof("Subject: [PHP-jp nnnnnnnn]"));
3627 14 : if (pstr != NULL) {
3628 14 : subject_buf = subject = (char *)pstr->val;
3629 : }
3630 : } else {
3631 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing Subject: field");
3632 0 : err = 1;
3633 : }
3634 :
3635 : /* message body */
3636 14 : if (message != NULL) {
3637 14 : orig_str.no_language = MBSTRG(language);
3638 14 : orig_str.val = message;
3639 14 : orig_str.len = message_len;
3640 14 : orig_str.no_encoding = MBSTRG(current_internal_encoding);
3641 :
3642 14 : if (orig_str.no_encoding == mbfl_no_encoding_invalid
3643 : || orig_str.no_encoding == mbfl_no_encoding_pass) {
3644 1 : orig_str.no_encoding = mbfl_identify_encoding_no(&orig_str, MBSTRG(current_detect_order_list), MBSTRG(current_detect_order_list_size), MBSTRG(strict_detection));
3645 : }
3646 :
3647 14 : pstr = NULL;
3648 : {
3649 : mbfl_string tmpstr;
3650 :
3651 14 : if (mbfl_convert_encoding(&orig_str, &tmpstr, tran_cs) != NULL) {
3652 14 : tmpstr.no_encoding=mbfl_no_encoding_8bit;
3653 14 : pstr = mbfl_convert_encoding(&tmpstr, &conv_str, body_enc);
3654 14 : efree(tmpstr.val);
3655 : }
3656 : }
3657 14 : if (pstr != NULL) {
3658 14 : message_buf = message = (char *)pstr->val;
3659 : }
3660 : } else {
3661 : /* this is not really an error, so it is allowed. */
3662 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty message body");
3663 0 : message = NULL;
3664 : }
3665 :
3666 : /* other headers */
3667 : #define PHP_MBSTR_MAIL_MIME_HEADER1 "Mime-Version: 1.0"
3668 : #define PHP_MBSTR_MAIL_MIME_HEADER2 "Content-Type: text/plain"
3669 : #define PHP_MBSTR_MAIL_MIME_HEADER3 "; charset="
3670 : #define PHP_MBSTR_MAIL_MIME_HEADER4 "Content-Transfer-Encoding: "
3671 14 : if (headers != NULL) {
3672 0 : p = headers;
3673 0 : n = headers_len;
3674 0 : mbfl_memory_device_strncat(&device, p, n);
3675 0 : if (n > 0 && p[n - 1] != '\n') {
3676 0 : mbfl_memory_device_strncat(&device, "\n", 1);
3677 : }
3678 : }
3679 :
3680 14 : mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER1, sizeof(PHP_MBSTR_MAIL_MIME_HEADER1) - 1);
3681 14 : mbfl_memory_device_strncat(&device, "\n", 1);
3682 :
3683 14 : if (!suppressed_hdrs.cnt_type) {
3684 14 : mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER2, sizeof(PHP_MBSTR_MAIL_MIME_HEADER2) - 1);
3685 :
3686 14 : p = (char *)mbfl_no2preferred_mime_name(tran_cs);
3687 14 : if (p != NULL) {
3688 14 : mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER3, sizeof(PHP_MBSTR_MAIL_MIME_HEADER3) - 1);
3689 14 : mbfl_memory_device_strcat(&device, p);
3690 : }
3691 14 : mbfl_memory_device_strncat(&device, "\n", 1);
3692 : }
3693 14 : if (!suppressed_hdrs.cnt_trans_enc) {
3694 14 : mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER4, sizeof(PHP_MBSTR_MAIL_MIME_HEADER4) - 1);
3695 14 : p = (char *)mbfl_no2preferred_mime_name(body_enc);
3696 14 : if (p == NULL) {
3697 0 : p = "7bit";
3698 : }
3699 14 : mbfl_memory_device_strcat(&device, p);
3700 14 : mbfl_memory_device_strncat(&device, "\n", 1);
3701 : }
3702 :
3703 14 : mbfl_memory_device_unput(&device);
3704 14 : mbfl_memory_device_output('\0', &device);
3705 14 : headers = (char *)device.buffer;
3706 :
3707 14 : if (force_extra_parameters) {
3708 0 : extra_cmd = php_escape_shell_cmd(force_extra_parameters);
3709 14 : } else if (extra_cmd) {
3710 0 : extra_cmd = php_escape_shell_cmd(extra_cmd);
3711 : }
3712 :
3713 28 : if (!err && php_mail(to_r, subject, message, headers, extra_cmd TSRMLS_CC)) {
3714 14 : RETVAL_TRUE;
3715 : } else {
3716 0 : RETVAL_FALSE;
3717 : }
3718 :
3719 14 : if (extra_cmd) {
3720 0 : efree(extra_cmd);
3721 : }
3722 14 : if (to_r != to) {
3723 14 : efree(to_r);
3724 : }
3725 14 : if (subject_buf) {
3726 14 : efree((void *)subject_buf);
3727 : }
3728 14 : if (message_buf) {
3729 14 : efree((void *)message_buf);
3730 : }
3731 14 : mbfl_memory_device_clear(&device);
3732 14 : zend_hash_destroy(&ht_headers);
3733 : }
3734 :
3735 : #undef SKIP_LONG_HEADER_SEP_MBSTRING
3736 : #undef MAIL_ASCIIZ_CHECK_MBSTRING
3737 : #undef APPEND_ONE_CHAR
3738 : #undef SEPARATE_SMART_STR
3739 : #undef PHP_MBSTR_MAIL_MIME_HEADER1
3740 : #undef PHP_MBSTR_MAIL_MIME_HEADER2
3741 : #undef PHP_MBSTR_MAIL_MIME_HEADER3
3742 : #undef PHP_MBSTR_MAIL_MIME_HEADER4
3743 : /* }}} */
3744 :
3745 : /* {{{ proto mixed mb_get_info([string type])
3746 : Returns the current settings of mbstring */
3747 : PHP_FUNCTION(mb_get_info)
3748 0 : {
3749 0 : char *typ = NULL;
3750 : int typ_len, n;
3751 : char *name;
3752 : const struct mb_overload_def *over_func;
3753 : zval *row1, *row2;
3754 0 : const mbfl_language *lang = mbfl_no2language(MBSTRG(language));
3755 : enum mbfl_no_encoding *entry;
3756 : #ifdef ZEND_MULTIBYTE
3757 : zval *row3;
3758 : #endif /* ZEND_MULTIBYTE */
3759 :
3760 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &typ, &typ_len) == FAILURE) {
3761 0 : RETURN_FALSE;
3762 : }
3763 :
3764 0 : if (!typ || !strcasecmp("all", typ)) {
3765 0 : array_init(return_value);
3766 0 : if ((name = (char *)mbfl_no_encoding2name(MBSTRG(current_internal_encoding))) != NULL) {
3767 0 : add_assoc_string(return_value, "internal_encoding", name, 1);
3768 : }
3769 0 : if ((name = (char *)mbfl_no_encoding2name(MBSTRG(http_input_identify))) != NULL) {
3770 0 : add_assoc_string(return_value, "http_input", name, 1);
3771 : }
3772 0 : if ((name = (char *)mbfl_no_encoding2name(MBSTRG(current_http_output_encoding))) != NULL) {
3773 0 : add_assoc_string(return_value, "http_output", name, 1);
3774 : }
3775 0 : add_assoc_long(return_value, "func_overload", MBSTRG(func_overload));
3776 0 : if (MBSTRG(func_overload)){
3777 0 : over_func = &(mb_ovld[0]);
3778 0 : MAKE_STD_ZVAL(row1);
3779 0 : array_init(row1);
3780 0 : while (over_func->type > 0) {
3781 0 : if ((MBSTRG(func_overload) & over_func->type) == over_func->type ) {
3782 0 : add_assoc_string(row1, over_func->orig_func, over_func->ovld_func, 1);
3783 : }
3784 0 : over_func++;
3785 : }
3786 0 : add_assoc_zval(return_value, "func_overload_list", row1);
3787 : } else {
3788 0 : add_assoc_string(return_value, "func_overload_list", "no overload", 1);
3789 : }
3790 0 : if (lang != NULL) {
3791 0 : if ((name = (char *)mbfl_no_encoding2name(lang->mail_charset)) != NULL) {
3792 0 : add_assoc_string(return_value, "mail_charset", name, 1);
3793 : }
3794 0 : if ((name = (char *)mbfl_no_encoding2name(lang->mail_header_encoding)) != NULL) {
3795 0 : add_assoc_string(return_value, "mail_header_encoding", name, 1);
3796 : }
3797 0 : if ((name = (char *)mbfl_no_encoding2name(lang->mail_body_encoding)) != NULL) {
3798 0 : add_assoc_string(return_value, "mail_body_encoding", name, 1);
3799 : }
3800 : }
3801 0 : add_assoc_long(return_value, "illegal_chars", MBSTRG(illegalchars));
3802 0 : if (MBSTRG(encoding_translation)) {
3803 0 : add_assoc_string(return_value, "encoding_translation", "On", 1);
3804 : } else {
3805 0 : add_assoc_string(return_value, "encoding_translation", "Off", 1);
3806 : }
3807 0 : if ((name = (char *)mbfl_no_language2name(MBSTRG(language))) != NULL) {
3808 0 : add_assoc_string(return_value, "language", name, 1);
3809 : }
3810 0 : n = MBSTRG(current_detect_order_list_size);
3811 0 : entry = MBSTRG(current_detect_order_list);
3812 0 : if(n > 0) {
3813 0 : MAKE_STD_ZVAL(row2);
3814 0 : array_init(row2);
3815 0 : while (n > 0) {
3816 0 : if ((name = (char *)mbfl_no_encoding2name(*entry)) != NULL) {
3817 0 : add_next_index_string(row2, name, 1);
3818 : }
3819 0 : entry++;
3820 0 : n--;
3821 : }
3822 0 : add_assoc_zval(return_value, "detect_order", row2);
3823 : }
3824 0 : if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
3825 0 : add_assoc_string(return_value, "substitute_character", "none", 1);
3826 0 : } else if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG) {
3827 0 : add_assoc_string(return_value, "substitute_character", "long", 1);
3828 0 : } else if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_ENTITY) {
3829 0 : add_assoc_string(return_value, "substitute_character", "entity", 1);
3830 : } else {
3831 0 : add_assoc_long(return_value, "substitute_character", MBSTRG(current_filter_illegal_substchar));
3832 : }
3833 0 : if (MBSTRG(strict_detection)) {
3834 0 : add_assoc_string(return_value, "strict_detection", "On", 1);
3835 : } else {
3836 0 : add_assoc_string(return_value, "strict_detection", "Off", 1);
3837 : }
3838 : #ifdef ZEND_MULTIBYTE
3839 : entry = MBSTRG(script_encoding_list);
3840 : n = MBSTRG(script_encoding_list_size);
3841 : if(n > 0) {
3842 : MAKE_STD_ZVAL(row3);
3843 : array_init(row3);
3844 : while (n > 0) {
3845 : if ((name = (char *)mbfl_no_encoding2name(*entry)) != NULL) {
3846 : add_next_index_string(row3, name, 1);
3847 : }
3848 : entry++;
3849 : n--;
3850 : }
3851 : add_assoc_zval(return_value, "script_encoding", row3);
3852 : }
3853 : #endif /* ZEND_MULTIBYTE */
3854 0 : } else if (!strcasecmp("internal_encoding", typ)) {
3855 0 : if ((name = (char *)mbfl_no_encoding2name(MBSTRG(current_internal_encoding))) != NULL) {
3856 0 : RETVAL_STRING(name, 1);
3857 : }
3858 0 : } else if (!strcasecmp("http_input", typ)) {
3859 0 : if ((name = (char *)mbfl_no_encoding2name(MBSTRG(http_input_identify))) != NULL) {
3860 0 : RETVAL_STRING(name, 1);
3861 : }
3862 0 : } else if (!strcasecmp("http_output", typ)) {
3863 0 : if ((name = (char *)mbfl_no_encoding2name(MBSTRG(current_http_output_encoding))) != NULL) {
3864 0 : RETVAL_STRING(name, 1);
3865 : }
3866 0 : } else if (!strcasecmp("func_overload", typ)) {
3867 0 : RETVAL_LONG(MBSTRG(func_overload));
3868 0 : } else if (!strcasecmp("func_overload_list", typ)) {
3869 0 : if (MBSTRG(func_overload)){
3870 0 : over_func = &(mb_ovld[0]);
3871 0 : array_init(return_value);
3872 0 : while (over_func->type > 0) {
3873 0 : if ((MBSTRG(func_overload) & over_func->type) == over_func->type ) {
3874 0 : add_assoc_string(return_value, over_func->orig_func, over_func->ovld_func, 1);
3875 : }
3876 0 : over_func++;
3877 : }
3878 : } else {
3879 0 : RETVAL_STRING("no overload", 1);
3880 : }
3881 0 : } else if (!strcasecmp("mail_charset", typ)) {
3882 0 : if (lang != NULL && (name = (char *)mbfl_no_encoding2name(lang->mail_charset)) != NULL) {
3883 0 : RETVAL_STRING(name, 1);
3884 : }
3885 0 : } else if (!strcasecmp("mail_header_encoding", typ)) {
3886 0 : if (lang != NULL && (name = (char *)mbfl_no_encoding2name(lang->mail_header_encoding)) != NULL) {
3887 0 : RETVAL_STRING(name, 1);
3888 : }
3889 0 : } else if (!strcasecmp("mail_body_encoding", typ)) {
3890 0 : if (lang != NULL && (name = (char *)mbfl_no_encoding2name(lang->mail_body_encoding)) != NULL) {
3891 0 : RETVAL_STRING(name, 1);
3892 : }
3893 0 : } else if (!strcasecmp("illegal_chars", typ)) {
3894 0 : RETVAL_LONG(MBSTRG(illegalchars));
3895 0 : } else if (!strcasecmp("encoding_translation", typ)) {
3896 0 : if (MBSTRG(encoding_translation)) {
3897 0 : RETVAL_STRING("On", 1);
3898 : } else {
3899 0 : RETVAL_STRING("Off", 1);
3900 : }
3901 0 : } else if (!strcasecmp("language", typ)) {
3902 0 : if ((name = (char *)mbfl_no_language2name(MBSTRG(language))) != NULL) {
3903 0 : RETVAL_STRING(name, 1);
3904 : }
3905 0 : } else if (!strcasecmp("detect_order", typ)) {
3906 0 : n = MBSTRG(current_detect_order_list_size);
3907 0 : entry = MBSTRG(current_detect_order_list);
3908 0 : if(n > 0) {
3909 0 : array_init(return_value);
3910 0 : while (n > 0) {
3911 0 : name = (char *)mbfl_no_encoding2name(*entry);
3912 0 : if (name) {
3913 0 : add_next_index_string(return_value, name, 1);
3914 : }
3915 0 : entry++;
3916 0 : n--;
3917 : }
3918 : }
3919 0 : } else if (!strcasecmp("substitute_character", typ)) {
3920 0 : if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
3921 0 : RETVAL_STRING("none", 1);
3922 0 : } else if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG) {
3923 0 : RETVAL_STRING("long", 1);
3924 0 : } else if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_ENTITY) {
3925 0 : RETVAL_STRING("entity", 1);
3926 : } else {
3927 0 : RETVAL_LONG(MBSTRG(current_filter_illegal_substchar));
3928 : }
3929 0 : } else if (!strcasecmp("strict_detection", typ)) {
3930 0 : if (MBSTRG(strict_detection)) {
3931 0 : RETVAL_STRING("On", 1);
3932 : } else {
3933 0 : RETVAL_STRING("Off", 1);
3934 : }
3935 : } else {
3936 : #ifdef ZEND_MULTIBYTE
3937 : if (!strcasecmp("script_encoding", typ)) {
3938 : entry = MBSTRG(script_encoding_list);
3939 : n = MBSTRG(script_encoding_list_size);
3940 : if(n > 0) {
3941 : array_init(return_value);
3942 : while (n > 0) {
3943 : name = (char *)mbfl_no_encoding2name(*entry);
3944 : if (name) {
3945 : add_next_index_string(return_value, name, 1);
3946 : }
3947 : entry++;
3948 : n--;
3949 : }
3950 : }
3951 : return;
3952 : }
3953 : #endif /* ZEND_MULTIBYTE */
3954 0 : RETURN_FALSE;
3955 : }
3956 : }
3957 : /* }}} */
3958 :
3959 : /* {{{ proto bool mb_check_encoding([string var[, string encoding]])
3960 : Check if the string is valid for the specified encoding */
3961 : PHP_FUNCTION(mb_check_encoding)
3962 513 : {
3963 513 : char *var = NULL;
3964 : int var_len;
3965 513 : char *enc = NULL;
3966 : int enc_len;
3967 : mbfl_buffer_converter *convd;
3968 513 : enum mbfl_no_encoding no_encoding = MBSTRG(current_internal_encoding);
3969 513 : mbfl_string string, result, *ret = NULL;
3970 513 : long illegalchars = 0;
3971 :
3972 513 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ss", &var, &var_len, &enc, &enc_len) == FAILURE) {
3973 0 : RETURN_FALSE;
3974 : }
3975 :
3976 513 : if (var == NULL) {
3977 0 : RETURN_BOOL(MBSTRG(illegalchars) == 0);
3978 : }
3979 :
3980 513 : if (enc != NULL) {
3981 513 : no_encoding = mbfl_name2no_encoding(enc);
3982 513 : if (no_encoding == mbfl_no_encoding_invalid || no_encoding == mbfl_no_encoding_pass) {
3983 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid encoding \"%s\"", enc);
3984 0 : RETURN_FALSE;
3985 : }
3986 : }
3987 :
3988 513 : convd = mbfl_buffer_converter_new(no_encoding, no_encoding, 0);
3989 513 : if (convd == NULL) {
3990 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create converter");
3991 0 : RETURN_FALSE;
3992 : }
3993 513 : mbfl_buffer_converter_illegal_mode(convd, MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE);
3994 513 : mbfl_buffer_converter_illegal_substchar(convd, 0);
3995 :
3996 : /* initialize string */
3997 513 : mbfl_string_init_set(&string, mbfl_no_language_neutral, no_encoding);
3998 513 : mbfl_string_init(&result);
3999 :
4000 513 : string.val = (unsigned char *)var;
4001 513 : string.len = var_len;
4002 513 : ret = mbfl_buffer_converter_feed_result(convd, &string, &result);
4003 513 : illegalchars = mbfl_buffer_illegalchars(convd);
4004 513 : mbfl_buffer_converter_delete(convd);
4005 :
4006 513 : RETVAL_FALSE;
4007 513 : if (ret != NULL) {
4008 513 : if (illegalchars == 0 && string.len == result.len && memcmp(string.val, result.val, string.len) == 0) {
4009 376 : RETVAL_TRUE;
4010 : }
4011 513 : mbfl_string_clear(&result);
4012 : }
4013 : }
4014 : /* }}} */
4015 :
4016 : /* {{{ MBSTRING_API int php_mb_encoding_translation() */
4017 : MBSTRING_API int php_mb_encoding_translation(TSRMLS_D)
4018 144 : {
4019 144 : return MBSTRG(encoding_translation);
4020 : }
4021 : /* }}} */
4022 :
4023 : /* {{{ MBSTRING_API size_t php_mb_mbchar_bytes_ex() */
4024 : MBSTRING_API size_t php_mb_mbchar_bytes_ex(const char *s, const mbfl_encoding *enc)
4025 1032 : {
4026 1032 : if (enc != NULL) {
4027 1032 : if (enc->flag & MBFL_ENCTYPE_MBCS) {
4028 22 : if (enc->mblen_table != NULL) {
4029 22 : if (s != NULL) return enc->mblen_table[*(unsigned char *)s];
4030 : }
4031 1010 : } else if (enc->flag & (MBFL_ENCTYPE_WCS2BE | MBFL_ENCTYPE_WCS2LE)) {
4032 0 : return 2;
4033 1010 : } else if (enc->flag & (MBFL_ENCTYPE_WCS4BE | MBFL_ENCTYPE_WCS4LE)) {
4034 0 : return 4;
4035 : }
4036 : }
4037 1010 : return 1;
4038 : }
4039 : /* }}} */
4040 :
4041 : /* {{{ MBSTRING_API size_t php_mb_mbchar_bytes() */
4042 : MBSTRING_API size_t php_mb_mbchar_bytes(const char *s TSRMLS_DC)
4043 0 : {
4044 0 : return php_mb_mbchar_bytes_ex(s,
4045 : mbfl_no2encoding(MBSTRG(internal_encoding)));
4046 : }
4047 : /* }}} */
4048 :
4049 : /* {{{ MBSTRING_API char *php_mb_safe_strrchr_ex() */
4050 : MBSTRING_API char *php_mb_safe_strrchr_ex(const char *s, unsigned int c, size_t nbytes, const mbfl_encoding *enc)
4051 0 : {
4052 0 : register const char *p = s;
4053 0 : char *last=NULL;
4054 :
4055 0 : if (nbytes == (size_t)-1) {
4056 0 : size_t nb = 0;
4057 :
4058 0 : while (*p != '\0') {
4059 0 : if (nb == 0) {
4060 0 : if ((unsigned char)*p == (unsigned char)c) {
4061 0 : last = (char *)p;
4062 : }
4063 0 : nb = php_mb_mbchar_bytes_ex(p, enc);
4064 0 : if (nb == 0) {
4065 0 : return NULL; /* something is going wrong! */
4066 : }
4067 : }
4068 0 : --nb;
4069 0 : ++p;
4070 : }
4071 : } else {
4072 0 : register size_t bcnt = nbytes;
4073 : register size_t nbytes_char;
4074 0 : while (bcnt > 0) {
4075 0 : if ((unsigned char)*p == (unsigned char)c) {
4076 0 : last = (char *)p;
4077 : }
4078 0 : nbytes_char = php_mb_mbchar_bytes_ex(p, enc);
4079 0 : if (bcnt < nbytes_char) {
4080 0 : return NULL;
4081 : }
4082 0 : p += nbytes_char;
4083 0 : bcnt -= nbytes_char;
4084 : }
4085 : }
4086 0 : return last;
4087 : }
4088 : /* }}} */
4089 :
4090 : /* {{{ MBSTRING_API char *php_mb_safe_strrchr() */
4091 : MBSTRING_API char *php_mb_safe_strrchr(const char *s, unsigned int c, size_t nbytes TSRMLS_DC)
4092 0 : {
4093 0 : return php_mb_safe_strrchr_ex(s, c, nbytes,
4094 : mbfl_no2encoding(MBSTRG(internal_encoding)));
4095 : }
4096 : /* }}} */
4097 :
4098 : /* {{{ MBSTRING_API char *php_mb_strrchr() */
4099 : MBSTRING_API char *php_mb_strrchr(const char *s, char c TSRMLS_DC)
4100 0 : {
4101 0 : return php_mb_safe_strrchr(s, c, -1 TSRMLS_CC);
4102 : }
4103 : /* }}} */
4104 :
4105 : /* {{{ MBSTRING_API size_t php_mb_gpc_mbchar_bytes() */
4106 : MBSTRING_API size_t php_mb_gpc_mbchar_bytes(const char *s TSRMLS_DC)
4107 0 : {
4108 :
4109 0 : if (MBSTRG(http_input_identify) != mbfl_no_encoding_invalid){
4110 0 : return php_mb_mbchar_bytes_ex(s,
4111 : mbfl_no2encoding(MBSTRG(http_input_identify)));
4112 : } else {
4113 0 : return php_mb_mbchar_bytes_ex(s,
4114 : mbfl_no2encoding(MBSTRG(internal_encoding)));
4115 : }
4116 : }
4117 : /* }}} */
4118 :
4119 : /* {{{ MBSTRING_API int php_mb_gpc_encoding_converter() */
4120 : MBSTRING_API int php_mb_gpc_encoding_converter(char **str, int *len, int num, const char *encoding_to, const char *encoding_from
4121 : TSRMLS_DC)
4122 0 : {
4123 : int i;
4124 0 : mbfl_string string, result, *ret = NULL;
4125 : enum mbfl_no_encoding from_encoding, to_encoding;
4126 : mbfl_buffer_converter *convd;
4127 :
4128 0 : if (encoding_to) {
4129 : /* new encoding */
4130 0 : to_encoding = mbfl_name2no_encoding(encoding_to);
4131 0 : if (to_encoding == mbfl_no_encoding_invalid) {
4132 0 : return -1;
4133 : }
4134 : } else {
4135 0 : to_encoding = MBSTRG(current_internal_encoding);
4136 : }
4137 0 : if (encoding_from) {
4138 : /* old encoding */
4139 0 : from_encoding = mbfl_name2no_encoding(encoding_from);
4140 0 : if (from_encoding == mbfl_no_encoding_invalid) {
4141 0 : return -1;
4142 : }
4143 : } else {
4144 0 : from_encoding = MBSTRG(http_input_identify);
4145 : }
4146 :
4147 0 : if (from_encoding == mbfl_no_encoding_pass) {
4148 0 : return 0;
4149 : }
4150 :
4151 : /* initialize string */
4152 0 : mbfl_string_init(&string);
4153 0 : mbfl_string_init(&result);
4154 0 : string.no_encoding = from_encoding;
4155 0 : string.no_language = MBSTRG(language);
4156 :
4157 0 : for (i=0; i<num; i++){
4158 0 : string.val = (char*)str[i];
4159 0 : string.len = len[i];
4160 :
4161 : /* initialize converter */
4162 0 : convd = mbfl_buffer_converter_new(from_encoding, to_encoding, string.len);
4163 0 : if (convd == NULL) {
4164 0 : return -1;
4165 : }
4166 0 : mbfl_buffer_converter_illegal_mode(convd, MBSTRG(current_filter_illegal_mode));
4167 0 : mbfl_buffer_converter_illegal_substchar(convd, MBSTRG(current_filter_illegal_substchar));
4168 :
4169 : /* do it */
4170 0 : ret = mbfl_buffer_converter_feed_result(convd, &string, &result);
4171 0 : if (ret != NULL) {
4172 0 : efree(str[i]);
4173 0 : str[i] = ret->val;
4174 0 : len[i] = ret->len;
4175 : }
4176 :
4177 0 : MBSTRG(illegalchars) += mbfl_buffer_illegalchars(convd);
4178 0 : mbfl_buffer_converter_delete(convd);
4179 : }
4180 :
4181 0 : return ret ? 0 : -1;
4182 : }
4183 : /* }}} */
4184 :
4185 : /* {{{ MBSTRING_API int php_mb_gpc_encoding_detector()
4186 : */
4187 : MBSTRING_API int php_mb_gpc_encoding_detector(char **arg_string, int *arg_length, int num, char *arg_list TSRMLS_DC)
4188 0 : {
4189 : mbfl_string string;
4190 : enum mbfl_no_encoding *elist;
4191 0 : enum mbfl_no_encoding encoding = mbfl_no_encoding_invalid;
4192 0 : mbfl_encoding_detector *identd = NULL;
4193 :
4194 : int size;
4195 : enum mbfl_no_encoding *list;
4196 :
4197 0 : if (MBSTRG(http_input_list_size) == 1 &&
4198 : MBSTRG(http_input_list)[0] == mbfl_no_encoding_pass) {
4199 0 : MBSTRG(http_input_identify) = mbfl_no_encoding_pass;
4200 0 : return SUCCESS;
4201 : }
4202 :
4203 0 : if (MBSTRG(http_input_list_size) == 1 &&
4204 : MBSTRG(http_input_list)[0] != mbfl_no_encoding_auto &&
4205 : mbfl_no_encoding2name(MBSTRG(http_input_list)[0]) != NULL) {
4206 0 : MBSTRG(http_input_identify) = MBSTRG(http_input_list)[0];
4207 0 : return SUCCESS;
4208 : }
4209 :
4210 0 : if (arg_list && strlen(arg_list)>0) {
4211 : /* make encoding list */
4212 0 : list = NULL;
4213 0 : size = 0;
4214 0 : php_mb_parse_encoding_list(arg_list, strlen(arg_list), &list, &size, 0 TSRMLS_CC);
4215 :
4216 0 : if (size > 0 && list != NULL) {
4217 0 : elist = list;
4218 : } else {
4219 0 : elist = MBSTRG(current_detect_order_list);
4220 0 : size = MBSTRG(current_detect_order_list_size);
4221 0 : if (size <= 0){
4222 0 : elist = MBSTRG(default_detect_order_list);
4223 0 : size = MBSTRG(default_detect_order_list_size);
4224 : }
4225 : }
4226 : } else {
4227 0 : elist = MBSTRG(current_detect_order_list);
4228 0 : size = MBSTRG(current_detect_order_list_size);
4229 0 : if (size <= 0){
4230 0 : elist = MBSTRG(default_detect_order_list);
4231 0 : size = MBSTRG(default_detect_order_list_size);
4232 : }
4233 : }
4234 :
4235 0 : mbfl_string_init(&string);
4236 0 : string.no_language = MBSTRG(language);
4237 :
4238 0 : identd = mbfl_encoding_detector_new(elist, size, MBSTRG(strict_detection));
4239 :
4240 0 : if (identd) {
4241 0 : int n = 0;
4242 0 : while(n < num){
4243 0 : string.val = (unsigned char *)arg_string[n];
4244 0 : string.len = arg_length[n];
4245 0 : if (mbfl_encoding_detector_feed(identd, &string)) {
4246 0 : break;
4247 : }
4248 0 : n++;
4249 : }
4250 0 : encoding = mbfl_encoding_detector_judge(identd);
4251 0 : mbfl_encoding_detector_delete(identd);
4252 : }
4253 :
4254 0 : if (encoding != mbfl_no_encoding_invalid) {
4255 0 : MBSTRG(http_input_identify) = encoding;
4256 0 : return SUCCESS;
4257 : } else {
4258 0 : return FAILURE;
4259 : }
4260 : }
4261 : /* }}} */
4262 :
4263 : /* {{{ MBSTRING_API int php_mb_stripos()
4264 : */
4265 :
4266 : MBSTRING_API int php_mb_stripos(int mode, char *old_haystack, int old_haystack_len, char *old_needle, int old_needle_len, long offset, char *from_encoding TSRMLS_DC)
4267 608 : {
4268 : int n;
4269 : mbfl_string haystack, needle;
4270 608 : n = -1;
4271 :
4272 608 : mbfl_string_init(&haystack);
4273 608 : mbfl_string_init(&needle);
4274 608 : haystack.no_language = MBSTRG(language);
4275 608 : haystack.no_encoding = MBSTRG(current_internal_encoding);
4276 608 : needle.no_language = MBSTRG(language);
4277 608 : needle.no_encoding = MBSTRG(current_internal_encoding);
4278 :
4279 : do {
4280 608 : haystack.val = php_unicode_convert_case(PHP_UNICODE_CASE_UPPER, old_haystack, (size_t) old_haystack_len, &haystack.len, from_encoding TSRMLS_CC);
4281 :
4282 608 : if (!haystack.val) {
4283 40 : break;
4284 : }
4285 :
4286 568 : if (haystack.len <= 0) {
4287 32 : break;
4288 : }
4289 :
4290 536 : needle.val = php_unicode_convert_case(PHP_UNICODE_CASE_UPPER, old_needle, (size_t) old_needle_len, &needle.len, from_encoding TSRMLS_CC);
4291 :
4292 536 : if (!needle.val) {
4293 0 : break;
4294 : }
4295 :
4296 536 : if (needle.len <= 0) {
4297 24 : break;
4298 : }
4299 :
4300 512 : haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(from_encoding);
4301 512 : if (haystack.no_encoding == mbfl_no_encoding_invalid) {
4302 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", from_encoding);
4303 0 : break;
4304 : }
4305 :
4306 : {
4307 512 : int haystack_char_len = mbfl_strlen(&haystack);
4308 :
4309 512 : if (mode) {
4310 239 : if ((offset > 0 && offset > haystack_char_len) ||
4311 : (offset < 0 && -offset > haystack_char_len)) {
4312 14 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset is greater than the length of haystack string");
4313 14 : break;
4314 : }
4315 : } else {
4316 273 : if (offset < 0 || offset > haystack_char_len) {
4317 26 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset not contained in string");
4318 26 : break;
4319 : }
4320 : }
4321 : }
4322 :
4323 472 : n = mbfl_strpos(&haystack, &needle, offset, mode);
4324 : } while(0);
4325 :
4326 608 : if(haystack.val){
4327 568 : efree(haystack.val);
4328 : }
4329 :
4330 608 : if(needle.val){
4331 536 : efree(needle.val);
4332 : }
4333 :
4334 608 : return n;
4335 : }
4336 : /* }}} */
4337 :
4338 : #ifdef ZEND_MULTIBYTE
4339 : /* {{{ MBSTRING_API int php_mb_set_zend_encoding() */
4340 : MBSTRING_API int php_mb_set_zend_encoding(TSRMLS_D)
4341 : {
4342 : /* 'd better use mbfl_memory_device? */
4343 : char *name, *list = NULL;
4344 : int n, *entry, list_size = 0;
4345 : zend_encoding_detector encoding_detector;
4346 : zend_encoding_converter encoding_converter;
4347 : zend_encoding_oddlen encoding_oddlen;
4348 :
4349 : /* notify script encoding to Zend Engine */
4350 : entry = MBSTRG(script_encoding_list);
4351 : n = MBSTRG(script_encoding_list_size);
4352 : while (n > 0) {
4353 : name = (char *)mbfl_no_encoding2name(*entry);
4354 : if (name) {
4355 : list_size += strlen(name) + 1;
4356 : if (!list) {
4357 : list = (char*)emalloc(list_size);
4358 : *list = (char)NULL;
4359 : } else {
4360 : list = (char*)erealloc(list, list_size);
4361 : strcat(list, ",");
4362 : }
4363 : strcat(list, name);
4364 : }
4365 : entry++;
4366 : n--;
4367 : }
4368 : zend_multibyte_set_script_encoding(list, (list ? strlen(list) : 0) TSRMLS_CC);
4369 : if (list) {
4370 : efree(list);
4371 : }
4372 : encoding_detector = php_mb_encoding_detector;
4373 : encoding_converter = php_mb_encoding_converter;
4374 : encoding_oddlen = php_mb_oddlen;
4375 :
4376 : /* TODO: make independent from mbstring.encoding_translation? */
4377 : if (MBSTRG(encoding_translation)) {
4378 : /* notify internal encoding to Zend Engine */
4379 : name = (char*)mbfl_no_encoding2name(MBSTRG(current_internal_encoding));
4380 : zend_multibyte_set_internal_encoding(name, strlen(name) TSRMLS_CC);
4381 : }
4382 :
4383 : zend_multibyte_set_functions(encoding_detector, encoding_converter, encoding_oddlen TSRMLS_CC);
4384 :
4385 : return 0;
4386 : }
4387 : /* }}} */
4388 :
4389 : /* {{{ char *php_mb_encoding_detector()
4390 : * Interface for Zend Engine
4391 : */
4392 : char* php_mb_encoding_detector(const char *arg_string, int arg_length, char *arg_list TSRMLS_DC)
4393 : {
4394 : mbfl_string string;
4395 : const char *ret;
4396 : enum mbfl_no_encoding *elist;
4397 : int size, *list;
4398 :
4399 : /* make encoding list */
4400 : list = NULL;
4401 : size = 0;
4402 : php_mb_parse_encoding_list(arg_list, strlen(arg_list), &list, &size, 0 TSRMLS_CC);
4403 : if (size <= 0) {
4404 : return NULL;
4405 : }
4406 : if (size > 0 && list != NULL) {
4407 : elist = list;
4408 : } else {
4409 : elist = MBSTRG(current_detect_order_list);
4410 : size = MBSTRG(current_detect_order_list_size);
4411 : }
4412 :
4413 : mbfl_string_init(&string);
4414 : string.no_language = MBSTRG(language);
4415 : string.val = (char*)arg_string;
4416 : string.len = arg_length;
4417 : ret = mbfl_identify_encoding_name(&string, elist, size, 0);
4418 : if (list != NULL) {
4419 : efree((void *)list);
4420 : }
4421 : if (ret != NULL) {
4422 : return estrdup(ret);
4423 : } else {
4424 : return NULL;
4425 : }
4426 : }
4427 : /* }}} */
4428 :
4429 : /* {{{ int php_mb_encoding_converter() */
4430 : int php_mb_encoding_converter(char **to, int *to_length, const char *from,
4431 : int from_length, const char *encoding_to, const char *encoding_from
4432 : TSRMLS_DC)
4433 : {
4434 : mbfl_string string, result, *ret;
4435 : enum mbfl_no_encoding from_encoding, to_encoding;
4436 : mbfl_buffer_converter *convd;
4437 :
4438 : /* new encoding */
4439 : to_encoding = mbfl_name2no_encoding(encoding_to);
4440 : if (to_encoding == mbfl_no_encoding_invalid) {
4441 : return -1;
4442 : }
4443 : /* old encoding */
4444 : from_encoding = mbfl_name2no_encoding(encoding_from);
4445 : if (from_encoding == mbfl_no_encoding_invalid) {
4446 : return -1;
4447 : }
4448 : /* initialize string */
4449 : mbfl_string_init(&string);
4450 : mbfl_string_init(&result);
4451 : string.no_encoding = from_encoding;
4452 : string.no_language = MBSTRG(language);
4453 : string.val = (char*)from;
4454 : string.len = from_length;
4455 :
4456 : /* initialize converter */
4457 : convd = mbfl_buffer_converter_new(from_encoding, to_encoding, string.len);
4458 : if (convd == NULL) {
4459 : return -1;
4460 : }
4461 : mbfl_buffer_converter_illegal_mode(convd, MBSTRG(current_filter_illegal_mode));
4462 : mbfl_buffer_converter_illegal_substchar(convd, MBSTRG(current_filter_illegal_substchar));
4463 :
4464 : /* do it */
4465 : ret = mbfl_buffer_converter_feed_result(convd, &string, &result);
4466 : if (ret != NULL) {
4467 : *to = ret->val;
4468 : *to_length = ret->len;
4469 : }
4470 :
4471 : MBSTRG(illegalchars) += mbfl_buffer_illegalchars(convd);
4472 : mbfl_buffer_converter_delete(convd);
4473 :
4474 : return ret ? 0 : -1;
4475 : }
4476 : /* }}} */
4477 :
4478 : /* {{{ int php_mb_oddlen()
4479 : * returns number of odd (e.g. appears only first byte of multibyte
4480 : * character) chars
4481 : */
4482 : int php_mb_oddlen(const char *string, int length, const char *encoding TSRMLS_DC)
4483 : {
4484 : mbfl_string mb_string;
4485 :
4486 : mbfl_string_init(&mb_string);
4487 : mb_string.no_language = MBSTRG(language);
4488 : mb_string.no_encoding = mbfl_name2no_encoding(encoding);
4489 : mb_string.val = (char*)string;
4490 : mb_string.len = length;
4491 :
4492 : if (mb_string.no_encoding == mbfl_no_encoding_invalid) {
4493 : return 0;
4494 : }
4495 : return mbfl_oddlen(&mb_string);
4496 : }
4497 : /* }}} */
4498 : #endif /* ZEND_MULTIBYTE */
4499 :
4500 : #endif /* HAVE_MBSTRING */
4501 :
4502 : /*
4503 : * Local variables:
4504 : * tab-width: 4
4505 : * c-basic-offset: 4
4506 : * End:
4507 : * vim600: fdm=marker
4508 : * vim: noet sw=4 ts=4
4509 : */
|