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