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: 922 1241 74.3 %
Date: 2014-07-21 Functions: 40 40 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Tue, 22 Jul 2014 01:33:10 +0000 (10 days ago)

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