PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/iconv - iconv.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 923 1229 75.1 %
Date: 2016-09-18 Functions: 41 41 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 7                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2016 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Rui Hirokawa <rui_hirokawa@ybb.ne.jp>                       |
      16             :    |          Stig Bakken <ssb@php.net>                                   |
      17             :    |          Moriyoshi Koizumi <moriyoshi@php.net>                       |
      18             :    +----------------------------------------------------------------------+
      19             :  */
      20             : 
      21             : /* $Id$ */
      22             : 
      23             : #ifdef HAVE_CONFIG_H
      24             : #include "config.h"
      25             : #endif
      26             : 
      27             : #include "php.h"
      28             : #include "php_globals.h"
      29             : #include "ext/standard/info.h"
      30             : #include "main/php_output.h"
      31             : #include "SAPI.h"
      32             : #include "php_ini.h"
      33             : 
      34             : #ifdef HAVE_STDLIB_H
      35             : # include <stdlib.h>
      36             : #endif
      37             : 
      38             : #include <errno.h>
      39             : 
      40             : #include "php_iconv.h"
      41             : 
      42             : #ifdef HAVE_ICONV
      43             : 
      44             : #ifdef PHP_ICONV_H_PATH
      45             : #include PHP_ICONV_H_PATH
      46             : #else
      47             : #include <iconv.h>
      48             : #endif
      49             : 
      50             : #ifdef HAVE_GLIBC_ICONV
      51             : #include <gnu/libc-version.h>
      52             : #endif
      53             : 
      54             : #ifdef HAVE_LIBICONV
      55             : #undef iconv
      56             : #endif
      57             : 
      58             : #include "zend_smart_str.h"
      59             : #include "ext/standard/base64.h"
      60             : #include "ext/standard/quot_print.h"
      61             : 
      62             : #define _php_iconv_memequal(a, b, c) \
      63             :   ((c) == sizeof(zend_ulong) ? *((zend_ulong *)(a)) == *((zend_ulong *)(b)) : ((c) == sizeof(unsigned int) ? *((unsigned int *)(a)) == *((unsigned int *)(b)) : memcmp(a, b, c) == 0))
      64             : 
      65             : /* {{{ arginfo */
      66             : ZEND_BEGIN_ARG_INFO_EX(arginfo_iconv_strlen, 0, 0, 1)
      67             :         ZEND_ARG_INFO(0, str)
      68             :         ZEND_ARG_INFO(0, charset)
      69             : ZEND_END_ARG_INFO()
      70             : 
      71             : ZEND_BEGIN_ARG_INFO_EX(arginfo_iconv_substr, 0, 0, 2)
      72             :         ZEND_ARG_INFO(0, str)
      73             :         ZEND_ARG_INFO(0, offset)
      74             :         ZEND_ARG_INFO(0, length)
      75             :         ZEND_ARG_INFO(0, charset)
      76             : ZEND_END_ARG_INFO()
      77             : 
      78             : ZEND_BEGIN_ARG_INFO_EX(arginfo_iconv_strpos, 0, 0, 2)
      79             :         ZEND_ARG_INFO(0, haystack)
      80             :         ZEND_ARG_INFO(0, needle)
      81             :         ZEND_ARG_INFO(0, offset)
      82             :         ZEND_ARG_INFO(0, charset)
      83             : ZEND_END_ARG_INFO()
      84             : 
      85             : ZEND_BEGIN_ARG_INFO_EX(arginfo_iconv_strrpos, 0, 0, 2)
      86             :         ZEND_ARG_INFO(0, haystack)
      87             :         ZEND_ARG_INFO(0, needle)
      88             :         ZEND_ARG_INFO(0, charset)
      89             : ZEND_END_ARG_INFO()
      90             : 
      91             : ZEND_BEGIN_ARG_INFO_EX(arginfo_iconv_mime_encode, 0, 0, 2)
      92             :         ZEND_ARG_INFO(0, field_name)
      93             :         ZEND_ARG_INFO(0, field_value)
      94             :         ZEND_ARG_INFO(0, preference) /* ZEND_ARG_ARRAY_INFO(0, preference, 1) */
      95             : ZEND_END_ARG_INFO()
      96             : 
      97             : ZEND_BEGIN_ARG_INFO_EX(arginfo_iconv_mime_decode, 0, 0, 1)
      98             :         ZEND_ARG_INFO(0, encoded_string)
      99             :         ZEND_ARG_INFO(0, mode)
     100             :         ZEND_ARG_INFO(0, charset)
     101             : ZEND_END_ARG_INFO()
     102             : 
     103             : ZEND_BEGIN_ARG_INFO_EX(arginfo_iconv_mime_decode_headers, 0, 0, 1)
     104             :         ZEND_ARG_INFO(0, headers)
     105             :         ZEND_ARG_INFO(0, mode)
     106             :         ZEND_ARG_INFO(0, charset)
     107             : ZEND_END_ARG_INFO()
     108             : 
     109             : ZEND_BEGIN_ARG_INFO(arginfo_iconv, 0)
     110             :         ZEND_ARG_INFO(0, in_charset)
     111             :         ZEND_ARG_INFO(0, out_charset)
     112             :         ZEND_ARG_INFO(0, str)
     113             : ZEND_END_ARG_INFO()
     114             : 
     115             : ZEND_BEGIN_ARG_INFO(arginfo_iconv_set_encoding, 0)
     116             :         ZEND_ARG_INFO(0, type)
     117             :         ZEND_ARG_INFO(0, charset)
     118             : ZEND_END_ARG_INFO()
     119             : 
     120             : ZEND_BEGIN_ARG_INFO_EX(arginfo_iconv_get_encoding, 0, 0, 0)
     121             :         ZEND_ARG_INFO(0, type)
     122             : ZEND_END_ARG_INFO()
     123             : 
     124             : /* }}} */
     125             : 
     126             : /* {{{ iconv_functions[]
     127             :  */
     128             : const zend_function_entry iconv_functions[] = {
     129             :         PHP_RAW_NAMED_FE(iconv,php_if_iconv,                            arginfo_iconv)
     130             :         PHP_FE(iconv_get_encoding,                                              arginfo_iconv_get_encoding)
     131             :         PHP_FE(iconv_set_encoding,                                              arginfo_iconv_set_encoding)
     132             :         PHP_FE(iconv_strlen,                                                    arginfo_iconv_strlen)
     133             :         PHP_FE(iconv_substr,                                                    arginfo_iconv_substr)
     134             :         PHP_FE(iconv_strpos,                                                    arginfo_iconv_strpos)
     135             :         PHP_FE(iconv_strrpos,                                                   arginfo_iconv_strrpos)
     136             :         PHP_FE(iconv_mime_encode,                                               arginfo_iconv_mime_encode)
     137             :         PHP_FE(iconv_mime_decode,                                               arginfo_iconv_mime_decode)
     138             :         PHP_FE(iconv_mime_decode_headers,                               arginfo_iconv_mime_decode_headers)
     139             :         PHP_FE_END
     140             : };
     141             : /* }}} */
     142             : 
     143             : ZEND_DECLARE_MODULE_GLOBALS(iconv)
     144             : static PHP_GINIT_FUNCTION(iconv);
     145             : 
     146             : /* {{{ iconv_module_entry
     147             :  */
     148             : zend_module_entry iconv_module_entry = {
     149             :         STANDARD_MODULE_HEADER,
     150             :         "iconv",
     151             :         iconv_functions,
     152             :         PHP_MINIT(miconv),
     153             :         PHP_MSHUTDOWN(miconv),
     154             :         NULL,
     155             :         NULL,
     156             :         PHP_MINFO(miconv),
     157             :         PHP_ICONV_VERSION,
     158             :         PHP_MODULE_GLOBALS(iconv),
     159             :         PHP_GINIT(iconv),
     160             :         NULL,
     161             :         NULL,
     162             :         STANDARD_MODULE_PROPERTIES_EX
     163             : };
     164             : /* }}} */
     165             : 
     166             : #ifdef COMPILE_DL_ICONV
     167             : #ifdef ZTS
     168             : ZEND_TSRMLS_CACHE_DEFINE()
     169             : #endif
     170             : ZEND_GET_MODULE(iconv)
     171             : #endif
     172             : 
     173             : /* {{{ PHP_GINIT_FUNCTION */
     174       23922 : static PHP_GINIT_FUNCTION(iconv)
     175             : {
     176             : #if defined(COMPILE_DL_ICONV) && defined(ZTS)
     177             :         ZEND_TSRMLS_CACHE_UPDATE();
     178             : #endif
     179       23922 :         iconv_globals->input_encoding = NULL;
     180       23922 :         iconv_globals->output_encoding = NULL;
     181       23922 :         iconv_globals->internal_encoding = NULL;
     182       23922 : }
     183             : /* }}} */
     184             : 
     185             : #if defined(HAVE_LIBICONV) && defined(ICONV_ALIASED_LIBICONV)
     186             : #define iconv libiconv
     187             : #endif
     188             : 
     189             : /* {{{ typedef enum php_iconv_enc_scheme_t */
     190             : typedef enum _php_iconv_enc_scheme_t {
     191             :         PHP_ICONV_ENC_SCHEME_BASE64,
     192             :         PHP_ICONV_ENC_SCHEME_QPRINT
     193             : } php_iconv_enc_scheme_t;
     194             : /* }}} */
     195             : 
     196             : #define PHP_ICONV_MIME_DECODE_STRICT            (1<<0)
     197             : #define PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR (1<<1)
     198             : 
     199             : /* {{{ prototypes */
     200             : static php_iconv_err_t _php_iconv_appendl(smart_str *d, const char *s, size_t l, iconv_t cd);
     201             : static php_iconv_err_t _php_iconv_appendc(smart_str *d, const char c, iconv_t cd);
     202             : 
     203             : static void _php_iconv_show_error(php_iconv_err_t err, const char *out_charset, const char *in_charset);
     204             : 
     205             : static php_iconv_err_t _php_iconv_strlen(size_t *pretval, const char *str, size_t nbytes, const char *enc);
     206             : 
     207             : static php_iconv_err_t _php_iconv_substr(smart_str *pretval, const char *str, size_t nbytes, zend_long offset, zend_long len, const char *enc);
     208             : 
     209             : static php_iconv_err_t _php_iconv_strpos(size_t *pretval, const char *haystk, size_t haystk_nbytes, const char *ndl, size_t ndl_nbytes, zend_long offset, const char *enc);
     210             : 
     211             : static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fname, size_t fname_nbytes, const char *fval, size_t fval_nbytes, size_t max_line_len, const char *lfchars, php_iconv_enc_scheme_t enc_scheme, const char *out_charset, const char *enc);
     212             : 
     213             : static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *str, size_t str_nbytes, const char *enc, const char **next_pos, int mode);
     214             : 
     215             : static php_iconv_err_t php_iconv_stream_filter_register_factory(void);
     216             : static php_iconv_err_t php_iconv_stream_filter_unregister_factory(void);
     217             : 
     218             : static int php_iconv_output_conflict(const char *handler_name, size_t handler_name_len);
     219             : static php_output_handler *php_iconv_output_handler_init(const char *name, size_t name_len, size_t chunk_size, int flags);
     220             : static int php_iconv_output_handler(void **nothing, php_output_context *output_context);
     221             : /* }}} */
     222             : 
     223             : /* {{{ static globals */
     224             : static char _generic_superset_name[] = ICONV_UCS4_ENCODING;
     225             : #define GENERIC_SUPERSET_NAME _generic_superset_name
     226             : #define GENERIC_SUPERSET_NBYTES 4
     227             : /* }}} */
     228             : 
     229             : 
     230       23953 : static PHP_INI_MH(OnUpdateInputEncoding)
     231             : {
     232       23953 :         if (ZSTR_LEN(new_value) >= ICONV_CSNMAXLEN) {
     233           0 :                 return FAILURE;
     234             :         }
     235       23953 :         if (stage & (PHP_INI_STAGE_ACTIVATE | PHP_INI_STAGE_RUNTIME)) {
     236          27 :                 php_error_docref("ref.iconv", E_DEPRECATED, "Use of iconv.input_encoding is deprecated");
     237             :         }
     238       23953 :         OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
     239       23953 :         return SUCCESS;
     240             : }
     241             : 
     242             : 
     243       23957 : static PHP_INI_MH(OnUpdateOutputEncoding)
     244             : {
     245       23957 :         if (ZSTR_LEN(new_value) >= ICONV_CSNMAXLEN) {
     246           1 :                 return FAILURE;
     247             :         }
     248       23956 :         if (stage & (PHP_INI_STAGE_ACTIVATE | PHP_INI_STAGE_RUNTIME)) {
     249          28 :                 php_error_docref("ref.iconv", E_DEPRECATED, "Use of iconv.output_encoding is deprecated");
     250             :         }
     251       23956 :         OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
     252       23956 :         return SUCCESS;
     253             : }
     254             : 
     255             : 
     256       23961 : static PHP_INI_MH(OnUpdateInternalEncoding)
     257             : {
     258       23961 :         if (ZSTR_LEN(new_value) >= ICONV_CSNMAXLEN) {
     259           0 :                 return FAILURE;
     260             :         }
     261       23961 :         if (stage & (PHP_INI_STAGE_ACTIVATE | PHP_INI_STAGE_RUNTIME)) {
     262          31 :                 php_error_docref("ref.iconv", E_DEPRECATED, "Use of iconv.internal_encoding is deprecated");
     263             :         }
     264       23961 :         OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
     265       23961 :         return SUCCESS;
     266             : }
     267             : 
     268             : 
     269             : /* {{{ PHP_INI
     270             :  */
     271             : PHP_INI_BEGIN()
     272             :         STD_PHP_INI_ENTRY("iconv.input_encoding",    "", PHP_INI_ALL, OnUpdateInputEncoding,    input_encoding,    zend_iconv_globals, iconv_globals)
     273             :         STD_PHP_INI_ENTRY("iconv.output_encoding",   "", PHP_INI_ALL, OnUpdateOutputEncoding,   output_encoding,   zend_iconv_globals, iconv_globals)
     274             :         STD_PHP_INI_ENTRY("iconv.internal_encoding", "", PHP_INI_ALL, OnUpdateInternalEncoding, internal_encoding, zend_iconv_globals, iconv_globals)
     275             : PHP_INI_END()
     276             : /* }}} */
     277             : 
     278             : /* {{{ PHP_MINIT_FUNCTION */
     279       23922 : PHP_MINIT_FUNCTION(miconv)
     280             : {
     281       23922 :         char *version = "unknown";
     282             : 
     283       23922 :         REGISTER_INI_ENTRIES();
     284             : 
     285             : #if HAVE_LIBICONV
     286             :         {
     287             :                 static char buf[16];
     288             :                 snprintf(buf, sizeof(buf), "%d.%d",
     289             :                     ((_libiconv_version >> 8) & 0x0f), (_libiconv_version & 0x0f));
     290             :                 version = buf;
     291             :         }
     292             : #elif HAVE_GLIBC_ICONV
     293       23922 :         version = (char *)gnu_get_libc_version();
     294             : #elif defined(NETWARE)
     295             :         version = "OS built-in";
     296             : #endif
     297             : 
     298             : #ifdef PHP_ICONV_IMPL
     299       23922 :         REGISTER_STRING_CONSTANT("ICONV_IMPL", PHP_ICONV_IMPL, CONST_CS | CONST_PERSISTENT);
     300             : #elif HAVE_LIBICONV
     301             :         REGISTER_STRING_CONSTANT("ICONV_IMPL", "libiconv", CONST_CS | CONST_PERSISTENT);
     302             : #elif defined(NETWARE)
     303             :         REGISTER_STRING_CONSTANT("ICONV_IMPL", "Novell", CONST_CS | CONST_PERSISTENT);
     304             : #else
     305             :         REGISTER_STRING_CONSTANT("ICONV_IMPL", "unknown", CONST_CS | CONST_PERSISTENT);
     306             : #endif
     307       23922 :         REGISTER_STRING_CONSTANT("ICONV_VERSION", version, CONST_CS | CONST_PERSISTENT);
     308             : 
     309       23922 :         REGISTER_LONG_CONSTANT("ICONV_MIME_DECODE_STRICT", PHP_ICONV_MIME_DECODE_STRICT, CONST_CS | CONST_PERSISTENT);
     310       23922 :         REGISTER_LONG_CONSTANT("ICONV_MIME_DECODE_CONTINUE_ON_ERROR", PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR, CONST_CS | CONST_PERSISTENT);
     311             : 
     312       23922 :         if (php_iconv_stream_filter_register_factory() != PHP_ICONV_ERR_SUCCESS) {
     313           0 :                 return FAILURE;
     314             :         }
     315             : 
     316       23922 :         php_output_handler_alias_register(ZEND_STRL("ob_iconv_handler"), php_iconv_output_handler_init);
     317       23922 :         php_output_handler_conflict_register(ZEND_STRL("ob_iconv_handler"), php_iconv_output_conflict);
     318             : 
     319       23922 :         return SUCCESS;
     320             : }
     321             : /* }}} */
     322             : 
     323             : /* {{{ PHP_MSHUTDOWN_FUNCTION */
     324       23963 : PHP_MSHUTDOWN_FUNCTION(miconv)
     325             : {
     326       23963 :         php_iconv_stream_filter_unregister_factory();
     327       23963 :         UNREGISTER_INI_ENTRIES();
     328       23963 :         return SUCCESS;
     329             : }
     330             : /* }}} */
     331             : 
     332             : /* {{{ PHP_MINFO_FUNCTION */
     333         150 : PHP_MINFO_FUNCTION(miconv)
     334             : {
     335             :         zval *iconv_impl, *iconv_ver;
     336             : 
     337         150 :         iconv_impl = zend_get_constant_str("ICONV_IMPL", sizeof("ICONV_IMPL")-1);
     338         150 :         iconv_ver = zend_get_constant_str("ICONV_VERSION", sizeof("ICONV_VERSION")-1);
     339             : 
     340         150 :         php_info_print_table_start();
     341         150 :         php_info_print_table_row(2, "iconv support", "enabled");
     342         150 :         php_info_print_table_row(2, "iconv implementation", Z_STRVAL_P(iconv_impl));
     343         150 :         php_info_print_table_row(2, "iconv library version", Z_STRVAL_P(iconv_ver));
     344         150 :         php_info_print_table_end();
     345             : 
     346         150 :         DISPLAY_INI_ENTRIES();
     347         150 : }
     348             : /* }}} */
     349             : 
     350         571 : static char *get_internal_encoding(void) {
     351         571 :         if (ICONVG(internal_encoding) && ICONVG(internal_encoding)[0]) {
     352          63 :                 return ICONVG(internal_encoding);
     353         508 :         } else if (PG(internal_encoding) && PG(internal_encoding)[0]) {
     354           0 :                 return PG(internal_encoding);
     355         508 :         } else if (SG(default_charset)) {
     356         508 :                 return SG(default_charset);
     357             :         }
     358           0 :         return "";
     359             : }
     360             : 
     361          36 : static char *get_input_encoding(void) {
     362          36 :         if (ICONVG(input_encoding) && ICONVG(input_encoding)[0]) {
     363          27 :                 return ICONVG(input_encoding);
     364           9 :         } else if (PG(input_encoding) && PG(input_encoding)[0]) {
     365           0 :                 return PG(input_encoding);
     366           9 :         } else if (SG(default_charset)) {
     367           9 :                 return SG(default_charset);
     368             :         }
     369           0 :         return "";
     370             : }
     371             : 
     372          44 : static char *get_output_encoding(void) {
     373          44 :         if (ICONVG(output_encoding) && ICONVG(output_encoding)[0]) {
     374          31 :                 return ICONVG(output_encoding);
     375          13 :         } else if (PG(output_encoding) && PG(output_encoding)[0]) {
     376           0 :                 return PG(output_encoding);
     377          13 :         } else if (SG(default_charset)) {
     378          13 :                 return SG(default_charset);
     379             :         }
     380           0 :         return "";
     381             : }
     382             : 
     383             : 
     384           2 : static int php_iconv_output_conflict(const char *handler_name, size_t handler_name_len)
     385             : {
     386           2 :         if (php_output_get_level()) {
     387           0 :                 if (php_output_handler_conflict(handler_name, handler_name_len, ZEND_STRL("ob_iconv_handler"))
     388           0 :                 ||      php_output_handler_conflict(handler_name, handler_name_len, ZEND_STRL("mb_output_handler"))) {
     389           0 :                         return FAILURE;
     390             :                 }
     391             :         }
     392           2 :         return SUCCESS;
     393             : }
     394             : 
     395           2 : static php_output_handler *php_iconv_output_handler_init(const char *handler_name, size_t handler_name_len, size_t chunk_size, int flags)
     396             : {
     397           2 :         return php_output_handler_create_internal(handler_name, handler_name_len, php_iconv_output_handler, chunk_size, flags);
     398             : }
     399             : 
     400           2 : static int php_iconv_output_handler(void **nothing, php_output_context *output_context)
     401             : {
     402           2 :         char *s, *content_type, *mimetype = NULL;
     403           2 :         int output_status, mimetype_len = 0;
     404             : 
     405           2 :         if (output_context->op & PHP_OUTPUT_HANDLER_START) {
     406           2 :                 output_status = php_output_get_status();
     407           2 :                 if (output_status & PHP_OUTPUT_SENT) {
     408           0 :                         return FAILURE;
     409             :                 }
     410             : 
     411           2 :                 if (SG(sapi_headers).mimetype && !strncasecmp(SG(sapi_headers).mimetype, "text/", 5)) {
     412           0 :                         if ((s = strchr(SG(sapi_headers).mimetype,';')) == NULL){
     413           0 :                                 mimetype = SG(sapi_headers).mimetype;
     414             :                         } else {
     415           0 :                                 mimetype = SG(sapi_headers).mimetype;
     416           0 :                                 mimetype_len = (int)(s - SG(sapi_headers).mimetype);
     417             :                         }
     418           2 :                 } else if (SG(sapi_headers).send_default_content_type) {
     419           2 :                         mimetype = SG(default_mimetype) ? SG(default_mimetype) : SAPI_DEFAULT_MIMETYPE;
     420             :                 }
     421             : 
     422           2 :                 if (mimetype != NULL && !(output_context->op & PHP_OUTPUT_HANDLER_CLEAN)) {
     423             :                         size_t len;
     424           2 :                         char *p = strstr(get_output_encoding(), "//");
     425             : 
     426           2 :                         if (p) {
     427           0 :                                 len = spprintf(&content_type, 0, "Content-Type:%.*s; charset=%.*s", mimetype_len ? mimetype_len : (int) strlen(mimetype), mimetype, (int) (p - get_output_encoding()), get_output_encoding());
     428             :                         } else {
     429           2 :                                 len = spprintf(&content_type, 0, "Content-Type:%.*s; charset=%s", mimetype_len ? mimetype_len : (int) strlen(mimetype), mimetype, get_output_encoding());
     430             :                         }
     431           2 :                         if (content_type && SUCCESS == sapi_add_header(content_type, (uint)len, 0)) {
     432           2 :                                 SG(sapi_headers).send_default_content_type = 0;
     433           2 :                                 php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE, NULL);
     434             :                         }
     435             :                 }
     436             :         }
     437             : 
     438           2 :         if (output_context->in.used) {
     439             :                 zend_string *out;
     440           2 :                 output_context->out.free = 1;
     441           2 :                 _php_iconv_show_error(php_iconv_string(output_context->in.data, output_context->in.used, &out, get_output_encoding(), get_internal_encoding()), get_output_encoding(), get_internal_encoding());
     442           2 :                 if (out) {
     443           2 :                         output_context->out.data = estrndup(ZSTR_VAL(out), ZSTR_LEN(out));
     444           2 :                         output_context->out.used = ZSTR_LEN(out);
     445           2 :                         zend_string_free(out);
     446             :                 } else {
     447           0 :                         output_context->out.data = NULL;
     448           0 :                         output_context->out.used = 0;
     449             :                 }
     450             :         }
     451             : 
     452           2 :         return SUCCESS;
     453             : }
     454             : 
     455             : /* {{{ _php_iconv_appendl() */
     456        2292 : static php_iconv_err_t _php_iconv_appendl(smart_str *d, const char *s, size_t l, iconv_t cd)
     457             : {
     458        2292 :         const char *in_p = s;
     459        2292 :         size_t in_left = l;
     460             :         char *out_p;
     461        2292 :         size_t out_left = 0;
     462        2292 :         size_t buf_growth = 128;
     463             : #if !ICONV_SUPPORTS_ERRNO
     464             :         size_t prev_in_left = in_left;
     465             : #endif
     466             : 
     467        2292 :         if (in_p != NULL) {
     468        6826 :                 while (in_left > 0) {
     469        2274 :                         out_left = buf_growth - out_left;
     470        2274 :                         smart_str_alloc(d, out_left, 0);
     471             : 
     472        2274 :                         out_p = ZSTR_VAL((d)->s) + ZSTR_LEN((d)->s);
     473             : 
     474        2274 :                         if (iconv(cd, (char **)&in_p, &in_left, (char **) &out_p, &out_left) == (size_t)-1) {
     475             : #if ICONV_SUPPORTS_ERRNO
     476           4 :                                 switch (errno) {
     477             :                                         case EINVAL:
     478           0 :                                                 return PHP_ICONV_ERR_ILLEGAL_CHAR;
     479             : 
     480             :                                         case EILSEQ:
     481           4 :                                                 return PHP_ICONV_ERR_ILLEGAL_SEQ;
     482             : 
     483             :                                         case E2BIG:
     484           0 :                                                 break;
     485             : 
     486             :                                         default:
     487           0 :                                                 return PHP_ICONV_ERR_UNKNOWN;
     488             :                                 }
     489             : #else
     490             :                                 if (prev_in_left == in_left) {
     491             :                                         return PHP_ICONV_ERR_UNKNOWN;
     492             :                                 }
     493             : #endif
     494             :                         }
     495             : #if !ICONV_SUPPORTS_ERRNO
     496             :                         prev_in_left = in_left;
     497             : #endif
     498        2270 :                         ZSTR_LEN((d)->s) += (buf_growth - out_left);
     499        2270 :                         buf_growth <<= 1;
     500             :                 }
     501             :         } else {
     502             :                 for (;;) {
     503          14 :                         out_left = buf_growth - out_left;
     504          14 :                         smart_str_alloc(d, out_left, 0);
     505             : 
     506          14 :                         out_p = ZSTR_VAL((d)->s) + ZSTR_LEN((d)->s);
     507             : 
     508          14 :                         if (iconv(cd, NULL, NULL, (char **) &out_p, &out_left) == (size_t)0) {
     509          14 :                                 ZSTR_LEN((d)->s) += (buf_growth - out_left);
     510          14 :                                 break;
     511             :                         } else {
     512             : #if ICONV_SUPPORTS_ERRNO
     513           0 :                                 if (errno != E2BIG) {
     514           0 :                                         return PHP_ICONV_ERR_UNKNOWN;
     515             :                                 }
     516             : #else
     517             :                                 if (out_left != 0) {
     518             :                                         return PHP_ICONV_ERR_UNKNOWN;
     519             :                                 }
     520             : #endif
     521             :                         }
     522           0 :                         ZSTR_LEN((d)->s) += (buf_growth - out_left);
     523           0 :                         buf_growth <<= 1;
     524           0 :                 }
     525             :         }
     526        2288 :         return PHP_ICONV_ERR_SUCCESS;
     527             : }
     528             : /* }}} */
     529             : 
     530             : /* {{{ _php_iconv_appendc() */
     531        1882 : static php_iconv_err_t _php_iconv_appendc(smart_str *d, const char c, iconv_t cd)
     532             : {
     533        1882 :         return _php_iconv_appendl(d, &c, 1, cd);
     534             : }
     535             : /* }}} */
     536             : 
     537             : /* {{{ */
     538             : #if ICONV_BROKEN_IGNORE
     539         226 : static int _php_check_ignore(const char *charset)
     540             : {
     541         226 :   size_t clen = strlen(charset);
     542         226 :   if (clen >= 9 && strcmp("//IGNORE", charset+clen-8) == 0) {
     543           4 :     return 1;
     544             :   }
     545         222 :   if (clen >= 19 && strcmp("//IGNORE//TRANSLIT", charset+clen-18) == 0) {
     546           0 :     return 1;
     547             :   }
     548         222 :   return 0;
     549             : }
     550             : #else
     551             : #define _php_check_ignore(x) (0)
     552             : #endif
     553             : /* }}} */
     554             : 
     555             : /* {{{ php_iconv_string()
     556             :  */
     557         226 : PHP_ICONV_API php_iconv_err_t php_iconv_string(const char *in_p, size_t in_len, zend_string **out, const char *out_charset, const char *in_charset)
     558             : {
     559             : #if !ICONV_SUPPORTS_ERRNO
     560             :         size_t in_size, out_size, out_left;
     561             :         char *out_p;
     562             :         iconv_t cd;
     563             :         size_t result;
     564             :         zend_string *ret, *out_buffer;
     565             : 
     566             :         /*
     567             :           This is not the right way to get output size...
     568             :           This is not space efficient for large text.
     569             :           This is also problem for encoding like UTF-7/UTF-8/ISO-2022 which
     570             :           a single char can be more than 4 bytes.
     571             :           I added 15 extra bytes for safety. <yohgaki@php.net>
     572             :         */
     573             :         out_size = in_len * sizeof(int) + 15;
     574             :         out_left = out_size;
     575             : 
     576             :         in_size = in_len;
     577             : 
     578             :         cd = iconv_open(out_charset, in_charset);
     579             : 
     580             :         if (cd == (iconv_t)(-1)) {
     581             :                 return PHP_ICONV_ERR_UNKNOWN;
     582             :         }
     583             : 
     584             :         out_buffer = zend_string_alloc(out_size, 0);
     585             :         out_p = ZSTR_VAL(out_buffer);
     586             : 
     587             : #ifdef NETWARE
     588             :         result = iconv(cd, (char **) &in_p, &in_size, (char **)
     589             : #else
     590             :         result = iconv(cd, (const char **) &in_p, &in_size, (char **)
     591             : #endif
     592             :                                 &out_p, &out_left);
     593             : 
     594             :         if (result == (size_t)(-1)) {
     595             :                 zend_string_free(out_buffer);
     596             :                 return PHP_ICONV_ERR_UNKNOWN;
     597             :         }
     598             : 
     599             :         if (out_left < 8) {
     600             :                 size_t pos = out_p - ZSTR_VAL(out_buffer);
     601             :                 out_buffer = zend_string_extend(out_buffer, out_size + 8, 0);
     602             :                 out_p = ZSTR_VAL(out_buffer) + pos;
     603             :                 out_size += 7;
     604             :                 out_left += 7;
     605             :         }
     606             : 
     607             :         /* flush the shift-out sequences */
     608             :         result = iconv(cd, NULL, NULL, &out_p, &out_left);
     609             : 
     610             :         if (result == (size_t)(-1)) {
     611             :                 zend_string_free(out_buffer);
     612             :                 return PHP_ICONV_ERR_UNKNOWN;
     613             :         }
     614             : 
     615             :         ZSTR_VAL(out_buffer)[out_size - out_left] = '\0';
     616             :         ZSTR_LEN(out_buffer) = out_size - out_left;
     617             : 
     618             :         iconv_close(cd);
     619             : 
     620             :         *out = out_buffer;
     621             :         return PHP_ICONV_ERR_SUCCESS;
     622             : 
     623             : #else
     624             :         /*
     625             :           iconv supports errno. Handle it better way.
     626             :         */
     627             :         iconv_t cd;
     628             :         size_t in_left, out_size, out_left;
     629             :         char *out_p;
     630         226 :         size_t bsz, result = 0;
     631         226 :         php_iconv_err_t retval = PHP_ICONV_ERR_SUCCESS;
     632             :         zend_string *out_buf;
     633         226 :         int ignore_ilseq = _php_check_ignore(out_charset);
     634             : 
     635         226 :         *out = NULL;
     636             : 
     637         226 :         cd = iconv_open(out_charset, in_charset);
     638             : 
     639         226 :         if (cd == (iconv_t)(-1)) {
     640          27 :                 if (errno == EINVAL) {
     641          27 :                         return PHP_ICONV_ERR_WRONG_CHARSET;
     642             :                 } else {
     643           0 :                         return PHP_ICONV_ERR_CONVERTER;
     644             :                 }
     645             :         }
     646         199 :         in_left= in_len;
     647         199 :         out_left = in_len + 32; /* Avoid realloc() most cases */
     648         199 :         out_size = 0;
     649         199 :         bsz = out_left;
     650         199 :         out_buf = zend_string_alloc(bsz, 0);
     651         199 :         out_p = ZSTR_VAL(out_buf);
     652             : 
     653         407 :         while (in_left > 0) {
     654         208 :                 result = iconv(cd, (char **) &in_p, &in_left, (char **) &out_p, &out_left);
     655         208 :                 out_size = bsz - out_left;
     656         208 :                 if (result == (size_t)(-1)) {
     657          15 :                         if (ignore_ilseq && errno == EILSEQ) {
     658           2 :                                 if (in_left <= 1) {
     659           2 :                                         result = 0;
     660             :                                 } else {
     661           0 :                                         errno = 0;
     662           0 :                                         in_p++;
     663           0 :                                         in_left--;
     664           0 :                                         continue;
     665             :                                 }
     666             :                         }
     667             : 
     668          15 :                         if (errno == E2BIG && in_left > 0) {
     669             :                                 /* converted string is longer than out buffer */
     670           9 :                                 bsz += in_len;
     671             : 
     672           9 :                                 out_buf = zend_string_extend(out_buf, bsz, 0);
     673           9 :                                 out_p = ZSTR_VAL(out_buf);
     674           9 :                                 out_p += out_size;
     675           9 :                                 out_left = bsz - out_size;
     676           9 :                                 continue;
     677             :                         }
     678             :                 }
     679         199 :                 break;
     680             :         }
     681             : 
     682         199 :         if (result != (size_t)(-1)) {
     683             :                 /* flush the shift-out sequences */
     684             :                 for (;;) {
     685         195 :                         result = iconv(cd, NULL, NULL, (char **) &out_p, &out_left);
     686         195 :                         out_size = bsz - out_left;
     687             : 
     688         195 :                         if (result != (size_t)(-1)) {
     689         195 :                                 break;
     690             :                         }
     691             : 
     692           0 :                         if (errno == E2BIG) {
     693           0 :                                 bsz += 16;
     694           0 :                                 out_buf = zend_string_extend(out_buf, bsz, 0);
     695           0 :                                 out_p = ZSTR_VAL(out_buf);
     696           0 :                                 out_p += out_size;
     697           0 :                                 out_left = bsz - out_size;
     698             :                         } else {
     699           0 :                                 break;
     700             :                         }
     701           0 :                 }
     702             :         }
     703             : 
     704         199 :         iconv_close(cd);
     705             : 
     706         199 :         if (result == (size_t)(-1)) {
     707           4 :                 switch (errno) {
     708             :                         case EINVAL:
     709           2 :                                 retval = PHP_ICONV_ERR_ILLEGAL_CHAR;
     710           2 :                                 break;
     711             : 
     712             :                         case EILSEQ:
     713           2 :                                 retval = PHP_ICONV_ERR_ILLEGAL_SEQ;
     714           2 :                                 break;
     715             : 
     716             :                         case E2BIG:
     717             :                                 /* should not happen */
     718           0 :                                 retval = PHP_ICONV_ERR_TOO_BIG;
     719           0 :                                 break;
     720             : 
     721             :                         default:
     722             :                                 /* other error */
     723             :                                 zend_string_free(out_buf);
     724           0 :                                 return PHP_ICONV_ERR_UNKNOWN;
     725             :                 }
     726             :         }
     727         199 :         *out_p = '\0';
     728         199 :         ZSTR_LEN(out_buf) = out_size;
     729         199 :         *out = out_buf;
     730         199 :         return retval;
     731             : #endif
     732             : }
     733             : /* }}} */
     734             : 
     735             : /* {{{ _php_iconv_strlen() */
     736         113 : static php_iconv_err_t _php_iconv_strlen(size_t *pretval, const char *str, size_t nbytes, const char *enc)
     737             : {
     738             :         char buf[GENERIC_SUPERSET_NBYTES*2];
     739             : 
     740         113 :         php_iconv_err_t err = PHP_ICONV_ERR_SUCCESS;
     741             : 
     742             :         iconv_t cd;
     743             : 
     744             :         const char *in_p;
     745             :         size_t in_left;
     746             : 
     747             :         char *out_p;
     748             :         size_t out_left;
     749             : 
     750             :         size_t cnt;
     751             : 
     752         113 :         *pretval = (size_t)-1;
     753             : 
     754         113 :         cd = iconv_open(GENERIC_SUPERSET_NAME, enc);
     755             : 
     756         113 :         if (cd == (iconv_t)(-1)) {
     757             : #if ICONV_SUPPORTS_ERRNO
     758          13 :                 if (errno == EINVAL) {
     759          13 :                         return PHP_ICONV_ERR_WRONG_CHARSET;
     760             :                 } else {
     761           0 :                         return PHP_ICONV_ERR_CONVERTER;
     762             :                 }
     763             : #else
     764             :                 return PHP_ICONV_ERR_UNKNOWN;
     765             : #endif
     766             :         }
     767             : 
     768         100 :         errno = 0;
     769         100 :         out_left = 0;
     770             : 
     771        3439 :         for (in_p = str, in_left = nbytes, cnt = 0; in_left > 0; cnt+=2) {
     772             :                 size_t prev_in_left;
     773        3339 :                 out_p = buf;
     774        3339 :                 out_left = sizeof(buf);
     775             : 
     776        3339 :                 prev_in_left = in_left;
     777             : 
     778        3339 :                 if (iconv(cd, (char **)&in_p, &in_left, (char **) &out_p, &out_left) == (size_t)-1) {
     779        3250 :                         if (prev_in_left == in_left) {
     780           0 :                                 break;
     781             :                         }
     782             :                 }
     783             :         }
     784             : 
     785         100 :         if (out_left > 0) {
     786          39 :                 cnt -= out_left / GENERIC_SUPERSET_NBYTES;
     787             :         }
     788             : 
     789             : #if ICONV_SUPPORTS_ERRNO
     790         100 :         switch (errno) {
     791             :                 case EINVAL:
     792           0 :                         err = PHP_ICONV_ERR_ILLEGAL_CHAR;
     793           0 :                         break;
     794             : 
     795             :                 case EILSEQ:
     796           0 :                         err = PHP_ICONV_ERR_ILLEGAL_SEQ;
     797           0 :                         break;
     798             : 
     799             :                 case E2BIG:
     800             :                 case 0:
     801         100 :                         *pretval = cnt;
     802         100 :                         break;
     803             : 
     804             :                 default:
     805           0 :                         err = PHP_ICONV_ERR_UNKNOWN;
     806             :                         break;
     807             :         }
     808             : #else
     809             :         *pretval = cnt;
     810             : #endif
     811             : 
     812         100 :         iconv_close(cd);
     813             : 
     814         100 :         return err;
     815             : }
     816             : 
     817             : /* }}} */
     818             : 
     819             : /* {{{ _php_iconv_substr() */
     820          19 : static php_iconv_err_t _php_iconv_substr(smart_str *pretval,
     821             :         const char *str, size_t nbytes, zend_long offset, zend_long len, const char *enc)
     822             : {
     823             :         char buf[GENERIC_SUPERSET_NBYTES];
     824             : 
     825          19 :         php_iconv_err_t err = PHP_ICONV_ERR_SUCCESS;
     826             : 
     827             :         iconv_t cd1, cd2;
     828             : 
     829             :         const char *in_p;
     830             :         size_t in_left;
     831             : 
     832             :         char *out_p;
     833             :         size_t out_left;
     834             : 
     835             :         size_t cnt;
     836             :         size_t total_len;
     837             : 
     838          19 :         err = _php_iconv_strlen(&total_len, str, nbytes, enc);
     839          19 :         if (err != PHP_ICONV_ERR_SUCCESS) {
     840           1 :                 return err;
     841             :         }
     842             : 
     843          18 :         if (len < 0) {
     844           3 :                 if ((len += (total_len - offset)) < 0) {
     845           2 :                         return PHP_ICONV_ERR_SUCCESS;
     846             :                 }
     847             :         }
     848             : 
     849          16 :         if (offset < 0) {
     850           1 :                 if ((offset += total_len) < 0) {
     851           0 :                         return PHP_ICONV_ERR_SUCCESS;
     852             :                 }
     853             :         }
     854             : 
     855          16 :         if((size_t)len > total_len) {
     856           3 :                 len = total_len;
     857             :         }
     858             : 
     859             : 
     860          16 :         if ((size_t)offset > total_len) {
     861           1 :                 return PHP_ICONV_ERR_SUCCESS;
     862             :         }
     863             : 
     864          15 :         if ((size_t)(offset + len) > total_len ) {
     865             :                 /* trying to compute the length */
     866           4 :                 len = total_len - offset;
     867             :         }
     868             : 
     869          15 :         if (len == 0) {
     870             :                 smart_str_appendl(pretval, "", 0);
     871             :                 smart_str_0(pretval);
     872           2 :                 return PHP_ICONV_ERR_SUCCESS;
     873             :         }
     874             : 
     875          13 :         cd1 = iconv_open(GENERIC_SUPERSET_NAME, enc);
     876             : 
     877          13 :         if (cd1 == (iconv_t)(-1)) {
     878             : #if ICONV_SUPPORTS_ERRNO
     879           0 :                 if (errno == EINVAL) {
     880           0 :                         return PHP_ICONV_ERR_WRONG_CHARSET;
     881             :                 } else {
     882           0 :                         return PHP_ICONV_ERR_CONVERTER;
     883             :                 }
     884             : #else
     885             :                 return PHP_ICONV_ERR_UNKNOWN;
     886             : #endif
     887             :         }
     888             : 
     889          13 :         cd2 = (iconv_t)NULL;
     890          13 :         errno = 0;
     891             : 
     892         114 :         for (in_p = str, in_left = nbytes, cnt = 0; in_left > 0 && len > 0; ++cnt) {
     893             :                 size_t prev_in_left;
     894         101 :                 out_p = buf;
     895         101 :                 out_left = sizeof(buf);
     896             : 
     897         101 :                 prev_in_left = in_left;
     898             : 
     899         101 :                 if (iconv(cd1, (char **)&in_p, &in_left, (char **) &out_p, &out_left) == (size_t)-1) {
     900          96 :                         if (prev_in_left == in_left) {
     901           0 :                                 break;
     902             :                         }
     903             :                 }
     904             : 
     905         101 :                 if ((zend_long)cnt >= offset) {
     906          67 :                         if (cd2 == (iconv_t)NULL) {
     907          13 :                                 cd2 = iconv_open(enc, GENERIC_SUPERSET_NAME);
     908             : 
     909          13 :                                 if (cd2 == (iconv_t)(-1)) {
     910           0 :                                         cd2 = (iconv_t)NULL;
     911             : #if ICONV_SUPPORTS_ERRNO
     912           0 :                                         if (errno == EINVAL) {
     913           0 :                                                 err = PHP_ICONV_ERR_WRONG_CHARSET;
     914             :                                         } else {
     915           0 :                                                 err = PHP_ICONV_ERR_CONVERTER;
     916             :                                         }
     917             : #else
     918             :                                         err = PHP_ICONV_ERR_UNKNOWN;
     919             : #endif
     920           0 :                                         break;
     921             :                                 }
     922             :                         }
     923             : 
     924          67 :                         if (_php_iconv_appendl(pretval, buf, sizeof(buf), cd2) != PHP_ICONV_ERR_SUCCESS) {
     925           0 :                                 break;
     926             :                         }
     927          67 :                         --len;
     928             :                 }
     929             : 
     930             :         }
     931             : 
     932             : #if ICONV_SUPPORTS_ERRNO
     933          13 :         switch (errno) {
     934             :                 case EINVAL:
     935           0 :                         err = PHP_ICONV_ERR_ILLEGAL_CHAR;
     936           0 :                         break;
     937             : 
     938             :                 case EILSEQ:
     939           0 :                         err = PHP_ICONV_ERR_ILLEGAL_SEQ;
     940             :                         break;
     941             : 
     942             :                 case E2BIG:
     943             :                         break;
     944             :         }
     945             : #endif
     946          13 :         if (err == PHP_ICONV_ERR_SUCCESS) {
     947          13 :                 if (cd2 != (iconv_t)NULL) {
     948          13 :                         _php_iconv_appendl(pretval, NULL, 0, cd2);
     949             :                 }
     950             :                 smart_str_0(pretval);
     951             :         }
     952             : 
     953          13 :         if (cd1 != (iconv_t)NULL) {
     954          13 :                 iconv_close(cd1);
     955             :         }
     956             : 
     957          13 :         if (cd2 != (iconv_t)NULL) {
     958          13 :                 iconv_close(cd2);
     959             :         }
     960          13 :         return err;
     961             : }
     962             : 
     963             : /* }}} */
     964             : 
     965             : /* {{{ _php_iconv_strpos() */
     966         191 : static php_iconv_err_t _php_iconv_strpos(size_t *pretval,
     967             :         const char *haystk, size_t haystk_nbytes,
     968             :         const char *ndl, size_t ndl_nbytes,
     969             :         zend_long offset, const char *enc)
     970             : {
     971             :         char buf[GENERIC_SUPERSET_NBYTES];
     972             : 
     973         191 :         php_iconv_err_t err = PHP_ICONV_ERR_SUCCESS;
     974             : 
     975             :         iconv_t cd;
     976             : 
     977             :         const char *in_p;
     978             :         size_t in_left;
     979             : 
     980             :         char *out_p;
     981             :         size_t out_left;
     982             : 
     983             :         size_t cnt;
     984             : 
     985             :         zend_string *ndl_buf;
     986             :         const char *ndl_buf_p;
     987             :         size_t ndl_buf_left;
     988             : 
     989             :         size_t match_ofs;
     990             : 
     991         191 :         *pretval = (size_t)-1;
     992             : 
     993         191 :         err = php_iconv_string(ndl, ndl_nbytes, &ndl_buf, GENERIC_SUPERSET_NAME, enc);
     994             : 
     995         191 :         if (err != PHP_ICONV_ERR_SUCCESS) {
     996          24 :                 if (ndl_buf != NULL) {
     997           0 :                         zend_string_free(ndl_buf);
     998             :                 }
     999          24 :                 return err;
    1000             :         }
    1001             : 
    1002         167 :         cd = iconv_open(GENERIC_SUPERSET_NAME, enc);
    1003             : 
    1004         167 :         if (cd == (iconv_t)(-1)) {
    1005           0 :                 if (ndl_buf != NULL) {
    1006           0 :                         zend_string_free(ndl_buf);
    1007             :                 }
    1008             : #if ICONV_SUPPORTS_ERRNO
    1009           0 :                 if (errno == EINVAL) {
    1010           0 :                         return PHP_ICONV_ERR_WRONG_CHARSET;
    1011             :                 } else {
    1012           0 :                         return PHP_ICONV_ERR_CONVERTER;
    1013             :                 }
    1014             : #else
    1015             :                 return PHP_ICONV_ERR_UNKNOWN;
    1016             : #endif
    1017             :         }
    1018             : 
    1019         167 :         ndl_buf_p = ZSTR_VAL(ndl_buf);
    1020         167 :         ndl_buf_left = ZSTR_LEN(ndl_buf);
    1021         167 :         match_ofs = (size_t)-1;
    1022             : 
    1023        7517 :         for (in_p = haystk, in_left = haystk_nbytes, cnt = 0; in_left > 0; ++cnt) {
    1024             :                 size_t prev_in_left;
    1025        7400 :                 out_p = buf;
    1026        7400 :                 out_left = sizeof(buf);
    1027             : 
    1028        7400 :                 prev_in_left = in_left;
    1029             : 
    1030        7400 :                 if (iconv(cd, (char **)&in_p, &in_left, (char **) &out_p, &out_left) == (size_t)-1) {
    1031        7281 :                         if (prev_in_left == in_left) {
    1032             : #if ICONV_SUPPORTS_ERRNO
    1033           0 :                                 switch (errno) {
    1034             :                                         case EINVAL:
    1035           0 :                                                 err = PHP_ICONV_ERR_ILLEGAL_CHAR;
    1036           0 :                                                 break;
    1037             : 
    1038             :                                         case EILSEQ:
    1039           0 :                                                 err = PHP_ICONV_ERR_ILLEGAL_SEQ;
    1040           0 :                                                 break;
    1041             : 
    1042             :                                         case E2BIG:
    1043           0 :                                                 break;
    1044             : 
    1045             :                                         default:
    1046           0 :                                                 err = PHP_ICONV_ERR_UNKNOWN;
    1047             :                                                 break;
    1048             :                                 }
    1049             : #endif
    1050           0 :                                 break;
    1051             :                         }
    1052             :                 }
    1053        7400 :                 if (offset >= 0) {
    1054        1714 :                         if (cnt >= (size_t)offset) {
    1055        1383 :                                 if (_php_iconv_memequal(buf, ndl_buf_p, sizeof(buf))) {
    1056         332 :                                         if (match_ofs == (size_t)-1) {
    1057          87 :                                                 match_ofs = cnt;
    1058             :                                         }
    1059         332 :                                         ndl_buf_p += GENERIC_SUPERSET_NBYTES;
    1060         332 :                                         ndl_buf_left -= GENERIC_SUPERSET_NBYTES;
    1061         332 :                                         if (ndl_buf_left == 0) {
    1062          50 :                                                 *pretval = match_ofs;
    1063          50 :                                                 break;
    1064             :                                         }
    1065             :                                 } else {
    1066             :                                         size_t i, j, lim;
    1067             : 
    1068        1051 :                                         i = 0;
    1069        1051 :                                         j = GENERIC_SUPERSET_NBYTES;
    1070        1051 :                                         lim = (size_t)(ndl_buf_p - ZSTR_VAL(ndl_buf));
    1071             : 
    1072        2285 :                                         while (j < lim) {
    1073         183 :                                                 if (_php_iconv_memequal(&ZSTR_VAL(ndl_buf)[j], &ZSTR_VAL(ndl_buf)[i],
    1074             :                                                            GENERIC_SUPERSET_NBYTES)) {
    1075           0 :                                                         i += GENERIC_SUPERSET_NBYTES;
    1076             :                                                 } else {
    1077         183 :                                                         j -= i;
    1078         183 :                                                         i = 0;
    1079             :                                                 }
    1080         183 :                                                 j += GENERIC_SUPERSET_NBYTES;
    1081             :                                         }
    1082             : 
    1083        1051 :                                         if (_php_iconv_memequal(buf, &ZSTR_VAL(ndl_buf)[i], sizeof(buf))) {
    1084         123 :                                                 match_ofs += (lim - i) / GENERIC_SUPERSET_NBYTES;
    1085         123 :                                                 i += GENERIC_SUPERSET_NBYTES;
    1086         123 :                                                 ndl_buf_p = &ZSTR_VAL(ndl_buf)[i];
    1087         123 :                                                 ndl_buf_left = ZSTR_LEN(ndl_buf) - i;
    1088             :                                         } else {
    1089         928 :                                                 match_ofs = (size_t)-1;
    1090         928 :                                                 ndl_buf_p = ZSTR_VAL(ndl_buf);
    1091         928 :                                                 ndl_buf_left = ZSTR_LEN(ndl_buf);
    1092             :                                         }
    1093             :                                 }
    1094             :                         }
    1095             :                 } else {
    1096        5686 :                         if (_php_iconv_memequal(buf, ndl_buf_p, sizeof(buf))) {
    1097         566 :                                 if (match_ofs == (size_t)-1) {
    1098         175 :                                         match_ofs = cnt;
    1099             :                                 }
    1100         566 :                                 ndl_buf_p += GENERIC_SUPERSET_NBYTES;
    1101         566 :                                 ndl_buf_left -= GENERIC_SUPERSET_NBYTES;
    1102         566 :                                 if (ndl_buf_left == 0) {
    1103          50 :                                         *pretval = match_ofs;
    1104          50 :                                         ndl_buf_p = ZSTR_VAL(ndl_buf);
    1105          50 :                                         ndl_buf_left = ZSTR_LEN(ndl_buf);
    1106          50 :                                         match_ofs = -1;
    1107             :                                 }
    1108             :                         } else {
    1109             :                                 size_t i, j, lim;
    1110             : 
    1111        5120 :                                 i = 0;
    1112        5120 :                                 j = GENERIC_SUPERSET_NBYTES;
    1113        5120 :                                 lim = (size_t)(ndl_buf_p - ZSTR_VAL(ndl_buf));
    1114             : 
    1115       10538 :                                 while (j < lim) {
    1116         298 :                                         if (_php_iconv_memequal(&ZSTR_VAL(ndl_buf)[j], &ZSTR_VAL(ndl_buf)[i],
    1117             :                                                            GENERIC_SUPERSET_NBYTES)) {
    1118           0 :                                                 i += GENERIC_SUPERSET_NBYTES;
    1119             :                                         } else {
    1120         298 :                                                 j -= i;
    1121         298 :                                                 i = 0;
    1122             :                                         }
    1123         298 :                                         j += GENERIC_SUPERSET_NBYTES;
    1124             :                                 }
    1125             : 
    1126        5120 :                                 if (_php_iconv_memequal(buf, &ZSTR_VAL(ndl_buf)[i], sizeof(buf))) {
    1127         179 :                                         match_ofs += (lim - i) / GENERIC_SUPERSET_NBYTES;
    1128         179 :                                         i += GENERIC_SUPERSET_NBYTES;
    1129         179 :                                         ndl_buf_p = &ZSTR_VAL(ndl_buf)[i];
    1130         179 :                                         ndl_buf_left = ZSTR_LEN(ndl_buf) - i;
    1131             :                                 } else {
    1132        4941 :                                         match_ofs = (size_t)-1;
    1133        4941 :                                         ndl_buf_p = ZSTR_VAL(ndl_buf);
    1134        4941 :                                         ndl_buf_left = ZSTR_LEN(ndl_buf);
    1135             :                                 }
    1136             :                         }
    1137             :                 }
    1138             :         }
    1139             : 
    1140         167 :         if (ndl_buf) {
    1141         167 :                 zend_string_free(ndl_buf);
    1142             :         }
    1143             : 
    1144         167 :         iconv_close(cd);
    1145             : 
    1146         167 :         return err;
    1147             : }
    1148             : /* }}} */
    1149             : 
    1150             : /* {{{ _php_iconv_mime_encode() */
    1151          83 : static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fname, size_t fname_nbytes, const char *fval, size_t fval_nbytes, size_t max_line_len, const char *lfchars, php_iconv_enc_scheme_t enc_scheme, const char *out_charset, const char *enc)
    1152             : {
    1153          83 :         php_iconv_err_t err = PHP_ICONV_ERR_SUCCESS;
    1154          83 :         iconv_t cd = (iconv_t)(-1), cd_pl = (iconv_t)(-1);
    1155          83 :         size_t char_cnt = 0;
    1156             :         size_t out_charset_len;
    1157             :         size_t lfchars_len;
    1158          83 :         char *buf = NULL;
    1159             :         const char *in_p;
    1160             :         size_t in_left;
    1161             :         char *out_p;
    1162             :         size_t out_left;
    1163          83 :         zend_string *encoded = NULL;
    1164             :         static int qp_table[256] = {
    1165             :                 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x00 */
    1166             :                 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x10 */
    1167             :                 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x20 */
    1168             :                 1, 1, 1, 1, 1, 1, 1 ,1, 1, 1, 1, 1, 1, 3, 1, 3, /* 0x30 */
    1169             :                 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 */
    1170             :                 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, /* 0x50 */
    1171             :                 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 */
    1172             :                 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, /* 0x70 */
    1173             :                 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x80 */
    1174             :                 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x90 */
    1175             :                 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xA0 */
    1176             :                 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xB0 */
    1177             :                 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xC0 */
    1178             :                 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xD0 */
    1179             :                 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xE0 */
    1180             :                 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3  /* 0xF0 */
    1181             :         };
    1182             : 
    1183          83 :         out_charset_len = strlen(out_charset);
    1184          83 :         lfchars_len = strlen(lfchars);
    1185             : 
    1186         159 :         if ((fname_nbytes + 2) >= max_line_len
    1187          76 :                 || (out_charset_len + 12) >= max_line_len) {
    1188             :                 /* field name is too long */
    1189          24 :                 err = PHP_ICONV_ERR_TOO_BIG;
    1190          24 :                 goto out;
    1191             :         }
    1192             : 
    1193          59 :         cd_pl = iconv_open(ICONV_ASCII_ENCODING, enc);
    1194          59 :         if (cd_pl == (iconv_t)(-1)) {
    1195             : #if ICONV_SUPPORTS_ERRNO
    1196           0 :                 if (errno == EINVAL) {
    1197           0 :                         err = PHP_ICONV_ERR_WRONG_CHARSET;
    1198             :                 } else {
    1199           0 :                         err = PHP_ICONV_ERR_CONVERTER;
    1200             :                 }
    1201             : #else
    1202             :                 err = PHP_ICONV_ERR_UNKNOWN;
    1203             : #endif
    1204           0 :                 goto out;
    1205             :         }
    1206             : 
    1207          59 :         cd = iconv_open(out_charset, enc);
    1208          59 :         if (cd == (iconv_t)(-1)) {
    1209             : #if ICONV_SUPPORTS_ERRNO
    1210           0 :                 if (errno == EINVAL) {
    1211           0 :                         err = PHP_ICONV_ERR_WRONG_CHARSET;
    1212             :                 } else {
    1213           0 :                         err = PHP_ICONV_ERR_CONVERTER;
    1214             :                 }
    1215             : #else
    1216             :                 err = PHP_ICONV_ERR_UNKNOWN;
    1217             : #endif
    1218           0 :                 goto out;
    1219             :         }
    1220             : 
    1221          59 :         buf = safe_emalloc(1, max_line_len, 5);
    1222             : 
    1223          59 :         char_cnt = max_line_len;
    1224             : 
    1225          59 :         _php_iconv_appendl(pretval, fname, fname_nbytes, cd_pl);
    1226          59 :         char_cnt -= fname_nbytes;
    1227             :         smart_str_appendl(pretval, ": ", sizeof(": ") - 1);
    1228          59 :         char_cnt -= 2;
    1229             : 
    1230          59 :         in_p = fval;
    1231          59 :         in_left = fval_nbytes;
    1232             : 
    1233             :         do {
    1234             :                 size_t prev_in_left;
    1235             :                 size_t out_size;
    1236             : 
    1237         180 :                 if (char_cnt < (out_charset_len + 12)) {
    1238             :                         /* lfchars must be encoded in ASCII here*/
    1239             :                         smart_str_appendl(pretval, lfchars, lfchars_len);
    1240             :                         smart_str_appendc(pretval, ' ');
    1241         126 :                         char_cnt = max_line_len - 1;
    1242             :                 }
    1243             : 
    1244             :                 smart_str_appendl(pretval, "=?", sizeof("=?") - 1);
    1245         180 :                 char_cnt -= 2;
    1246             :                 smart_str_appendl(pretval, out_charset, out_charset_len);
    1247         180 :                 char_cnt -= out_charset_len;
    1248             :                 smart_str_appendc(pretval, '?');
    1249         180 :                 char_cnt --;
    1250             : 
    1251         180 :                 switch (enc_scheme) {
    1252             :                         case PHP_ICONV_ENC_SCHEME_BASE64: {
    1253             :                                 size_t ini_in_left;
    1254             :                                 const char *ini_in_p;
    1255         174 :                                 size_t out_reserved = 4;
    1256             : 
    1257             :                                 smart_str_appendc(pretval, 'B');
    1258         174 :                                 char_cnt--;
    1259             :                                 smart_str_appendc(pretval, '?');
    1260         174 :                                 char_cnt--;
    1261             : 
    1262         174 :                                 prev_in_left = ini_in_left = in_left;
    1263         174 :                                 ini_in_p = in_p;
    1264             : 
    1265         174 :                                 out_size = (char_cnt - 2) / 4 * 3;
    1266             : 
    1267             :                                 for (;;) {
    1268         174 :                                         out_p = buf;
    1269             : 
    1270         174 :                                         if (out_size <= out_reserved) {
    1271           6 :                                                 err = PHP_ICONV_ERR_TOO_BIG;
    1272           6 :                                                 goto out;
    1273             :                                         }
    1274             : 
    1275         168 :                                         out_left = out_size - out_reserved;
    1276             : 
    1277         168 :                                         if (iconv(cd, (char **)&in_p, &in_left, (char **) &out_p, &out_left) == (size_t)-1) {
    1278             : #if ICONV_SUPPORTS_ERRNO
    1279         122 :                                                 switch (errno) {
    1280             :                                                         case EINVAL:
    1281           0 :                                                                 err = PHP_ICONV_ERR_ILLEGAL_CHAR;
    1282           0 :                                                                 goto out;
    1283             : 
    1284             :                                                         case EILSEQ:
    1285           0 :                                                                 err = PHP_ICONV_ERR_ILLEGAL_SEQ;
    1286           0 :                                                                 goto out;
    1287             : 
    1288             :                                                         case E2BIG:
    1289         122 :                                                                 if (prev_in_left == in_left) {
    1290           6 :                                                                         err = PHP_ICONV_ERR_TOO_BIG;
    1291           6 :                                                                         goto out;
    1292             :                                                                 }
    1293         116 :                                                                 break;
    1294             : 
    1295             :                                                         default:
    1296           0 :                                                                 err = PHP_ICONV_ERR_UNKNOWN;
    1297           0 :                                                                 goto out;
    1298             :                                                 }
    1299             : #else
    1300             :                                                 if (prev_in_left == in_left) {
    1301             :                                                         err = PHP_ICONV_ERR_UNKNOWN;
    1302             :                                                         goto out;
    1303             :                                                 }
    1304             : #endif
    1305             :                                         }
    1306             : 
    1307         162 :                                         out_left += out_reserved;
    1308             : 
    1309         162 :                                         if (iconv(cd, NULL, NULL, (char **) &out_p, &out_left) == (size_t)-1) {
    1310             : #if ICONV_SUPPORTS_ERRNO
    1311           0 :                                                 if (errno != E2BIG) {
    1312           0 :                                                         err = PHP_ICONV_ERR_UNKNOWN;
    1313           0 :                                                         goto out;
    1314             :                                                 }
    1315             : #else
    1316             :                                                 if (out_left != 0) {
    1317             :                                                         err = PHP_ICONV_ERR_UNKNOWN;
    1318             :                                                         goto out;
    1319             :                                                 }
    1320             : #endif
    1321             :                                         } else {
    1322         162 :                                                 break;
    1323             :                                         }
    1324             : 
    1325           0 :                                         if (iconv(cd, NULL, NULL, NULL, NULL) == (size_t)-1) {
    1326           0 :                                                 err = PHP_ICONV_ERR_UNKNOWN;
    1327           0 :                                                 goto out;
    1328             :                                         }
    1329             : 
    1330           0 :                                         out_reserved += 4;
    1331           0 :                                         in_left = ini_in_left;
    1332           0 :                                         in_p = ini_in_p;
    1333           0 :                                 }
    1334             : 
    1335         162 :                                 prev_in_left = in_left;
    1336             : 
    1337         162 :                                 encoded = php_base64_encode((unsigned char *) buf, (out_size - out_left));
    1338             : 
    1339         162 :                                 if (char_cnt < ZSTR_LEN(encoded)) {
    1340             :                                         /* something went wrong! */
    1341           0 :                                         err = PHP_ICONV_ERR_UNKNOWN;
    1342           0 :                                         goto out;
    1343             :                                 }
    1344             : 
    1345         162 :                                 smart_str_appendl(pretval, ZSTR_VAL(encoded), ZSTR_LEN(encoded));
    1346         162 :                                 char_cnt -= ZSTR_LEN(encoded);
    1347             :                                 smart_str_appendl(pretval, "?=", sizeof("?=") - 1);
    1348         162 :                                 char_cnt -= 2;
    1349             : 
    1350             :                                 zend_string_release(encoded);
    1351         162 :                                 encoded = NULL;
    1352         162 :                         } break; /* case PHP_ICONV_ENC_SCHEME_BASE64: */
    1353             : 
    1354             :                         case PHP_ICONV_ENC_SCHEME_QPRINT: {
    1355             :                                 size_t ini_in_left;
    1356             :                                 const char *ini_in_p;
    1357             :                                 const unsigned char *p;
    1358             :                                 size_t nbytes_required;
    1359             : 
    1360             :                                 smart_str_appendc(pretval, 'Q');
    1361           6 :                                 char_cnt--;
    1362             :                                 smart_str_appendc(pretval, '?');
    1363           6 :                                 char_cnt--;
    1364             : 
    1365           6 :                                 prev_in_left = ini_in_left = in_left;
    1366           6 :                                 ini_in_p = in_p;
    1367             : 
    1368          12 :                                 for (out_size = (char_cnt - 2) / 3; out_size > 0;) {
    1369             : #if !ICONV_SUPPORTS_ERRNO
    1370             :                                         size_t prev_out_left;
    1371             : #endif
    1372             : 
    1373           6 :                                         nbytes_required = 0;
    1374             : 
    1375           6 :                                         out_p = buf;
    1376           6 :                                         out_left = out_size;
    1377             : 
    1378           6 :                                         if (iconv(cd, (char **)&in_p, &in_left, (char **) &out_p, &out_left) == (size_t)-1) {
    1379             : #if ICONV_SUPPORTS_ERRNO
    1380           5 :                                                 switch (errno) {
    1381             :                                                         case EINVAL:
    1382           0 :                                                                 err = PHP_ICONV_ERR_ILLEGAL_CHAR;
    1383           0 :                                                                 goto out;
    1384             : 
    1385             :                                                         case EILSEQ:
    1386           0 :                                                                 err = PHP_ICONV_ERR_ILLEGAL_SEQ;
    1387           0 :                                                                 goto out;
    1388             : 
    1389             :                                                         case E2BIG:
    1390           5 :                                                                 if (prev_in_left == in_left) {
    1391           0 :                                                                         err = PHP_ICONV_ERR_UNKNOWN;
    1392           0 :                                                                         goto out;
    1393             :                                                                 }
    1394           5 :                                                                 break;
    1395             : 
    1396             :                                                         default:
    1397           0 :                                                                 err = PHP_ICONV_ERR_UNKNOWN;
    1398           0 :                                                                 goto out;
    1399             :                                                 }
    1400             : #else
    1401             :                                                 if (prev_in_left == in_left) {
    1402             :                                                         err = PHP_ICONV_ERR_UNKNOWN;
    1403             :                                                         goto out;
    1404             :                                                 }
    1405             : #endif
    1406             :                                         }
    1407             : #if !ICONV_SUPPORTS_ERRNO
    1408             :                                         prev_out_left = out_left;
    1409             : #endif
    1410           6 :                                         if (iconv(cd, NULL, NULL, (char **) &out_p, &out_left) == (size_t)-1) {
    1411             : #if ICONV_SUPPORTS_ERRNO
    1412           0 :                                                 if (errno != E2BIG) {
    1413           0 :                                                         err = PHP_ICONV_ERR_UNKNOWN;
    1414           0 :                                                         goto out;
    1415             :                                                 }
    1416             : #else
    1417             :                                                 if (out_left == prev_out_left) {
    1418             :                                                         err = PHP_ICONV_ERR_UNKNOWN;
    1419             :                                                         goto out;
    1420             :                                                 }
    1421             : #endif
    1422             :                                         }
    1423             : 
    1424          24 :                                         for (p = (unsigned char *)buf; p < (unsigned char *)out_p; p++) {
    1425          18 :                                                 nbytes_required += qp_table[*p];
    1426             :                                         }
    1427             : 
    1428           6 :                                         if (nbytes_required <= char_cnt - 2) {
    1429           6 :                                                 break;
    1430             :                                         }
    1431             : 
    1432           0 :                                         out_size -= ((nbytes_required - (char_cnt - 2)) + 1) / 3;
    1433           0 :                                         in_left = ini_in_left;
    1434           0 :                                         in_p = ini_in_p;
    1435             :                                 }
    1436             : 
    1437          24 :                                 for (p = (unsigned char *)buf; p < (unsigned char *)out_p; p++) {
    1438          18 :                                         if (qp_table[*p] == 1) {
    1439           0 :                                                 smart_str_appendc(pretval, *(char *)p);
    1440           0 :                                                 char_cnt--;
    1441             :                                         } else {
    1442             :                                                 static char qp_digits[] = "0123456789ABCDEF";
    1443             :                                                 smart_str_appendc(pretval, '=');
    1444          18 :                                                 smart_str_appendc(pretval, qp_digits[(*p >> 4) & 0x0f]);
    1445          18 :                                                 smart_str_appendc(pretval, qp_digits[(*p & 0x0f)]);
    1446          18 :                                                 char_cnt -= 3;
    1447             :                                         }
    1448             :                                 }
    1449             : 
    1450             :                                 smart_str_appendl(pretval, "?=", sizeof("?=") - 1);
    1451           6 :                                 char_cnt -= 2;
    1452             : 
    1453           6 :                                 if (iconv(cd, NULL, NULL, NULL, NULL) == (size_t)-1) {
    1454           0 :                                         err = PHP_ICONV_ERR_UNKNOWN;
    1455           0 :                                         goto out;
    1456             :                                 }
    1457             : 
    1458             :                         } break; /* case PHP_ICONV_ENC_SCHEME_QPRINT: */
    1459             :                 }
    1460         168 :         } while (in_left > 0);
    1461             : 
    1462             :         smart_str_0(pretval);
    1463             : 
    1464             : out:
    1465          83 :         if (cd != (iconv_t)(-1)) {
    1466          59 :                 iconv_close(cd);
    1467             :         }
    1468          83 :         if (cd_pl != (iconv_t)(-1)) {
    1469          59 :                 iconv_close(cd_pl);
    1470             :         }
    1471          83 :         if (encoded != NULL) {
    1472             :                 zend_string_release(encoded);
    1473             :         }
    1474          83 :         if (buf != NULL) {
    1475          59 :                 efree(buf);
    1476             :         }
    1477          83 :         return err;
    1478             : }
    1479             : /* }}} */
    1480             : 
    1481             : /* {{{ _php_iconv_mime_decode() */
    1482         122 : static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *str, size_t str_nbytes, const char *enc, const char **next_pos, int mode)
    1483             : {
    1484         122 :         php_iconv_err_t err = PHP_ICONV_ERR_SUCCESS;
    1485             : 
    1486         122 :         iconv_t cd = (iconv_t)(-1), cd_pl = (iconv_t)(-1);
    1487             : 
    1488             :         const char *p1;
    1489             :         size_t str_left;
    1490         122 :         unsigned int scan_stat = 0;
    1491         122 :         const char *csname = NULL;
    1492             :         size_t csname_len;
    1493         122 :         const char *encoded_text = NULL;
    1494         122 :         size_t encoded_text_len = 0;
    1495         122 :         const char *encoded_word = NULL;
    1496         122 :         const char *spaces = NULL;
    1497             : 
    1498         122 :         php_iconv_enc_scheme_t enc_scheme = PHP_ICONV_ENC_SCHEME_BASE64;
    1499             : 
    1500         122 :         if (next_pos != NULL) {
    1501          46 :                 *next_pos = NULL;
    1502             :         }
    1503             : 
    1504         122 :         cd_pl = iconv_open(enc, ICONV_ASCII_ENCODING);
    1505             : 
    1506         122 :         if (cd_pl == (iconv_t)(-1)) {
    1507             : #if ICONV_SUPPORTS_ERRNO
    1508          15 :                 if (errno == EINVAL) {
    1509          15 :                         err = PHP_ICONV_ERR_WRONG_CHARSET;
    1510             :                 } else {
    1511           0 :                         err = PHP_ICONV_ERR_CONVERTER;
    1512             :                 }
    1513             : #else
    1514             :                 err = PHP_ICONV_ERR_UNKNOWN;
    1515             : #endif
    1516          15 :                 goto out;
    1517             :         }
    1518             : 
    1519         107 :         p1 = str;
    1520        5818 :         for (str_left = str_nbytes; str_left > 0; str_left--, p1++) {
    1521        5714 :                 int eos = 0;
    1522             : 
    1523        5714 :                 switch (scan_stat) {
    1524             :                         case 0: /* expecting any character */
    1525        1676 :                                 switch (*p1) {
    1526             :                                         case '\r': /* part of an EOL sequence? */
    1527           0 :                                                 scan_stat = 7;
    1528           0 :                                                 break;
    1529             : 
    1530             :                                         case '\n':
    1531          22 :                                                 scan_stat = 8;
    1532          22 :                                                 break;
    1533             : 
    1534             :                                         case '=': /* first letter of an encoded chunk */
    1535          10 :                                                 encoded_word = p1;
    1536          10 :                                                 scan_stat = 1;
    1537          10 :                                                 break;
    1538             : 
    1539             :                                         case ' ': case '\t': /* a chunk of whitespaces */
    1540         126 :                                                 spaces = p1;
    1541         126 :                                                 scan_stat = 11;
    1542         126 :                                                 break;
    1543             : 
    1544             :                                         default: /* first letter of a non-encoded word */
    1545        1518 :                                                 _php_iconv_appendc(pretval, *p1, cd_pl);
    1546        1518 :                                                 encoded_word = NULL;
    1547        1518 :                                                 if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
    1548          15 :                                                         scan_stat = 12;
    1549             :                                                 }
    1550             :                                                 break;
    1551             :                                 }
    1552        1676 :                                 break;
    1553             : 
    1554             :                         case 1: /* expecting a delimiter */
    1555         122 :                                 if (*p1 != '?') {
    1556           7 :                                         err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
    1557           7 :                                         if (err != PHP_ICONV_ERR_SUCCESS) {
    1558           0 :                                                 goto out;
    1559             :                                         }
    1560           7 :                                         encoded_word = NULL;
    1561           7 :                                         if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
    1562           0 :                                                 scan_stat = 12;
    1563             :                                         } else {
    1564           7 :                                                 scan_stat = 0;
    1565             :                                         }
    1566           7 :                                         break;
    1567             :                                 }
    1568         115 :                                 csname = p1 + 1;
    1569         115 :                                 scan_stat = 2;
    1570         115 :                                 break;
    1571             : 
    1572             :                         case 2: /* expecting a charset name */
    1573        1221 :                                 switch (*p1) {
    1574             :                                         case '?': /* normal delimiter: encoding scheme follows */
    1575         101 :                                                 scan_stat = 3;
    1576         101 :                                                 break;
    1577             : 
    1578             :                                         case '*': /* new style delimiter: locale id follows */
    1579          14 :                                                 scan_stat = 10;
    1580             :                                                 break;
    1581             :                                 }
    1582        1221 :                                 if (scan_stat != 2) {
    1583             :                                         char tmpbuf[80];
    1584             : 
    1585         115 :                                         if (csname == NULL) {
    1586           0 :                                                 err = PHP_ICONV_ERR_MALFORMED;
    1587           0 :                                                 goto out;
    1588             :                                         }
    1589             : 
    1590         115 :                                         csname_len = (size_t)(p1 - csname);
    1591             : 
    1592         115 :                                         if (csname_len > sizeof(tmpbuf) - 1) {
    1593           0 :                                                 if ((mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR)) {
    1594           0 :                                                         err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
    1595           0 :                                                         if (err != PHP_ICONV_ERR_SUCCESS) {
    1596           0 :                                                                 goto out;
    1597             :                                                         }
    1598           0 :                                                         encoded_word = NULL;
    1599           0 :                                                         if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
    1600           0 :                                                                 scan_stat = 12;
    1601             :                                                         } else {
    1602           0 :                                                                 scan_stat = 0;
    1603             :                                                         }
    1604           0 :                                                         break;
    1605             :                                                 } else {
    1606           0 :                                                         err = PHP_ICONV_ERR_MALFORMED;
    1607           0 :                                                         goto out;
    1608             :                                                 }
    1609             :                                         }
    1610             : 
    1611         115 :                                         memcpy(tmpbuf, csname, csname_len);
    1612         115 :                                         tmpbuf[csname_len] = '\0';
    1613             : 
    1614         115 :                                         if (cd != (iconv_t)(-1)) {
    1615          66 :                                                 iconv_close(cd);
    1616             :                                         }
    1617             : 
    1618         115 :                                         cd = iconv_open(enc, tmpbuf);
    1619             : 
    1620         115 :                                         if (cd == (iconv_t)(-1)) {
    1621           6 :                                                 if ((mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR)) {
    1622             :                                                         /* Bad character set, but the user wants us to
    1623             :                                                          * press on. In this case, we'll just insert the
    1624             :                                                          * undecoded encoded word, since there isn't really
    1625             :                                                          * a more sensible behaviour available; the only
    1626             :                                                          * other options are to swallow the encoded word
    1627             :                                                          * entirely or decode it with an arbitrarily chosen
    1628             :                                                          * single byte encoding, both of which seem to have
    1629             :                                                          * a higher WTF factor than leaving it undecoded.
    1630             :                                                          *
    1631             :                                                          * Given this approach, we need to skip ahead to
    1632             :                                                          * the end of the encoded word. */
    1633           6 :                                                         int qmarks = 2;
    1634          78 :                                                         while (qmarks > 0 && str_left > 1) {
    1635          66 :                                                                 if (*(++p1) == '?') {
    1636          12 :                                                                         --qmarks;
    1637             :                                                                 }
    1638          66 :                                                                 --str_left;
    1639             :                                                         }
    1640             : 
    1641             :                                                         /* Look ahead to check for the terminating = that
    1642             :                                                          * should be there as well; if it's there, we'll
    1643             :                                                          * also include that. If it's not, there isn't much
    1644             :                                                          * we can do at this point. */
    1645           6 :                                                         if (*(p1 + 1) == '=') {
    1646           6 :                                                                 ++p1;
    1647           6 :                                                                 --str_left;
    1648             :                                                         }
    1649             : 
    1650           6 :                                                         err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
    1651           6 :                                                         if (err != PHP_ICONV_ERR_SUCCESS) {
    1652           0 :                                                                 goto out;
    1653             :                                                         }
    1654             : 
    1655             :                                                         /* Let's go back and see if there are further
    1656             :                                                          * encoded words or bare content, and hope they
    1657             :                                                          * might actually have a valid character set. */
    1658           6 :                                                         scan_stat = 12;
    1659           6 :                                                         break;
    1660             :                                                 } else {
    1661             : #if ICONV_SUPPORTS_ERRNO
    1662           0 :                                                         if (errno == EINVAL) {
    1663           0 :                                                                 err = PHP_ICONV_ERR_WRONG_CHARSET;
    1664             :                                                         } else {
    1665           0 :                                                                 err = PHP_ICONV_ERR_CONVERTER;
    1666             :                                                         }
    1667             : #else
    1668             :                                                         err = PHP_ICONV_ERR_UNKNOWN;
    1669             : #endif
    1670           0 :                                                         goto out;
    1671             :                                                 }
    1672             :                                         }
    1673             :                                 }
    1674        1215 :                                 break;
    1675             : 
    1676             :                         case 3: /* expecting a encoding scheme specifier */
    1677         109 :                                 switch (*p1) {
    1678             :                                         case 'b':
    1679             :                                         case 'B':
    1680          58 :                                                 enc_scheme = PHP_ICONV_ENC_SCHEME_BASE64;
    1681          58 :                                                 scan_stat = 4;
    1682          58 :                                                 break;
    1683             : 
    1684             :                                         case 'q':
    1685             :                                         case 'Q':
    1686          49 :                                                 enc_scheme = PHP_ICONV_ENC_SCHEME_QPRINT;
    1687          49 :                                                 scan_stat = 4;
    1688          49 :                                                 break;
    1689             : 
    1690             :                                         default:
    1691           2 :                                                 if ((mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR)) {
    1692           2 :                                                         err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
    1693           2 :                                                         if (err != PHP_ICONV_ERR_SUCCESS) {
    1694           0 :                                                                 goto out;
    1695             :                                                         }
    1696           2 :                                                         encoded_word = NULL;
    1697           2 :                                                         if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
    1698           1 :                                                                 scan_stat = 12;
    1699             :                                                         } else {
    1700           1 :                                                                 scan_stat = 0;
    1701             :                                                         }
    1702           2 :                                                         break;
    1703             :                                                 } else {
    1704           0 :                                                         err = PHP_ICONV_ERR_MALFORMED;
    1705           0 :                                                         goto out;
    1706             :                                                 }
    1707             :                                 }
    1708         109 :                                 break;
    1709             : 
    1710             :                         case 4: /* expecting a delimiter */
    1711         107 :                                 if (*p1 != '?') {
    1712           0 :                                         if ((mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR)) {
    1713             :                                                 /* pass the entire chunk through the converter */
    1714           0 :                                                 err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
    1715           0 :                                                 if (err != PHP_ICONV_ERR_SUCCESS) {
    1716           0 :                                                         goto out;
    1717             :                                                 }
    1718           0 :                                                 encoded_word = NULL;
    1719           0 :                                                 if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
    1720           0 :                                                         scan_stat = 12;
    1721             :                                                 } else {
    1722           0 :                                                         scan_stat = 0;
    1723             :                                                 }
    1724           0 :                                                 break;
    1725             :                                         } else {
    1726           0 :                                                 err = PHP_ICONV_ERR_MALFORMED;
    1727           0 :                                                 goto out;
    1728             :                                         }
    1729             :                                 }
    1730         107 :                                 encoded_text = p1 + 1;
    1731         107 :                                 scan_stat = 5;
    1732         107 :                                 break;
    1733             : 
    1734             :                         case 5: /* expecting an encoded portion */
    1735        1596 :                                 if (*p1 == '?') {
    1736         107 :                                         encoded_text_len = (size_t)(p1 - encoded_text);
    1737         107 :                                         scan_stat = 6;
    1738             :                                 }
    1739        1596 :                                 break;
    1740             : 
    1741             :                         case 7: /* expecting a "\n" character */
    1742           0 :                                 if (*p1 == '\n') {
    1743           0 :                                         scan_stat = 8;
    1744             :                                 } else {
    1745             :                                         /* bare CR */
    1746           0 :                                         _php_iconv_appendc(pretval, '\r', cd_pl);
    1747           0 :                                         _php_iconv_appendc(pretval, *p1, cd_pl);
    1748           0 :                                         scan_stat = 0;
    1749             :                                 }
    1750           0 :                                 break;
    1751             : 
    1752             :                         case 8: /* checking whether the following line is part of a
    1753             :                                            folded header */
    1754          80 :                                 if (*p1 != ' ' && *p1 != '\t') {
    1755          28 :                                         --p1;
    1756          28 :                                         str_left = 1; /* quit_loop */
    1757          28 :                                         break;
    1758             :                                 }
    1759          52 :                                 if (encoded_word == NULL) {
    1760           4 :                                         _php_iconv_appendc(pretval, ' ', cd_pl);
    1761             :                                 }
    1762          52 :                                 spaces = NULL;
    1763          52 :                                 scan_stat = 11;
    1764          52 :                                 break;
    1765             : 
    1766             :                         case 6: /* expecting a End-Of-Chunk character "=" */
    1767         107 :                                 if (*p1 != '=') {
    1768           4 :                                         if ((mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR)) {
    1769             :                                                 /* pass the entire chunk through the converter */
    1770           2 :                                                 err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
    1771           2 :                                                 if (err != PHP_ICONV_ERR_SUCCESS) {
    1772           0 :                                                         goto out;
    1773             :                                                 }
    1774           2 :                                                 encoded_word = NULL;
    1775           2 :                                                 if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
    1776           1 :                                                         scan_stat = 12;
    1777             :                                                 } else {
    1778           1 :                                                         scan_stat = 0;
    1779             :                                                 }
    1780           2 :                                                 break;
    1781             :                                         } else {
    1782           2 :                                                 err = PHP_ICONV_ERR_MALFORMED;
    1783           2 :                                                 goto out;
    1784             :                                         }
    1785             :                                 }
    1786         103 :                                 scan_stat = 9;
    1787         103 :                                 if (str_left == 1) {
    1788          24 :                                         eos = 1;
    1789             :                                 } else {
    1790          79 :                                         break;
    1791             :                                 }
    1792             : 
    1793             :                         case 9: /* choice point, seeing what to do next.*/
    1794         104 :                                 switch (*p1) {
    1795             :                                         default:
    1796             :                                                 /* Handle non-RFC-compliant formats
    1797             :                                                  *
    1798             :                                                  * RFC2047 requires the character that comes right
    1799             :                                                  * after an encoded word (chunk) to be a whitespace,
    1800             :                                                  * while there are lots of broken implementations that
    1801             :                                                  * generate such malformed headers that don't fulfill
    1802             :                                                  * that requirement.
    1803             :                                                  */
    1804          31 :                                                 if (!eos) {
    1805           7 :                                                         if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
    1806             :                                                                 /* pass the entire chunk through the converter */
    1807           2 :                                                                 err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
    1808           2 :                                                                 if (err != PHP_ICONV_ERR_SUCCESS) {
    1809           0 :                                                                         goto out;
    1810             :                                                                 }
    1811           2 :                                                                 scan_stat = 12;
    1812           2 :                                                                 break;
    1813             :                                                         }
    1814             :                                                 }
    1815             :                                                 /* break is omitted intentionally */
    1816             : 
    1817             :                                         case '\r': case '\n': case ' ': case '\t': {
    1818             :                                                 zend_string *decoded_text;
    1819             : 
    1820         102 :                                                 switch (enc_scheme) {
    1821             :                                                         case PHP_ICONV_ENC_SCHEME_BASE64:
    1822          58 :                                                                 decoded_text = php_base64_decode((unsigned char*)encoded_text, encoded_text_len);
    1823          58 :                                                                 break;
    1824             : 
    1825             :                                                         case PHP_ICONV_ENC_SCHEME_QPRINT:
    1826          44 :                                                                 decoded_text = php_quot_print_decode((unsigned char*)encoded_text, encoded_text_len, 1);
    1827          44 :                                                                 break;
    1828             :                                                         default:
    1829           0 :                                                                 decoded_text = NULL;
    1830             :                                                                 break;
    1831             :                                                 }
    1832             : 
    1833         102 :                                                 if (decoded_text == NULL) {
    1834           0 :                                                         if ((mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR)) {
    1835             :                                                                 /* pass the entire chunk through the converter */
    1836           0 :                                                                 err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
    1837           0 :                                                                 if (err != PHP_ICONV_ERR_SUCCESS) {
    1838           0 :                                                                         goto out;
    1839             :                                                                 }
    1840           0 :                                                                 encoded_word = NULL;
    1841           0 :                                                                 if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
    1842           0 :                                                                         scan_stat = 12;
    1843             :                                                                 } else {
    1844           0 :                                                                         scan_stat = 0;
    1845             :                                                                 }
    1846           0 :                                                                 break;
    1847             :                                                         } else {
    1848           0 :                                                                 err = PHP_ICONV_ERR_UNKNOWN;
    1849           0 :                                                                 goto out;
    1850             :                                                         }
    1851             :                                                 }
    1852             : 
    1853         102 :                                                 err = _php_iconv_appendl(pretval, ZSTR_VAL(decoded_text), ZSTR_LEN(decoded_text), cd);
    1854             :                                                 zend_string_release(decoded_text);
    1855             : 
    1856         102 :                                                 if (err != PHP_ICONV_ERR_SUCCESS) {
    1857           3 :                                                         if ((mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR)) {
    1858             :                                                                 /* pass the entire chunk through the converter */
    1859           2 :                                                                 err = _php_iconv_appendl(pretval, encoded_word, (size_t)(p1 - encoded_word), cd_pl);
    1860           2 :                                                                 encoded_word = NULL;
    1861           2 :                                                                 if (err != PHP_ICONV_ERR_SUCCESS) {
    1862           1 :                                                                         break;
    1863             :                                                                 }
    1864             :                                                         } else {
    1865           1 :                                                                 goto out;
    1866             :                                                         }
    1867             :                                                 }
    1868             : 
    1869         100 :                                                 if (eos) { /* reached end-of-string. done. */
    1870          24 :                                                         scan_stat = 0;
    1871          24 :                                                         break;
    1872             :                                                 }
    1873             : 
    1874          76 :                                                 switch (*p1) {
    1875             :                                                         case '\r': /* part of an EOL sequence? */
    1876           0 :                                                                 scan_stat = 7;
    1877           0 :                                                                 break;
    1878             : 
    1879             :                                                         case '\n':
    1880          49 :                                                                 scan_stat = 8;
    1881          49 :                                                                 break;
    1882             : 
    1883             :                                                         case '=': /* first letter of an encoded chunk */
    1884           4 :                                                                 scan_stat = 1;
    1885           4 :                                                                 break;
    1886             : 
    1887             :                                                         case ' ': case '\t': /* medial whitespaces */
    1888          22 :                                                                 spaces = p1;
    1889          22 :                                                                 scan_stat = 11;
    1890          22 :                                                                 break;
    1891             : 
    1892             :                                                         default: /* first letter of a non-encoded word */
    1893           1 :                                                                 _php_iconv_appendc(pretval, *p1, cd_pl);
    1894           1 :                                                                 scan_stat = 12;
    1895             :                                                                 break;
    1896             :                                                 }
    1897             :                                         } break;
    1898             :                                 }
    1899         103 :                                 break;
    1900             : 
    1901             :                         case 10: /* expects a language specifier. dismiss it for now */
    1902          84 :                                 if (*p1 == '?') {
    1903          14 :                                         scan_stat = 3;
    1904             :                                 }
    1905          84 :                                 break;
    1906             : 
    1907             :                         case 11: /* expecting a chunk of whitespaces */
    1908         256 :                                 switch (*p1) {
    1909             :                                         case '\r': /* part of an EOL sequence? */
    1910           0 :                                                 scan_stat = 7;
    1911           0 :                                                 break;
    1912             : 
    1913             :                                         case '\n':
    1914           6 :                                                 scan_stat = 8;
    1915           6 :                                                 break;
    1916             : 
    1917             :                                         case '=': /* first letter of an encoded chunk */
    1918         109 :                                                 if (spaces != NULL && encoded_word == NULL) {
    1919          47 :                                                         _php_iconv_appendl(pretval, spaces, (size_t)(p1 - spaces), cd_pl);
    1920          47 :                                                         spaces = NULL;
    1921             :                                                 }
    1922         109 :                                                 encoded_word = p1;
    1923         109 :                                                 scan_stat = 1;
    1924         109 :                                                 break;
    1925             : 
    1926             :                                         case ' ': case '\t':
    1927          36 :                                                 break;
    1928             : 
    1929             :                                         default: /* first letter of a non-encoded word */
    1930         105 :                                                 if (spaces != NULL) {
    1931         101 :                                                         _php_iconv_appendl(pretval, spaces, (size_t)(p1 - spaces), cd_pl);
    1932         101 :                                                         spaces = NULL;
    1933             :                                                 }
    1934         105 :                                                 _php_iconv_appendc(pretval, *p1, cd_pl);
    1935         105 :                                                 encoded_word = NULL;
    1936         105 :                                                 if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
    1937           2 :                                                         scan_stat = 12;
    1938             :                                                 } else {
    1939         103 :                                                         scan_stat = 0;
    1940             :                                                 }
    1941             :                                                 break;
    1942             :                                 }
    1943         256 :                                 break;
    1944             : 
    1945             :                         case 12: /* expecting a non-encoded word */
    1946         276 :                                 switch (*p1) {
    1947             :                                         case '\r': /* part of an EOL sequence? */
    1948           0 :                                                 scan_stat = 7;
    1949           0 :                                                 break;
    1950             : 
    1951             :                                         case '\n':
    1952           3 :                                                 scan_stat = 8;
    1953           3 :                                                 break;
    1954             : 
    1955             :                                         case ' ': case '\t':
    1956          20 :                                                 spaces = p1;
    1957          20 :                                                 scan_stat = 11;
    1958          20 :                                                 break;
    1959             : 
    1960             :                                         case '=': /* first letter of an encoded chunk */
    1961          21 :                                                 if (!(mode & PHP_ICONV_MIME_DECODE_STRICT)) {
    1962           0 :                                                         encoded_word = p1;
    1963           0 :                                                         scan_stat = 1;
    1964           0 :                                                         break;
    1965             :                                                 }
    1966             :                                                 /* break is omitted intentionally */
    1967             : 
    1968             :                                         default:
    1969         253 :                                                 _php_iconv_appendc(pretval, *p1, cd_pl);
    1970             :                                                 break;
    1971             :                                 }
    1972             :                                 break;
    1973             :                 }
    1974             :         }
    1975         104 :         switch (scan_stat) {
    1976             :                 case 0: case 8: case 11: case 12:
    1977         103 :                         break;
    1978             :                 default:
    1979           1 :                         if ((mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR)) {
    1980           1 :                                 if (scan_stat == 1) {
    1981           1 :                                         _php_iconv_appendc(pretval, '=', cd_pl);
    1982             :                                 }
    1983           1 :                                 err = PHP_ICONV_ERR_SUCCESS;
    1984             :                         } else {
    1985           0 :                                 err = PHP_ICONV_ERR_MALFORMED;
    1986           0 :                                 goto out;
    1987             :                         }
    1988             :         }
    1989             : 
    1990         104 :         if (next_pos != NULL) {
    1991          46 :                 *next_pos = p1;
    1992             :         }
    1993             : 
    1994             :         smart_str_0(pretval);
    1995             : out:
    1996         122 :         if (cd != (iconv_t)(-1)) {
    1997          43 :                 iconv_close(cd);
    1998             :         }
    1999         122 :         if (cd_pl != (iconv_t)(-1)) {
    2000         107 :                 iconv_close(cd_pl);
    2001             :         }
    2002         122 :         return err;
    2003             : }
    2004             : /* }}} */
    2005             : 
    2006             : /* {{{ php_iconv_show_error() */
    2007         486 : static void _php_iconv_show_error(php_iconv_err_t err, const char *out_charset, const char *in_charset)
    2008             : {
    2009         486 :         switch (err) {
    2010             :                 case PHP_ICONV_ERR_SUCCESS:
    2011         388 :                         break;
    2012             : 
    2013             :                 case PHP_ICONV_ERR_CONVERTER:
    2014           0 :                         php_error_docref(NULL, E_NOTICE, "Cannot open converter");
    2015           0 :                         break;
    2016             : 
    2017             :                 case PHP_ICONV_ERR_WRONG_CHARSET:
    2018          55 :                         php_error_docref(NULL, E_NOTICE, "Wrong charset, conversion from `%s' to `%s' is not allowed",
    2019             :                                   in_charset, out_charset);
    2020          55 :                         break;
    2021             : 
    2022             :                 case PHP_ICONV_ERR_ILLEGAL_CHAR:
    2023           2 :                         php_error_docref(NULL, E_NOTICE, "Detected an incomplete multibyte character in input string");
    2024           2 :                         break;
    2025             : 
    2026             :                 case PHP_ICONV_ERR_ILLEGAL_SEQ:
    2027           3 :                         php_error_docref(NULL, E_NOTICE, "Detected an illegal character in input string");
    2028           3 :                         break;
    2029             : 
    2030             :                 case PHP_ICONV_ERR_TOO_BIG:
    2031             :                         /* should not happen */
    2032          36 :                         php_error_docref(NULL, E_WARNING, "Buffer length exceeded");
    2033          36 :                         break;
    2034             : 
    2035             :                 case PHP_ICONV_ERR_MALFORMED:
    2036           2 :                         php_error_docref(NULL, E_WARNING, "Malformed string");
    2037           2 :                         break;
    2038             : 
    2039             :                 default:
    2040             :                         /* other error */
    2041           0 :                         php_error_docref(NULL, E_NOTICE, "Unknown error (%d)", errno);
    2042             :                         break;
    2043             :         }
    2044         486 : }
    2045             : /* }}} */
    2046             : 
    2047             : /* {{{ proto int iconv_strlen(string str [, string charset])
    2048             :    Returns the character count of str */
    2049          87 : PHP_FUNCTION(iconv_strlen)
    2050             : {
    2051          87 :         char *charset = get_internal_encoding();
    2052          87 :         size_t charset_len = 0;
    2053             :         zend_string *str;
    2054             : 
    2055             :         php_iconv_err_t err;
    2056             : 
    2057             :         size_t retval;
    2058             : 
    2059          87 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|s",
    2060             :                 &str, &charset, &charset_len) == FAILURE) {
    2061           4 :                 RETURN_FALSE;
    2062             :         }
    2063             : 
    2064          83 :         if (charset_len >= ICONV_CSNMAXLEN) {
    2065           1 :                 php_error_docref(NULL, E_WARNING, "Charset parameter exceeds the maximum allowed length of %d characters", ICONV_CSNMAXLEN);
    2066           1 :                 RETURN_FALSE;
    2067             :         }
    2068             : 
    2069          82 :         err = _php_iconv_strlen(&retval, ZSTR_VAL(str), ZSTR_LEN(str), charset);
    2070          82 :         _php_iconv_show_error(err, GENERIC_SUPERSET_NAME, charset);
    2071          82 :         if (err == PHP_ICONV_ERR_SUCCESS) {
    2072          70 :                 RETVAL_LONG(retval);
    2073             :         } else {
    2074          12 :                 RETVAL_FALSE;
    2075             :         }
    2076             : }
    2077             : /* }}} */
    2078             : 
    2079             : /* {{{ proto string iconv_substr(string str, int offset, [int length, string charset])
    2080             :    Returns specified part of a string */
    2081          22 : PHP_FUNCTION(iconv_substr)
    2082             : {
    2083          22 :         char *charset = get_internal_encoding();
    2084          22 :         size_t charset_len = 0;
    2085             :         zend_string *str;
    2086          22 :         zend_long offset, length = 0;
    2087             : 
    2088             :         php_iconv_err_t err;
    2089             : 
    2090          22 :         smart_str retval = {0};
    2091             : 
    2092          22 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sl|ls",
    2093             :                 &str, &offset, &length,
    2094             :                 &charset, &charset_len) == FAILURE) {
    2095           2 :                 RETURN_FALSE;
    2096             :         }
    2097             : 
    2098          20 :         if (charset_len >= ICONV_CSNMAXLEN) {
    2099           1 :                 php_error_docref(NULL, E_WARNING, "Charset parameter exceeds the maximum allowed length of %d characters", ICONV_CSNMAXLEN);
    2100           1 :                 RETURN_FALSE;
    2101             :         }
    2102             : 
    2103          19 :         if (ZEND_NUM_ARGS() < 3) {
    2104           3 :                 length = ZSTR_LEN(str);
    2105             :         }
    2106             : 
    2107          19 :         err = _php_iconv_substr(&retval, ZSTR_VAL(str), ZSTR_LEN(str), offset, length, charset);
    2108          19 :         _php_iconv_show_error(err, GENERIC_SUPERSET_NAME, charset);
    2109             : 
    2110          19 :         if (err == PHP_ICONV_ERR_SUCCESS && ZSTR_LEN(str) >= 0 && retval.s != NULL) {
    2111          15 :                 RETURN_NEW_STR(retval.s);
    2112             :         }
    2113             :         smart_str_free(&retval);
    2114           4 :         RETURN_FALSE;
    2115             : }
    2116             : /* }}} */
    2117             : 
    2118             : /* {{{ proto int iconv_strpos(string haystack, string needle [, int offset [, string charset]])
    2119             :    Finds position of first occurrence of needle within part of haystack beginning with offset */
    2120         140 : PHP_FUNCTION(iconv_strpos)
    2121             : {
    2122         140 :         char *charset = get_internal_encoding();
    2123         140 :         size_t charset_len = 0, haystk_len;
    2124             :         zend_string *haystk;
    2125             :         zend_string *ndl;
    2126         140 :         zend_long offset = 0;
    2127             : 
    2128             :         php_iconv_err_t err;
    2129             : 
    2130             :         size_t retval;
    2131             : 
    2132         140 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|ls",
    2133             :                 &haystk, &ndl,
    2134             :                 &offset, &charset, &charset_len) == FAILURE) {
    2135          12 :                 RETURN_FALSE;
    2136             :         }
    2137             : 
    2138         128 :         if (charset_len >= ICONV_CSNMAXLEN) {
    2139           1 :                 php_error_docref(NULL, E_WARNING, "Charset parameter exceeds the maximum allowed length of %d characters", ICONV_CSNMAXLEN);
    2140           1 :                 RETURN_FALSE;
    2141             :         }
    2142             : 
    2143         127 :         if (offset < 0) {
    2144             :                 /* Convert negative offset (counted from the end of string) */
    2145          12 :                 err = _php_iconv_strlen(&haystk_len, ZSTR_VAL(haystk), ZSTR_LEN(haystk), charset);
    2146          12 :                 if (err != PHP_ICONV_ERR_SUCCESS) {
    2147           0 :                         _php_iconv_show_error(err, GENERIC_SUPERSET_NAME, charset);
    2148           0 :                         RETURN_FALSE;
    2149             :                 }
    2150          12 :                 offset += haystk_len;
    2151          12 :                 if (offset < 0) { /* If offset before start */
    2152           4 :                         php_error_docref(NULL, E_WARNING, "Offset not contained in string.");
    2153           4 :                         RETURN_FALSE;
    2154             :                 }
    2155             :         }
    2156             : 
    2157         123 :         if (ZSTR_LEN(ndl) < 1) {
    2158           9 :                 RETURN_FALSE;
    2159             :         }
    2160             : 
    2161         114 :         err = _php_iconv_strpos(&retval, ZSTR_VAL(haystk), ZSTR_LEN(haystk), ZSTR_VAL(ndl), ZSTR_LEN(ndl),
    2162             :                                 offset, charset);
    2163         114 :         _php_iconv_show_error(err, GENERIC_SUPERSET_NAME, charset);
    2164             : 
    2165         164 :         if (err == PHP_ICONV_ERR_SUCCESS && retval != (size_t)-1) {
    2166          50 :                 RETVAL_LONG((zend_long)retval);
    2167             :         } else {
    2168          64 :                 RETVAL_FALSE;
    2169             :         }
    2170             : }
    2171             : /* }}} */
    2172             : 
    2173             : /* {{{ proto int iconv_strrpos(string haystack, string needle [, string charset])
    2174             :    Finds position of last occurrence of needle within part of haystack beginning with offset */
    2175          92 : PHP_FUNCTION(iconv_strrpos)
    2176             : {
    2177          92 :         char *charset = get_internal_encoding();
    2178          92 :         size_t charset_len = 0;
    2179             :         zend_string *haystk;
    2180             :         zend_string *ndl;
    2181             : 
    2182             :         php_iconv_err_t err;
    2183             : 
    2184             :         size_t retval;
    2185             : 
    2186          92 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|s",
    2187             :                 &haystk, &ndl,
    2188             :                 &charset, &charset_len) == FAILURE) {
    2189           5 :                 RETURN_FALSE;
    2190             :         }
    2191             : 
    2192          87 :         if (ZSTR_LEN(ndl) < 1) {
    2193           9 :                 RETURN_FALSE;
    2194             :         }
    2195             : 
    2196          78 :         if (charset_len >= ICONV_CSNMAXLEN) {
    2197           1 :                 php_error_docref(NULL, E_WARNING, "Charset parameter exceeds the maximum allowed length of %d characters", ICONV_CSNMAXLEN);
    2198           1 :                 RETURN_FALSE;
    2199             :         }
    2200             : 
    2201          77 :         err = _php_iconv_strpos(&retval, ZSTR_VAL(haystk), ZSTR_LEN(haystk), ZSTR_VAL(ndl), ZSTR_LEN(ndl),
    2202             :                                 -1, charset);
    2203          77 :         _php_iconv_show_error(err, GENERIC_SUPERSET_NAME, charset);
    2204             : 
    2205         108 :         if (err == PHP_ICONV_ERR_SUCCESS && retval != (size_t)-1) {
    2206          31 :                 RETVAL_LONG((zend_long)retval);
    2207             :         } else {
    2208          46 :                 RETVAL_FALSE;
    2209             :         }
    2210             : }
    2211             : /* }}} */
    2212             : 
    2213             : /* {{{ proto string iconv_mime_encode(string field_name, string field_value [, array preference])
    2214             :    Composes a mime header field with field_name and field_value in a specified scheme */
    2215          83 : PHP_FUNCTION(iconv_mime_encode)
    2216             : {
    2217          83 :         zend_string *field_name = NULL;
    2218          83 :         zend_string *field_value = NULL;
    2219          83 :         zend_string *tmp_str = NULL;
    2220          83 :         zval *pref = NULL;
    2221          83 :         smart_str retval = {0};
    2222             :         php_iconv_err_t err;
    2223             : 
    2224          83 :         const char *in_charset = get_internal_encoding();
    2225          83 :         const char *out_charset = in_charset;
    2226          83 :         zend_long line_len = 76;
    2227          83 :         const char *lfchars = "\r\n";
    2228          83 :         php_iconv_enc_scheme_t scheme_id = PHP_ICONV_ENC_SCHEME_BASE64;
    2229             : 
    2230          83 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|a",
    2231             :                 &field_name, &field_value,
    2232             :                 &pref) == FAILURE) {
    2233             : 
    2234           0 :                 RETURN_FALSE;
    2235             :         }
    2236             : 
    2237          83 :         if (pref != NULL) {
    2238             :                 zval *pzval;
    2239             : 
    2240          82 :                 if ((pzval = zend_hash_str_find(Z_ARRVAL_P(pref), "scheme", sizeof("scheme") - 1)) != NULL) {
    2241          81 :                         if (Z_TYPE_P(pzval) == IS_STRING && Z_STRLEN_P(pzval) > 0) {
    2242          81 :                                 switch (Z_STRVAL_P(pzval)[0]) {
    2243             :                                         case 'B': case 'b':
    2244          80 :                                                 scheme_id = PHP_ICONV_ENC_SCHEME_BASE64;
    2245          80 :                                                 break;
    2246             : 
    2247             :                                         case 'Q': case 'q':
    2248           1 :                                                 scheme_id = PHP_ICONV_ENC_SCHEME_QPRINT;
    2249             :                                                 break;
    2250             :                                 }
    2251             :                         }
    2252             :                 }
    2253             : 
    2254         163 :                 if ((pzval = zend_hash_str_find(Z_ARRVAL_P(pref), "input-charset", sizeof("input-charset") - 1)) != NULL && Z_TYPE_P(pzval) == IS_STRING) {
    2255          81 :                         if (Z_STRLEN_P(pzval) >= ICONV_CSNMAXLEN) {
    2256           0 :                                 php_error_docref(NULL, E_WARNING, "Charset parameter exceeds the maximum allowed length of %d characters", ICONV_CSNMAXLEN);
    2257           0 :                                 RETURN_FALSE;
    2258             :                         }
    2259             : 
    2260          81 :                         if (Z_STRLEN_P(pzval) > 0) {
    2261          81 :                                 in_charset = Z_STRVAL_P(pzval);
    2262             :                         }
    2263             :                 }
    2264             : 
    2265             : 
    2266         163 :                 if ((pzval = zend_hash_str_find(Z_ARRVAL_P(pref), "output-charset", sizeof("output-charset") - 1)) != NULL && Z_TYPE_P(pzval) == IS_STRING) {
    2267          81 :                         if (Z_STRLEN_P(pzval) >= ICONV_CSNMAXLEN) {
    2268           0 :                                 php_error_docref(NULL, E_WARNING, "Charset parameter exceeds the maximum allowed length of %d characters", ICONV_CSNMAXLEN);
    2269           0 :                                 RETURN_FALSE;
    2270             :                         }
    2271             : 
    2272          81 :                         if (Z_STRLEN_P(pzval) > 0) {
    2273          81 :                                 out_charset = Z_STRVAL_P(pzval);
    2274             :                         }
    2275             :                 }
    2276             : 
    2277          82 :                 if ((pzval = zend_hash_str_find(Z_ARRVAL_P(pref), "line-length", sizeof("line-length") - 1)) != NULL) {
    2278          81 :                         line_len = zval_get_long(pzval);
    2279             :                 }
    2280             : 
    2281          82 :                 if ((pzval = zend_hash_str_find(Z_ARRVAL_P(pref), "line-break-chars", sizeof("line-break-chars") - 1)) != NULL) {
    2282          81 :                         if (Z_TYPE_P(pzval) != IS_STRING) {
    2283           1 :                                 tmp_str = zval_get_string(pzval);
    2284           1 :                                 lfchars = ZSTR_VAL(tmp_str);
    2285             :                         } else {
    2286          80 :                                 lfchars = Z_STRVAL_P(pzval);
    2287             :                         }
    2288             :                 }
    2289             :         }
    2290             : 
    2291         249 :         err = _php_iconv_mime_encode(&retval, ZSTR_VAL(field_name), ZSTR_LEN(field_name),
    2292         166 :                 ZSTR_VAL(field_value), ZSTR_LEN(field_value), line_len, lfchars, scheme_id,
    2293             :                 out_charset, in_charset);
    2294          83 :         _php_iconv_show_error(err, out_charset, in_charset);
    2295             : 
    2296          83 :         if (err == PHP_ICONV_ERR_SUCCESS) {
    2297          47 :                 if (retval.s != NULL) {
    2298          47 :                         RETVAL_STR(retval.s);
    2299             :                 } else {
    2300           0 :                         RETVAL_EMPTY_STRING();
    2301             :                 }
    2302             :         } else {
    2303             :                 smart_str_free(&retval);
    2304          36 :                 RETVAL_FALSE;
    2305             :         }
    2306             : 
    2307          83 :         if (tmp_str) {
    2308             :                 zend_string_release(tmp_str);
    2309             :         }
    2310             : }
    2311             : /* }}} */
    2312             : 
    2313             : /* {{{ proto string iconv_mime_decode(string encoded_string [, int mode, string charset])
    2314             :    Decodes a mime header field */
    2315          79 : PHP_FUNCTION(iconv_mime_decode)
    2316             : {
    2317             :         zend_string *encoded_str;
    2318          79 :         char *charset = get_internal_encoding();
    2319          79 :         size_t charset_len = 0;
    2320          79 :         zend_long mode = 0;
    2321             : 
    2322          79 :         smart_str retval = {0};
    2323             : 
    2324             :         php_iconv_err_t err;
    2325             : 
    2326          79 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|ls",
    2327             :                 &encoded_str, &mode, &charset, &charset_len) == FAILURE) {
    2328             : 
    2329           2 :                 RETURN_FALSE;
    2330             :         }
    2331             : 
    2332          77 :         if (charset_len >= ICONV_CSNMAXLEN) {
    2333           1 :                 php_error_docref(NULL, E_WARNING, "Charset parameter exceeds the maximum allowed length of %d characters", ICONV_CSNMAXLEN);
    2334           1 :                 RETURN_FALSE;
    2335             :         }
    2336             : 
    2337          76 :         err = _php_iconv_mime_decode(&retval, ZSTR_VAL(encoded_str), ZSTR_LEN(encoded_str), charset, NULL, (int)mode);
    2338          76 :         _php_iconv_show_error(err, charset, "???");
    2339             : 
    2340          76 :         if (err == PHP_ICONV_ERR_SUCCESS) {
    2341          58 :                 if (retval.s != NULL) {
    2342          50 :                         RETVAL_STR(retval.s);
    2343             :                 } else {
    2344           8 :                         RETVAL_EMPTY_STRING();
    2345             :                 }
    2346             :         } else {
    2347             :                 smart_str_free(&retval);
    2348          18 :                 RETVAL_FALSE;
    2349             :         }
    2350             : }
    2351             : /* }}} */
    2352             : 
    2353             : /* {{{ proto array iconv_mime_decode_headers(string headers [, int mode, string charset])
    2354             :    Decodes multiple mime header fields */
    2355          28 : PHP_FUNCTION(iconv_mime_decode_headers)
    2356             : {
    2357             :         zend_string *encoded_str;
    2358          28 :         char *charset = get_internal_encoding();
    2359          28 :         size_t charset_len = 0;
    2360          28 :         zend_long mode = 0;
    2361             :         char *enc_str_tmp;
    2362             :         size_t enc_str_len_tmp;
    2363             : 
    2364          28 :         php_iconv_err_t err = PHP_ICONV_ERR_SUCCESS;
    2365             : 
    2366          28 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|ls",
    2367             :                 &encoded_str, &mode, &charset, &charset_len) == FAILURE) {
    2368             : 
    2369           1 :                 RETURN_FALSE;
    2370             :         }
    2371             : 
    2372          27 :         if (charset_len >= ICONV_CSNMAXLEN) {
    2373           1 :                 php_error_docref(NULL, E_WARNING, "Charset parameter exceeds the maximum allowed length of %d characters", ICONV_CSNMAXLEN);
    2374           1 :                 RETURN_FALSE;
    2375             :         }
    2376             : 
    2377          26 :         array_init(return_value);
    2378             : 
    2379          26 :         enc_str_tmp = ZSTR_VAL(encoded_str);
    2380          26 :         enc_str_len_tmp = ZSTR_LEN(encoded_str);
    2381          98 :         while (enc_str_len_tmp > 0) {
    2382          46 :                 smart_str decoded_header = {0};
    2383          46 :                 char *header_name = NULL;
    2384          46 :                 size_t header_name_len = 0;
    2385          46 :                 char *header_value = NULL;
    2386          46 :                 size_t header_value_len = 0;
    2387             :                 char *p, *limit;
    2388             :                 const char *next_pos;
    2389             : 
    2390          46 :                 if (PHP_ICONV_ERR_SUCCESS != (err = _php_iconv_mime_decode(&decoded_header, enc_str_tmp, enc_str_len_tmp, charset, &next_pos, (int)mode))) {
    2391             :                         smart_str_free(&decoded_header);
    2392           0 :                         break;
    2393             :                 }
    2394             : 
    2395          46 :                 if (decoded_header.s == NULL) {
    2396           0 :                         break;
    2397             :                 }
    2398             : 
    2399          46 :                 limit = ZSTR_VAL(decoded_header.s) + ZSTR_LEN(decoded_header.s);
    2400         374 :                 for (p = ZSTR_VAL(decoded_header.s); p < limit; p++) {
    2401         359 :                         if (*p == ':') {
    2402          31 :                                 *p = '\0';
    2403          31 :                                 header_name = ZSTR_VAL(decoded_header.s);
    2404          31 :                                 header_name_len = p - ZSTR_VAL(decoded_header.s);
    2405             : 
    2406          93 :                                 while (++p < limit) {
    2407          62 :                                         if (*p != ' ' && *p != '\t') {
    2408          31 :                                                 break;
    2409             :                                         }
    2410             :                                 }
    2411             : 
    2412          31 :                                 header_value = p;
    2413          31 :                                 header_value_len = limit - p;
    2414             : 
    2415          31 :                                 break;
    2416             :                         }
    2417             :                 }
    2418             : 
    2419          46 :                 if (header_name != NULL) {
    2420             :                         zval *elem;
    2421             : 
    2422          31 :                         if ((elem = zend_hash_str_find(Z_ARRVAL_P(return_value), header_name, header_name_len)) != NULL) {
    2423           4 :                                 if (Z_TYPE_P(elem) != IS_ARRAY) {
    2424             :                                         zval new_elem;
    2425             : 
    2426           2 :                                         array_init(&new_elem);
    2427             :                                         Z_ADDREF_P(elem);
    2428           2 :                                         add_next_index_zval(&new_elem, elem);
    2429             : 
    2430           2 :                                         elem = zend_hash_str_update(Z_ARRVAL_P(return_value), header_name, header_name_len, &new_elem);
    2431             :                                 }
    2432           4 :                                 add_next_index_stringl(elem, header_value, header_value_len);
    2433             :                         } else {
    2434          27 :                                 add_assoc_stringl_ex(return_value, header_name, header_name_len, header_value, header_value_len);
    2435             :                         }
    2436             :                 }
    2437          46 :                 enc_str_len_tmp -= next_pos - enc_str_tmp;
    2438          46 :                 enc_str_tmp = (char *)next_pos;
    2439             : 
    2440             :                 smart_str_free(&decoded_header);
    2441             :         }
    2442             : 
    2443          26 :         if (err != PHP_ICONV_ERR_SUCCESS) {
    2444           0 :                 _php_iconv_show_error(err, charset, "???");
    2445             :                 zval_dtor(return_value);
    2446           0 :                 RETVAL_FALSE;
    2447             :         }
    2448             : }
    2449             : /* }}} */
    2450             : 
    2451             : /* {{{ proto string iconv(string in_charset, string out_charset, string str)
    2452             :    Returns str converted to the out_charset character set */
    2453          35 : PHP_NAMED_FUNCTION(php_if_iconv)
    2454             : {
    2455             :         char *in_charset, *out_charset;
    2456             :         zend_string *in_buffer;
    2457          35 :         size_t in_charset_len = 0, out_charset_len = 0;
    2458             :         php_iconv_err_t err;
    2459             :         zend_string *out_buffer;
    2460             : 
    2461          35 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssS",
    2462             :                 &in_charset, &in_charset_len, &out_charset, &out_charset_len, &in_buffer) == FAILURE)
    2463           0 :                 return;
    2464             : 
    2465          35 :         if (in_charset_len >= ICONV_CSNMAXLEN || out_charset_len >= ICONV_CSNMAXLEN) {
    2466           2 :                 php_error_docref(NULL, E_WARNING, "Charset parameter exceeds the maximum allowed length of %d characters", ICONV_CSNMAXLEN);
    2467           2 :                 RETURN_FALSE;
    2468             :         }
    2469             : 
    2470          33 :         err = php_iconv_string(ZSTR_VAL(in_buffer), (size_t)ZSTR_LEN(in_buffer), &out_buffer, out_charset, in_charset);
    2471          33 :         _php_iconv_show_error(err, out_charset, in_charset);
    2472          59 :         if (err == PHP_ICONV_ERR_SUCCESS && out_buffer != NULL) {
    2473          26 :                 RETVAL_STR(out_buffer);
    2474             :         } else {
    2475           7 :                 if (out_buffer != NULL) {
    2476           4 :                         zend_string_free(out_buffer);
    2477             :                 }
    2478           7 :                 RETURN_FALSE;
    2479             :         }
    2480             : }
    2481             : /* }}} */
    2482             : 
    2483             : /* {{{ proto bool iconv_set_encoding(string type, string charset)
    2484             :    Sets internal encoding and output encoding for ob_iconv_handler() */
    2485         113 : PHP_FUNCTION(iconv_set_encoding)
    2486             : {
    2487             :         char *type;
    2488             :         zend_string *charset;
    2489             :         size_t type_len, retval;
    2490             :         zend_string *name;
    2491             : 
    2492         113 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "sS", &type, &type_len, &charset) == FAILURE)
    2493           4 :                 return;
    2494             : 
    2495         109 :         if (ZSTR_LEN(charset) >= ICONV_CSNMAXLEN) {
    2496           3 :                 php_error_docref(NULL, E_WARNING, "Charset parameter exceeds the maximum allowed length of %d characters", ICONV_CSNMAXLEN);
    2497           3 :                 RETURN_FALSE;
    2498             :         }
    2499             : 
    2500         106 :         if(!strcasecmp("input_encoding", type)) {
    2501          26 :                 name = zend_string_init("iconv.input_encoding", sizeof("iconv.input_encoding") - 1, 0);
    2502          80 :         } else if(!strcasecmp("output_encoding", type)) {
    2503          27 :                 name = zend_string_init("iconv.output_encoding", sizeof("iconv.output_encoding") - 1, 0);
    2504          53 :         } else if(!strcasecmp("internal_encoding", type)) {
    2505          30 :                 name = zend_string_init("iconv.internal_encoding", sizeof("iconv.internal_encoding") - 1, 0);
    2506             :         } else {
    2507          23 :                 RETURN_FALSE;
    2508             :         }
    2509             : 
    2510          83 :         retval = zend_alter_ini_entry(name, charset, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
    2511             :         zend_string_release(name);
    2512             : 
    2513          83 :         if (retval == SUCCESS) {
    2514          83 :                 RETURN_TRUE;
    2515             :         } else {
    2516           0 :                 RETURN_FALSE;
    2517             :         }
    2518             : }
    2519             : /* }}} */
    2520             : 
    2521             : /* {{{ proto mixed iconv_get_encoding([string type])
    2522             :    Get internal encoding and output encoding for ob_iconv_handler() */
    2523         118 : PHP_FUNCTION(iconv_get_encoding)
    2524             : {
    2525         118 :         char *type = "all";
    2526         118 :         size_t type_len = sizeof("all")-1;
    2527             : 
    2528         118 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &type, &type_len) == FAILURE)
    2529           1 :                 return;
    2530             : 
    2531         117 :         if (!strcasecmp("all", type)) {
    2532           8 :                 array_init(return_value);
    2533           8 :                 add_assoc_string(return_value, "input_encoding",    get_input_encoding());
    2534           8 :                 add_assoc_string(return_value, "output_encoding",   get_output_encoding());
    2535           8 :                 add_assoc_string(return_value, "internal_encoding", get_internal_encoding());
    2536         109 :         } else if (!strcasecmp("input_encoding", type)) {
    2537          56 :                 RETVAL_STRING(get_input_encoding());
    2538          81 :         } else if (!strcasecmp("output_encoding", type)) {
    2539          56 :                 RETVAL_STRING(get_output_encoding());
    2540          53 :         } else if (!strcasecmp("internal_encoding", type)) {
    2541          56 :                 RETVAL_STRING(get_internal_encoding());
    2542             :         } else {
    2543          25 :                 RETURN_FALSE;
    2544             :         }
    2545             : 
    2546             : }
    2547             : /* }}} */
    2548             : 
    2549             : /* {{{ iconv stream filter */
    2550             : typedef struct _php_iconv_stream_filter {
    2551             :         iconv_t cd;
    2552             :         int persistent;
    2553             :         char *to_charset;
    2554             :         size_t to_charset_len;
    2555             :         char *from_charset;
    2556             :         size_t from_charset_len;
    2557             :         char stub[128];
    2558             :         size_t stub_len;
    2559             : } php_iconv_stream_filter;
    2560             : /* }}} iconv stream filter */
    2561             : 
    2562             : /* {{{ php_iconv_stream_filter_dtor */
    2563           6 : static void php_iconv_stream_filter_dtor(php_iconv_stream_filter *self)
    2564             : {
    2565           6 :         iconv_close(self->cd);
    2566           6 :         pefree(self->to_charset, self->persistent);
    2567           6 :         pefree(self->from_charset, self->persistent);
    2568           6 : }
    2569             : /* }}} */
    2570             : 
    2571             : /* {{{ php_iconv_stream_filter_ctor() */
    2572           6 : static php_iconv_err_t php_iconv_stream_filter_ctor(php_iconv_stream_filter *self,
    2573             :                 const char *to_charset, size_t to_charset_len,
    2574             :                 const char *from_charset, size_t from_charset_len, int persistent)
    2575             : {
    2576           6 :         if (NULL == (self->to_charset = pemalloc(to_charset_len + 1, persistent))) {
    2577           0 :                 return PHP_ICONV_ERR_ALLOC;
    2578             :         }
    2579           6 :         self->to_charset_len = to_charset_len;
    2580           6 :         if (NULL == (self->from_charset = pemalloc(from_charset_len + 1, persistent))) {
    2581           0 :                 pefree(self->to_charset, persistent);
    2582           0 :                 return PHP_ICONV_ERR_ALLOC;
    2583             :         }
    2584           6 :         self->from_charset_len = from_charset_len;
    2585             : 
    2586           6 :         memcpy(self->to_charset, to_charset, to_charset_len);
    2587           6 :         self->to_charset[to_charset_len] = '\0';
    2588           6 :         memcpy(self->from_charset, from_charset, from_charset_len);
    2589           6 :         self->from_charset[from_charset_len] = '\0';
    2590             : 
    2591           6 :         if ((iconv_t)-1 == (self->cd = iconv_open(self->to_charset, self->from_charset))) {
    2592           0 :                 pefree(self->from_charset, persistent);
    2593           0 :                 pefree(self->to_charset, persistent);
    2594           0 :                 return PHP_ICONV_ERR_UNKNOWN;
    2595             :         }
    2596           6 :         self->persistent = persistent;
    2597           6 :         self->stub_len = 0;
    2598           6 :         return PHP_ICONV_ERR_SUCCESS;
    2599             : }
    2600             : /* }}} */
    2601             : 
    2602             : /* {{{ php_iconv_stream_filter_append_bucket */
    2603           8 : static int php_iconv_stream_filter_append_bucket(
    2604             :                 php_iconv_stream_filter *self,
    2605             :                 php_stream *stream, php_stream_filter *filter,
    2606             :                 php_stream_bucket_brigade *buckets_out,
    2607             :                 const char *ps, size_t buf_len, size_t *consumed,
    2608             :                 int persistent)
    2609             : {
    2610             :         php_stream_bucket *new_bucket;
    2611           8 :         char *out_buf = NULL;
    2612             :         size_t out_buf_size;
    2613             :         char *pd, *pt;
    2614             :         size_t ocnt, prev_ocnt, icnt, tcnt;
    2615             :         size_t initial_out_buf_size;
    2616             : 
    2617           8 :         if (ps == NULL) {
    2618           2 :                 initial_out_buf_size = 64;
    2619           2 :                 icnt = 1;
    2620             :         } else {
    2621           6 :                 initial_out_buf_size = buf_len;
    2622           6 :                 icnt = buf_len;
    2623             :         }
    2624             : 
    2625           8 :         out_buf_size = ocnt = prev_ocnt = initial_out_buf_size;
    2626           8 :         if (NULL == (out_buf = pemalloc(out_buf_size, persistent))) {
    2627           0 :                 return FAILURE;
    2628             :         }
    2629             : 
    2630           8 :         pd = out_buf;
    2631             : 
    2632           8 :         if (self->stub_len > 0) {
    2633           0 :                 pt = self->stub;
    2634           0 :                 tcnt = self->stub_len;
    2635             : 
    2636           0 :                 while (tcnt > 0) {
    2637           0 :                         if (iconv(self->cd, &pt, &tcnt, &pd, &ocnt) == (size_t)-1) {
    2638             : #if ICONV_SUPPORTS_ERRNO
    2639           0 :                                 switch (errno) {
    2640             :                                         case EILSEQ:
    2641           0 :                                                 php_error_docref(NULL, E_WARNING, "iconv stream filter (\"%s\"=>\"%s\"): invalid multibyte sequence", self->from_charset, self->to_charset);
    2642           0 :                                                 goto out_failure;
    2643             : 
    2644             :                                         case EINVAL:
    2645           0 :                                                 if (ps != NULL) {
    2646           0 :                                                         if (icnt > 0) {
    2647           0 :                                                                 if (self->stub_len >= sizeof(self->stub)) {
    2648           0 :                                                                         php_error_docref(NULL, E_WARNING, "iconv stream filter (\"%s\"=>\"%s\"): insufficient buffer", self->from_charset, self->to_charset);
    2649           0 :                                                                         goto out_failure;
    2650             :                                                                 }
    2651           0 :                                                                 self->stub[self->stub_len++] = *(ps++);
    2652           0 :                                                                 icnt--;
    2653           0 :                                                                 pt = self->stub;
    2654           0 :                                                                 tcnt = self->stub_len;
    2655             :                                                         } else {
    2656           0 :                                                                 tcnt = 0;
    2657           0 :                                                                 break;
    2658             :                                                         }
    2659             :                                                 }
    2660           0 :                                                 break;
    2661             : 
    2662             :                                         case E2BIG: {
    2663             :                                                 char *new_out_buf;
    2664             :                                                 size_t new_out_buf_size;
    2665             : 
    2666           0 :                                                 new_out_buf_size = out_buf_size << 1;
    2667             : 
    2668           0 :                                                 if (new_out_buf_size < out_buf_size) {
    2669             :                                                         /* whoa! no bigger buckets are sold anywhere... */
    2670           0 :                                                         if (NULL == (new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, persistent))) {
    2671           0 :                                                                 goto out_failure;
    2672             :                                                         }
    2673             : 
    2674           0 :                                                         php_stream_bucket_append(buckets_out, new_bucket);
    2675             : 
    2676           0 :                                                         out_buf_size = ocnt = initial_out_buf_size;
    2677           0 :                                                         if (NULL == (out_buf = pemalloc(out_buf_size, persistent))) {
    2678           0 :                                                                 return FAILURE;
    2679             :                                                         }
    2680           0 :                                                         pd = out_buf;
    2681             :                                                 } else {
    2682           0 :                                                         if (NULL == (new_out_buf = perealloc(out_buf, new_out_buf_size, persistent))) {
    2683           0 :                                                                 if (NULL == (new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, persistent))) {
    2684           0 :                                                                         goto out_failure;
    2685             :                                                                 }
    2686             : 
    2687           0 :                                                                 php_stream_bucket_append(buckets_out, new_bucket);
    2688           0 :                                                                 return FAILURE;
    2689             :                                                         }
    2690           0 :                                                         pd = new_out_buf + (pd - out_buf);
    2691           0 :                                                         ocnt += (new_out_buf_size - out_buf_size);
    2692           0 :                                                         out_buf = new_out_buf;
    2693           0 :                                                         out_buf_size = new_out_buf_size;
    2694             :                                                 }
    2695           0 :                                         } break;
    2696             : 
    2697             :                                         default:
    2698           0 :                                                 php_error_docref(NULL, E_WARNING, "iconv stream filter (\"%s\"=>\"%s\"): unknown error", self->from_charset, self->to_charset);
    2699           0 :                                                 goto out_failure;
    2700             :                                 }
    2701             : #else
    2702             :                                 if (ocnt == prev_ocnt) {
    2703             :                                         php_error_docref(NULL, E_WARNING, "iconv stream filter (\"%s\"=>\"%s\"): unknown error", self->from_charset, self->to_charset);
    2704             :                                         goto out_failure;
    2705             :                                 }
    2706             : #endif
    2707             :                         }
    2708           0 :                         prev_ocnt = ocnt;
    2709             :                 }
    2710           0 :                 memmove(self->stub, pt, tcnt);
    2711           0 :                 self->stub_len = tcnt;
    2712             :         }
    2713             : 
    2714          23 :         while (icnt > 0) {
    2715          16 :                 if ((ps == NULL ? iconv(self->cd, NULL, NULL, &pd, &ocnt):
    2716           7 :                                         iconv(self->cd, (char **)&ps, &icnt, &pd, &ocnt)) == (size_t)-1) {
    2717             : #if ICONV_SUPPORTS_ERRNO
    2718           1 :                         switch (errno) {
    2719             :                                 case EILSEQ:
    2720           0 :                                         php_error_docref(NULL, E_WARNING, "iconv stream filter (\"%s\"=>\"%s\"): invalid multibyte sequence", self->from_charset, self->to_charset);
    2721           0 :                                         goto out_failure;
    2722             : 
    2723             :                                 case EINVAL:
    2724           0 :                                         if (ps != NULL) {
    2725           0 :                                                 if (icnt > sizeof(self->stub)) {
    2726           0 :                                                         php_error_docref(NULL, E_WARNING, "iconv stream filter (\"%s\"=>\"%s\"): insufficient buffer", self->from_charset, self->to_charset);
    2727           0 :                                                         goto out_failure;
    2728             :                                                 }
    2729           0 :                                                 memcpy(self->stub, ps, icnt);
    2730           0 :                                                 self->stub_len = icnt;
    2731           0 :                                                 ps += icnt;
    2732           0 :                                                 icnt = 0;
    2733             :                                         } else {
    2734           0 :                                                 php_error_docref(NULL, E_WARNING, "iconv stream filter (\"%s\"=>\"%s\"): unexpected octet values", self->from_charset, self->to_charset);
    2735           0 :                                                 goto out_failure;
    2736             :                                         }
    2737           0 :                                         break;
    2738             : 
    2739             :                                 case E2BIG: {
    2740             :                                         char *new_out_buf;
    2741             :                                         size_t new_out_buf_size;
    2742             : 
    2743           1 :                                         new_out_buf_size = out_buf_size << 1;
    2744             : 
    2745           1 :                                         if (new_out_buf_size < out_buf_size) {
    2746             :                                                 /* whoa! no bigger buckets are sold anywhere... */
    2747           0 :                                                 if (NULL == (new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, persistent))) {
    2748           0 :                                                         goto out_failure;
    2749             :                                                 }
    2750             : 
    2751           0 :                                                 php_stream_bucket_append(buckets_out, new_bucket);
    2752             : 
    2753           0 :                                                 out_buf_size = ocnt = initial_out_buf_size;
    2754           0 :                                                 if (NULL == (out_buf = pemalloc(out_buf_size, persistent))) {
    2755           0 :                                                         return FAILURE;
    2756             :                                                 }
    2757           0 :                                                 pd = out_buf;
    2758             :                                         } else {
    2759           1 :                                                 if (NULL == (new_out_buf = perealloc(out_buf, new_out_buf_size, persistent))) {
    2760           0 :                                                         if (NULL == (new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, persistent))) {
    2761           0 :                                                                 goto out_failure;
    2762             :                                                         }
    2763             : 
    2764           0 :                                                         php_stream_bucket_append(buckets_out, new_bucket);
    2765           0 :                                                         return FAILURE;
    2766             :                                                 }
    2767           1 :                                                 pd = new_out_buf + (pd - out_buf);
    2768           1 :                                                 ocnt += (new_out_buf_size - out_buf_size);
    2769           1 :                                                 out_buf = new_out_buf;
    2770           1 :                                                 out_buf_size = new_out_buf_size;
    2771             :                                         }
    2772           1 :                                 } break;
    2773             : 
    2774             :                                 default:
    2775           0 :                                         php_error_docref(NULL, E_WARNING, "iconv stream filter (\"%s\"=>\"%s\"): unknown error", self->from_charset, self->to_charset);
    2776           0 :                                         goto out_failure;
    2777             :                         }
    2778             : #else
    2779             :                         if (ocnt == prev_ocnt) {
    2780             :                                 php_error_docref(NULL, E_WARNING, "iconv stream filter (\"%s\"=>\"%s\"): unknown error", self->from_charset, self->to_charset);
    2781             :                                 goto out_failure;
    2782             :                         }
    2783             : #endif
    2784             :                 } else {
    2785           8 :                         if (ps == NULL) {
    2786           2 :                                 break;
    2787             :                         }
    2788             :                 }
    2789           7 :                 prev_ocnt = ocnt;
    2790             :         }
    2791             : 
    2792           8 :         if (out_buf_size > ocnt) {
    2793           6 :                 if (NULL == (new_bucket = php_stream_bucket_new(stream, out_buf, (out_buf_size - ocnt), 1, persistent))) {
    2794           0 :                         goto out_failure;
    2795             :                 }
    2796           6 :                 php_stream_bucket_append(buckets_out, new_bucket);
    2797             :         } else {
    2798           2 :                 pefree(out_buf, persistent);
    2799             :         }
    2800           8 :         *consumed += buf_len - icnt;
    2801             : 
    2802           8 :         return SUCCESS;
    2803             : 
    2804             : out_failure:
    2805           0 :         pefree(out_buf, persistent);
    2806           0 :         return FAILURE;
    2807             : }
    2808             : /* }}} php_iconv_stream_filter_append_bucket */
    2809             : 
    2810             : /* {{{ php_iconv_stream_filter_do_filter */
    2811           8 : static php_stream_filter_status_t php_iconv_stream_filter_do_filter(
    2812             :                 php_stream *stream, php_stream_filter *filter,
    2813             :                 php_stream_bucket_brigade *buckets_in,
    2814             :                 php_stream_bucket_brigade *buckets_out,
    2815             :                 size_t *bytes_consumed, int flags)
    2816             : {
    2817           8 :         php_stream_bucket *bucket = NULL;
    2818           8 :         size_t consumed = 0;
    2819           8 :         php_iconv_stream_filter *self = (php_iconv_stream_filter *)Z_PTR(filter->abstract);
    2820             : 
    2821          22 :         while (buckets_in->head != NULL) {
    2822           6 :                 bucket = buckets_in->head;
    2823             : 
    2824           6 :                 php_stream_bucket_unlink(bucket);
    2825             : 
    2826          12 :                 if (php_iconv_stream_filter_append_bucket(self, stream, filter,
    2827           6 :                                 buckets_out, bucket->buf, bucket->buflen, &consumed,
    2828             :                                 php_stream_is_persistent(stream)) != SUCCESS) {
    2829           0 :                         goto out_failure;
    2830             :                 }
    2831             : 
    2832           6 :                 php_stream_bucket_delref(bucket);
    2833             :         }
    2834             : 
    2835           8 :         if (flags != PSFS_FLAG_NORMAL) {
    2836           2 :                 if (php_iconv_stream_filter_append_bucket(self, stream, filter,
    2837             :                                 buckets_out, NULL, 0, &consumed,
    2838             :                                 php_stream_is_persistent(stream)) != SUCCESS) {
    2839           0 :                         goto out_failure;
    2840             :                 }
    2841             :         }
    2842             : 
    2843           8 :         if (bytes_consumed != NULL) {
    2844           0 :                 *bytes_consumed = consumed;
    2845             :         }
    2846             : 
    2847           8 :         return PSFS_PASS_ON;
    2848             : 
    2849             : out_failure:
    2850           0 :         if (bucket != NULL) {
    2851           0 :                 php_stream_bucket_delref(bucket);
    2852             :         }
    2853           0 :         return PSFS_ERR_FATAL;
    2854             : }
    2855             : /* }}} */
    2856             : 
    2857             : /* {{{ php_iconv_stream_filter_cleanup */
    2858           6 : static void php_iconv_stream_filter_cleanup(php_stream_filter *filter)
    2859             : {
    2860           6 :         php_iconv_stream_filter_dtor((php_iconv_stream_filter *)Z_PTR(filter->abstract));
    2861           6 :         pefree(Z_PTR(filter->abstract), ((php_iconv_stream_filter *)Z_PTR(filter->abstract))->persistent);
    2862           6 : }
    2863             : /* }}} */
    2864             : 
    2865             : static php_stream_filter_ops php_iconv_stream_filter_ops = {
    2866             :         php_iconv_stream_filter_do_filter,
    2867             :         php_iconv_stream_filter_cleanup,
    2868             :         "convert.iconv.*"
    2869             : };
    2870             : 
    2871             : /* {{{ php_iconv_stream_filter_create */
    2872           7 : static php_stream_filter *php_iconv_stream_filter_factory_create(const char *name, zval *params, int persistent)
    2873             : {
    2874           7 :         php_stream_filter *retval = NULL;
    2875             :         php_iconv_stream_filter *inst;
    2876           7 :         char *from_charset = NULL, *to_charset = NULL;
    2877             :         size_t from_charset_len, to_charset_len;
    2878             : 
    2879           7 :         if ((from_charset = strchr(name, '.')) == NULL) {
    2880           0 :                 return NULL;
    2881             :         }
    2882           7 :         ++from_charset;
    2883           7 :         if ((from_charset = strchr(from_charset, '.')) == NULL) {
    2884           0 :                 return NULL;
    2885             :         }
    2886           7 :         ++from_charset;
    2887           7 :         if ((to_charset = strpbrk(from_charset, "/.")) == NULL) {
    2888           1 :                 return NULL;
    2889             :         }
    2890           6 :         from_charset_len = to_charset - from_charset;
    2891           6 :         ++to_charset;
    2892           6 :         to_charset_len = strlen(to_charset);
    2893             : 
    2894           6 :         if (from_charset_len >= ICONV_CSNMAXLEN || to_charset_len >= ICONV_CSNMAXLEN) {
    2895           0 :                 return NULL;
    2896             :         }
    2897             : 
    2898           6 :         if (NULL == (inst = pemalloc(sizeof(php_iconv_stream_filter), persistent))) {
    2899           0 :                 return NULL;
    2900             :         }
    2901             : 
    2902           6 :         if (php_iconv_stream_filter_ctor(inst, to_charset, to_charset_len, from_charset, from_charset_len, persistent) != PHP_ICONV_ERR_SUCCESS) {
    2903           0 :                 pefree(inst, persistent);
    2904           0 :                 return NULL;
    2905             :         }
    2906             : 
    2907           6 :         if (NULL == (retval = php_stream_filter_alloc(&php_iconv_stream_filter_ops, inst, persistent))) {
    2908           0 :                 php_iconv_stream_filter_dtor(inst);
    2909           0 :                 pefree(inst, persistent);
    2910             :         }
    2911             : 
    2912           6 :         return retval;
    2913             : }
    2914             : /* }}} */
    2915             : 
    2916             : /* {{{ php_iconv_stream_register_factory */
    2917       23922 : static php_iconv_err_t php_iconv_stream_filter_register_factory(void)
    2918             : {
    2919             :         static php_stream_filter_factory filter_factory = {
    2920             :                 php_iconv_stream_filter_factory_create
    2921             :         };
    2922             : 
    2923       23922 :         if (FAILURE == php_stream_filter_register_factory(
    2924             :                                 php_iconv_stream_filter_ops.label,
    2925             :                                 &filter_factory)) {
    2926           0 :                 return PHP_ICONV_ERR_UNKNOWN;
    2927             :         }
    2928       23922 :         return PHP_ICONV_ERR_SUCCESS;
    2929             : }
    2930             : /* }}} */
    2931             : 
    2932             : /* {{{ php_iconv_stream_unregister_factory */
    2933       23963 : static php_iconv_err_t php_iconv_stream_filter_unregister_factory(void)
    2934             : {
    2935       23963 :         if (FAILURE == php_stream_filter_unregister_factory(
    2936             :                                 php_iconv_stream_filter_ops.label)) {
    2937           0 :                 return PHP_ICONV_ERR_UNKNOWN;
    2938             :         }
    2939       23963 :         return PHP_ICONV_ERR_SUCCESS;
    2940             : }
    2941             : /* }}} */
    2942             : /* }}} */
    2943             : #endif
    2944             : 
    2945             : /*
    2946             :  * Local variables:
    2947             :  * tab-width: 4
    2948             :  * c-basic-offset: 4
    2949             :  * End:
    2950             :  * vim600: sw=4 ts=4 fdm=marker
    2951             :  * vim<600: sw=4 ts=4
    2952             :  */

Generated by: LCOV version 1.10

Generated at Sun, 18 Sep 2016 08:20:06 +0000 (7 days ago)

Copyright © 2005-2016 The PHP Group
All rights reserved.