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