2001-01-09 15:22:45 +00:00
|
|
|
/*
|
|
|
|
+----------------------------------------------------------------------+
|
2001-12-11 15:32:16 +00:00
|
|
|
| PHP Version 4 |
|
2001-01-09 15:22:45 +00:00
|
|
|
+----------------------------------------------------------------------+
|
2001-12-11 15:32:16 +00:00
|
|
|
| Copyright (c) 1997-2002 The PHP Group |
|
2001-01-09 15:22:45 +00:00
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| This source file is subject to version 2.02 of the PHP license, |
|
|
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
|
|
| available at through the world-wide-web at |
|
|
|
|
| http://www.php.net/license/2_02.txt. |
|
|
|
|
| If you did not receive a copy of the PHP license and are unable to |
|
|
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
|
|
| license@php.net so we can mail you a copy immediately. |
|
|
|
|
+----------------------------------------------------------------------+
|
2001-12-13 14:31:16 +00:00
|
|
|
| Authors: Rui Hirokawa <rui_hirokawa@ybb.ne.jp> |
|
2001-01-09 15:22:45 +00:00
|
|
|
| Stig Bakken <ssb@fast.no> |
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
*/
|
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* $Id$ */
|
|
|
|
|
2001-05-24 10:07:29 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2001-01-09 15:22:45 +00:00
|
|
|
#include "php.h"
|
2002-09-04 05:17:16 +00:00
|
|
|
#include "php_globals.h"
|
|
|
|
#include "ext/standard/info.h"
|
|
|
|
#include "main/php_output.h"
|
|
|
|
#include "SAPI.h"
|
|
|
|
#include "php_ini.h"
|
2001-01-09 15:22:45 +00:00
|
|
|
|
2002-09-04 05:17:16 +00:00
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include "php_iconv.h"
|
|
|
|
|
|
|
|
#ifdef HAVE_ICONV
|
2001-01-09 15:22:45 +00:00
|
|
|
|
2002-03-21 20:22:05 +00:00
|
|
|
#ifdef HAVE_GICONV_H
|
|
|
|
#include <giconv.h>
|
|
|
|
#else
|
2001-05-27 19:43:16 +00:00
|
|
|
#include <iconv.h>
|
2002-03-21 20:22:05 +00:00
|
|
|
#endif
|
|
|
|
|
2002-10-11 17:48:39 +00:00
|
|
|
#ifdef HAVE_GLIBC_ICONV
|
|
|
|
#include <gnu/libc-version.h>
|
|
|
|
#endif
|
|
|
|
|
2002-09-04 05:17:16 +00:00
|
|
|
#ifdef HAVE_LIBICONV
|
2002-07-11 03:37:28 +00:00
|
|
|
#define LIBICONV_PLUG
|
2001-08-11 16:39:07 +00:00
|
|
|
#define icv_open(a, b) libiconv_open(a, b)
|
2001-01-31 16:57:00 +00:00
|
|
|
#define icv_close(a) libiconv_close(a)
|
2001-08-11 16:39:07 +00:00
|
|
|
#define icv(a, b, c, d, e) libiconv(a, b, c, d, e)
|
2001-01-31 16:57:00 +00:00
|
|
|
#else
|
2001-08-11 16:39:07 +00:00
|
|
|
#define icv_open(a, b) iconv_open(a, b)
|
2001-01-31 16:57:00 +00:00
|
|
|
#define icv_close(a) iconv_close(a)
|
2002-09-04 05:17:16 +00:00
|
|
|
#define icv(a, b, c, d, e) iconv(a, (char **) b, c, d, e)
|
2001-01-31 16:57:00 +00:00
|
|
|
#endif
|
|
|
|
|
2002-03-11 22:23:05 +00:00
|
|
|
/* {{{ iconv_functions[]
|
2001-06-05 13:12:10 +00:00
|
|
|
*/
|
2001-01-09 15:22:45 +00:00
|
|
|
function_entry iconv_functions[] = {
|
2001-10-22 02:28:00 +00:00
|
|
|
PHP_NAMED_FE(iconv,php_if_iconv, NULL)
|
2001-08-19 00:05:06 +00:00
|
|
|
PHP_FE(ob_iconv_handler, NULL)
|
|
|
|
PHP_FE(iconv_get_encoding, NULL)
|
|
|
|
PHP_FE(iconv_set_encoding, NULL)
|
2002-03-11 22:23:05 +00:00
|
|
|
{NULL, NULL, NULL}
|
2001-01-09 15:22:45 +00:00
|
|
|
};
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
2001-01-09 15:22:45 +00:00
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ iconv_module_entry
|
|
|
|
*/
|
2001-01-09 15:22:45 +00:00
|
|
|
zend_module_entry iconv_module_entry = {
|
2001-10-11 23:33:59 +00:00
|
|
|
STANDARD_MODULE_HEADER,
|
2001-01-09 15:22:45 +00:00
|
|
|
"iconv",
|
|
|
|
iconv_functions,
|
2001-05-27 19:43:16 +00:00
|
|
|
PHP_MINIT(miconv),
|
|
|
|
PHP_MSHUTDOWN(miconv),
|
2001-01-09 15:22:45 +00:00
|
|
|
NULL,
|
|
|
|
NULL,
|
2001-05-27 19:43:16 +00:00
|
|
|
PHP_MINFO(miconv),
|
2002-03-11 22:23:05 +00:00
|
|
|
NO_VERSION_YET,
|
2001-01-09 15:22:45 +00:00
|
|
|
STANDARD_MODULE_PROPERTIES
|
|
|
|
};
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
2001-01-09 15:22:45 +00:00
|
|
|
|
2001-05-27 19:43:16 +00:00
|
|
|
ZEND_DECLARE_MODULE_GLOBALS(iconv)
|
|
|
|
|
2001-01-09 15:22:45 +00:00
|
|
|
#ifdef COMPILE_DL_ICONV
|
|
|
|
ZEND_GET_MODULE(iconv)
|
|
|
|
#endif
|
|
|
|
|
2002-10-26 08:52:17 +00:00
|
|
|
/* {{{ typedef enum php_iconv_err_t */
|
|
|
|
typedef enum _php_iconv_err_t {
|
|
|
|
PHP_ICONV_ERR_SUCCESS = SUCCESS,
|
|
|
|
PHP_ICONV_ERR_CONVERTER = 1,
|
|
|
|
PHP_ICONV_ERR_WRONG_CHARSET = 2,
|
|
|
|
PHP_ICONV_ERR_TOO_BIG = 3,
|
|
|
|
PHP_ICONV_ERR_ILLEGAL_SEQ = 4,
|
|
|
|
PHP_ICONV_ERR_ILLEGAL_CHAR = 5,
|
|
|
|
PHP_ICONV_ERR_UNKNOWN = 6
|
|
|
|
} php_iconv_err_t;
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ prototypes */
|
|
|
|
static php_iconv_err_t php_iconv_string(const char * in_p, size_t in_len, char **out, size_t *out_len, const char *in_charset, const char *out_charset);
|
|
|
|
static void _php_iconv_show_error(php_iconv_err_t err, const char *in_charset, const char *out_charset TSRMLS_DC);
|
|
|
|
/* }}} */
|
2001-01-09 15:22:45 +00:00
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ PHP_INI
|
|
|
|
*/
|
2001-01-09 15:22:45 +00:00
|
|
|
PHP_INI_BEGIN()
|
2002-04-28 01:37:54 +00:00
|
|
|
STD_PHP_INI_ENTRY("iconv.input_encoding", ICONV_INPUT_ENCODING, PHP_INI_ALL, OnUpdateString, input_encoding, zend_iconv_globals, iconv_globals)
|
|
|
|
STD_PHP_INI_ENTRY("iconv.output_encoding", ICONV_OUTPUT_ENCODING, PHP_INI_ALL, OnUpdateString, output_encoding, zend_iconv_globals, iconv_globals)
|
|
|
|
STD_PHP_INI_ENTRY("iconv.internal_encoding", ICONV_INTERNAL_ENCODING, PHP_INI_ALL, OnUpdateString, internal_encoding, zend_iconv_globals, iconv_globals)
|
2001-01-09 15:22:45 +00:00
|
|
|
PHP_INI_END()
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
2001-01-09 15:22:45 +00:00
|
|
|
|
2002-11-08 18:06:31 +00:00
|
|
|
/* {{{ php_iconv_init_globals */
|
2001-08-19 00:05:06 +00:00
|
|
|
static void php_iconv_init_globals(zend_iconv_globals *iconv_globals)
|
2001-03-10 02:03:26 +00:00
|
|
|
{
|
|
|
|
iconv_globals->input_encoding = NULL;
|
|
|
|
iconv_globals->output_encoding = NULL;
|
|
|
|
iconv_globals->internal_encoding = NULL;
|
|
|
|
}
|
2002-10-26 08:52:17 +00:00
|
|
|
/* }}} */
|
2001-01-09 15:22:45 +00:00
|
|
|
|
2002-10-26 08:52:17 +00:00
|
|
|
/* {{{ PHP_MINIT_FUNCTION */
|
2001-05-27 19:43:16 +00:00
|
|
|
PHP_MINIT_FUNCTION(miconv)
|
2001-01-09 15:22:45 +00:00
|
|
|
{
|
2002-10-29 19:09:27 +00:00
|
|
|
char *version = "unknown";
|
2002-10-11 07:50:47 +00:00
|
|
|
|
2001-03-10 02:03:26 +00:00
|
|
|
ZEND_INIT_MODULE_GLOBALS(iconv, php_iconv_init_globals, NULL);
|
2001-01-09 15:22:45 +00:00
|
|
|
REGISTER_INI_ENTRIES();
|
2002-10-11 07:50:47 +00:00
|
|
|
|
|
|
|
#if HAVE_LIBICONV
|
|
|
|
{
|
|
|
|
static char buf[16];
|
2002-10-11 08:15:05 +00:00
|
|
|
snprintf(buf, sizeof(buf), "%d.%d",
|
|
|
|
((_libiconv_version >> 8) & 0x0f), (_libiconv_version & 0x0f));
|
2002-10-11 07:50:47 +00:00
|
|
|
version = buf;
|
|
|
|
}
|
2002-10-11 17:48:39 +00:00
|
|
|
#elif HAVE_GLIBC_ICONV
|
|
|
|
version = (char *)gnu_get_libc_version();
|
2002-10-11 07:50:47 +00:00
|
|
|
#endif
|
2002-10-11 17:48:39 +00:00
|
|
|
|
|
|
|
#ifdef PHP_ICONV_IMPL
|
|
|
|
REGISTER_STRING_CONSTANT("ICONV_IMPL", PHP_ICONV_IMPL, CONST_CS | CONST_PERSISTENT);
|
2002-11-14 23:07:53 +00:00
|
|
|
#elif HAVE_LIBICONV
|
|
|
|
REGISTER_STRING_CONSTANT("ICONV_IMPL", "libiconv", CONST_CS | CONST_PERSISTENT);
|
2002-10-11 17:01:34 +00:00
|
|
|
#else
|
|
|
|
REGISTER_STRING_CONSTANT("ICONV_IMPL", "unknown", CONST_CS | CONST_PERSISTENT);
|
|
|
|
#endif
|
2002-10-11 08:15:05 +00:00
|
|
|
REGISTER_STRING_CONSTANT("ICONV_VERSION", version, CONST_CS | CONST_PERSISTENT);
|
2002-10-11 07:50:47 +00:00
|
|
|
|
2001-01-09 15:22:45 +00:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
2002-10-26 08:52:17 +00:00
|
|
|
/* }}} */
|
2001-01-09 15:22:45 +00:00
|
|
|
|
2002-10-26 08:52:17 +00:00
|
|
|
/* {{{ PHP_MSHUTDOWN_FUNCTION */
|
2001-05-27 19:43:16 +00:00
|
|
|
PHP_MSHUTDOWN_FUNCTION(miconv)
|
2001-01-09 15:22:45 +00:00
|
|
|
{
|
|
|
|
UNREGISTER_INI_ENTRIES();
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
2002-10-26 08:52:17 +00:00
|
|
|
/* }}} */
|
2001-01-09 15:22:45 +00:00
|
|
|
|
2002-10-26 08:52:17 +00:00
|
|
|
/* {{{ PHP_MINFO_FUNCTION */
|
2001-05-27 19:43:16 +00:00
|
|
|
PHP_MINFO_FUNCTION(miconv)
|
2001-01-09 15:22:45 +00:00
|
|
|
{
|
2002-10-25 08:51:59 +00:00
|
|
|
zval iconv_impl, iconv_ver;
|
|
|
|
|
2002-10-25 11:50:35 +00:00
|
|
|
zend_get_constant("ICONV_IMPL", sizeof("ICONV_IMPL")-1, &iconv_impl TSRMLS_CC);
|
|
|
|
zend_get_constant("ICONV_VERSION", sizeof("ICONV_VERSION")-1, &iconv_ver TSRMLS_CC);
|
2002-10-25 08:51:59 +00:00
|
|
|
|
2001-01-09 15:22:45 +00:00
|
|
|
php_info_print_table_start();
|
2002-10-25 08:51:59 +00:00
|
|
|
php_info_print_table_row(2, "iconv support", "enabled");
|
|
|
|
php_info_print_table_row(2, "iconv implementation", Z_STRVAL(iconv_impl));
|
|
|
|
php_info_print_table_row(2, "iconv library version", Z_STRVAL(iconv_ver));
|
2001-01-09 15:22:45 +00:00
|
|
|
php_info_print_table_end();
|
|
|
|
|
|
|
|
DISPLAY_INI_ENTRIES();
|
2002-10-25 08:51:59 +00:00
|
|
|
|
|
|
|
zval_dtor(&iconv_impl);
|
|
|
|
zval_dtor(&iconv_ver);
|
2001-01-09 15:22:45 +00:00
|
|
|
}
|
2002-10-26 08:52:17 +00:00
|
|
|
/* }}} */
|
2001-01-09 15:22:45 +00:00
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ php_iconv_string
|
|
|
|
*/
|
2002-10-26 08:52:17 +00:00
|
|
|
php_iconv_err_t php_iconv_string(const char *in_p, size_t in_len,
|
2002-03-02 07:04:59 +00:00
|
|
|
char **out, size_t *out_len,
|
2002-10-26 08:52:17 +00:00
|
|
|
const char *in_charset, const char *out_charset)
|
2001-04-19 04:02:03 +00:00
|
|
|
{
|
2002-09-07 21:08:47 +00:00
|
|
|
#if !ICONV_SUPPORTS_ERRNO
|
2002-03-11 22:23:05 +00:00
|
|
|
unsigned int in_size, out_size, out_left;
|
|
|
|
char *out_buffer, *out_p;
|
|
|
|
iconv_t cd;
|
|
|
|
size_t result;
|
|
|
|
typedef unsigned int ucs4_t;
|
2002-03-02 07:04:59 +00:00
|
|
|
|
2002-11-06 16:54:18 +00:00
|
|
|
*out = NULL;
|
|
|
|
*out_len = 0;
|
2002-02-01 08:32:04 +00:00
|
|
|
|
2002-04-28 01:37:54 +00:00
|
|
|
/*
|
2002-03-02 07:04:59 +00:00
|
|
|
This is not the right way to get output size...
|
2002-02-01 08:32:04 +00:00
|
|
|
This is not space efficient for large text.
|
2002-02-28 03:09:01 +00:00
|
|
|
This is also problem for encoding like UTF-7/UTF-8/ISO-2022 which
|
2002-02-01 08:32:04 +00:00
|
|
|
a single char can be more than 4 bytes.
|
|
|
|
I added 15 extra bytes for safety. <yohgaki@php.net>
|
|
|
|
*/
|
2002-07-11 03:37:28 +00:00
|
|
|
out_size = in_len * sizeof(ucs4_t) + 15;
|
2002-02-01 08:32:04 +00:00
|
|
|
out_left = out_size;
|
2002-11-06 16:54:18 +00:00
|
|
|
|
|
|
|
in_size = in_len;
|
|
|
|
|
2002-03-11 22:23:05 +00:00
|
|
|
cd = icv_open(out_charset, in_charset);
|
|
|
|
|
2001-01-09 15:22:45 +00:00
|
|
|
if (cd == (iconv_t)(-1)) {
|
2002-10-26 08:52:17 +00:00
|
|
|
return PHP_ICONV_ERR_UNKNOWN;
|
2001-01-09 15:22:45 +00:00
|
|
|
}
|
2002-10-26 08:52:17 +00:00
|
|
|
|
|
|
|
out_buffer = (char *) emalloc(out_size + 1);
|
|
|
|
out_p = out_buffer;
|
2001-01-09 15:22:45 +00:00
|
|
|
|
2002-09-04 05:17:16 +00:00
|
|
|
result = icv(cd, (const char **) &in_p, &in_size, (char **)
|
2002-03-11 22:23:05 +00:00
|
|
|
&out_p, &out_left);
|
|
|
|
|
|
|
|
if (result == (size_t)(-1)) {
|
2002-02-01 08:32:04 +00:00
|
|
|
efree(out_buffer);
|
2002-10-26 08:52:17 +00:00
|
|
|
return PHP_ICONV_ERR_UNKNOWN;
|
2002-03-11 22:23:05 +00:00
|
|
|
}
|
|
|
|
|
2002-02-01 08:32:04 +00:00
|
|
|
*out_len = out_size - out_left;
|
2002-02-28 03:09:01 +00:00
|
|
|
out_buffer[*out_len] = '\0';
|
2002-11-06 16:54:18 +00:00
|
|
|
*out = out_buffer;
|
|
|
|
|
2002-03-11 22:23:05 +00:00
|
|
|
icv_close(cd);
|
2002-11-06 16:54:18 +00:00
|
|
|
|
2002-10-26 08:52:17 +00:00
|
|
|
return PHP_ICONV_ERR_SUCCESS;
|
2002-03-02 07:04:59 +00:00
|
|
|
|
|
|
|
#else
|
|
|
|
/*
|
2002-07-11 03:37:28 +00:00
|
|
|
iconv supports errno. Handle it better way.
|
2002-03-02 07:04:59 +00:00
|
|
|
*/
|
2002-03-11 22:23:05 +00:00
|
|
|
iconv_t cd;
|
|
|
|
size_t in_left, out_size, out_left;
|
|
|
|
char *out_p, *out_buf, *tmp_buf;
|
2002-08-05 18:26:06 +00:00
|
|
|
size_t bsz, result = 0;
|
2002-10-26 08:52:17 +00:00
|
|
|
php_iconv_err_t retval = PHP_ICONV_ERR_SUCCESS;
|
2002-03-02 07:04:59 +00:00
|
|
|
|
2002-11-06 16:54:18 +00:00
|
|
|
*out = NULL;
|
|
|
|
*out_len = 0;
|
|
|
|
|
2002-07-11 03:37:28 +00:00
|
|
|
cd = icv_open(out_charset, in_charset);
|
|
|
|
|
2002-03-02 07:04:59 +00:00
|
|
|
if (cd == (iconv_t)(-1)) {
|
|
|
|
if (errno == EINVAL) {
|
2002-10-26 08:52:17 +00:00
|
|
|
return PHP_ICONV_ERR_WRONG_CHARSET;
|
2002-07-11 03:37:28 +00:00
|
|
|
} else {
|
2002-10-26 08:52:17 +00:00
|
|
|
return PHP_ICONV_ERR_CONVERTER;
|
2002-03-02 07:04:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
in_left= in_len;
|
|
|
|
out_left = in_len + 32; /* Avoid realloc() most cases */
|
2002-07-11 03:37:28 +00:00
|
|
|
out_size = 0;
|
2002-03-02 07:04:59 +00:00
|
|
|
bsz = out_left;
|
2002-03-11 22:23:05 +00:00
|
|
|
out_buf = (char *) emalloc(bsz+1);
|
|
|
|
out_p = out_buf;
|
2002-07-11 03:37:28 +00:00
|
|
|
|
2002-11-06 16:29:16 +00:00
|
|
|
while (in_left > 0) {
|
2002-09-04 05:17:16 +00:00
|
|
|
result = icv(cd, (const char **) &in_p, &in_left, (char **) &out_p, &out_left);
|
2002-07-11 03:37:28 +00:00
|
|
|
out_size = bsz - out_left;
|
2002-11-06 16:29:16 +00:00
|
|
|
if (result == (size_t)(-1)) {
|
|
|
|
if (errno == E2BIG && in_left > 0) {
|
2002-07-11 03:37:28 +00:00
|
|
|
/* converted string is longer than out buffer */
|
|
|
|
bsz += in_len;
|
|
|
|
|
|
|
|
tmp_buf = (char*) erealloc(out_buf, bsz+1);
|
|
|
|
|
|
|
|
if (tmp_buf != NULL) {
|
|
|
|
out_p = out_buf = tmp_buf;
|
|
|
|
out_p += out_size;
|
|
|
|
out_left = bsz - out_size;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2002-03-02 07:04:59 +00:00
|
|
|
}
|
2002-07-11 03:37:28 +00:00
|
|
|
break;
|
2002-03-02 07:04:59 +00:00
|
|
|
}
|
2002-07-11 03:37:28 +00:00
|
|
|
icv_close(cd);
|
|
|
|
|
2002-03-11 22:23:05 +00:00
|
|
|
if (result == (size_t)(-1)) {
|
2002-03-02 07:04:59 +00:00
|
|
|
switch (errno) {
|
|
|
|
case EINVAL:
|
2002-10-26 08:52:17 +00:00
|
|
|
retval = PHP_ICONV_ERR_ILLEGAL_CHAR;
|
2002-03-02 07:04:59 +00:00
|
|
|
break;
|
2002-10-26 08:52:17 +00:00
|
|
|
|
2002-03-02 07:04:59 +00:00
|
|
|
case EILSEQ:
|
2002-10-26 08:52:17 +00:00
|
|
|
retval = PHP_ICONV_ERR_ILLEGAL_SEQ;
|
2002-03-02 07:04:59 +00:00
|
|
|
break;
|
|
|
|
case E2BIG:
|
|
|
|
/* should not happen */
|
2002-10-26 08:52:17 +00:00
|
|
|
retval = PHP_ICONV_ERR_TOO_BIG;
|
2002-03-02 07:04:59 +00:00
|
|
|
break;
|
2002-10-26 08:52:17 +00:00
|
|
|
|
2002-03-02 07:04:59 +00:00
|
|
|
default:
|
|
|
|
/* other error */
|
2002-10-26 08:52:17 +00:00
|
|
|
retval = PHP_ICONV_ERR_UNKNOWN;
|
2002-03-02 07:04:59 +00:00
|
|
|
efree(out_buf);
|
2002-10-26 08:52:17 +00:00
|
|
|
return PHP_ICONV_ERR_UNKNOWN;
|
2002-03-02 07:04:59 +00:00
|
|
|
}
|
2002-03-11 22:23:05 +00:00
|
|
|
}
|
2002-03-02 07:04:59 +00:00
|
|
|
*out_p = '\0';
|
|
|
|
*out = out_buf;
|
|
|
|
*out_len = out_size;
|
2002-10-26 08:52:17 +00:00
|
|
|
return retval;
|
2002-03-02 07:04:59 +00:00
|
|
|
#endif
|
2001-01-09 15:22:45 +00:00
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
2001-01-31 16:57:00 +00:00
|
|
|
|
2002-10-26 08:52:17 +00:00
|
|
|
/* {{{ php_iconv_show_error() */
|
|
|
|
static void _php_iconv_show_error(php_iconv_err_t err, const char *in_charset, const char *out_charset TSRMLS_DC)
|
|
|
|
{
|
|
|
|
switch (err) {
|
2002-10-30 19:21:56 +00:00
|
|
|
case PHP_ICONV_ERR_SUCCESS:
|
|
|
|
break;
|
|
|
|
|
2002-10-26 08:52:17 +00:00
|
|
|
case PHP_ICONV_ERR_CONVERTER:
|
2002-10-29 11:56:46 +00:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot open converter");
|
2002-10-26 08:52:17 +00:00
|
|
|
break;
|
2002-10-30 19:21:56 +00:00
|
|
|
|
2002-10-26 08:52:17 +00:00
|
|
|
case PHP_ICONV_ERR_WRONG_CHARSET:
|
2002-10-29 11:56:46 +00:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong charset, cannot convert from `%s' to `%s'",
|
2002-10-26 08:52:17 +00:00
|
|
|
in_charset, out_charset);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PHP_ICONV_ERR_ILLEGAL_CHAR:
|
2002-10-29 11:56:46 +00:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected incomplete character in input string");
|
2002-10-26 08:52:17 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PHP_ICONV_ERR_ILLEGAL_SEQ:
|
2002-10-29 11:56:46 +00:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected illegal character in input string");
|
2002-10-26 08:52:17 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PHP_ICONV_ERR_TOO_BIG:
|
|
|
|
/* should not happen */
|
2002-10-29 11:56:46 +00:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Run out buffer");
|
2002-10-26 08:52:17 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* other error */
|
2002-10-29 11:56:46 +00:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown error (%d)", errno);
|
2002-10-26 08:52:17 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2002-11-08 18:06:31 +00:00
|
|
|
/* }}} */
|
2002-10-26 08:52:17 +00:00
|
|
|
|
2001-01-09 15:22:45 +00:00
|
|
|
/* {{{ proto string iconv(string in_charset, string out_charset, string str)
|
2001-01-09 15:53:09 +00:00
|
|
|
Returns str converted to the out_charset character set */
|
2001-10-22 02:28:00 +00:00
|
|
|
PHP_NAMED_FUNCTION(php_if_iconv)
|
2001-01-09 15:22:45 +00:00
|
|
|
{
|
2002-03-11 22:23:05 +00:00
|
|
|
char *in_charset, *out_charset, *in_buffer, *out_buffer;
|
2002-11-08 18:40:54 +00:00
|
|
|
size_t out_len;
|
|
|
|
int in_charset_len, out_charset_len, in_buffer_len;
|
|
|
|
php_iconv_err_t err;
|
2001-05-27 19:43:16 +00:00
|
|
|
|
2002-03-11 22:23:05 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss",
|
|
|
|
&in_charset, &in_charset_len, &out_charset, &out_charset_len, &in_buffer, &in_buffer_len) == FAILURE)
|
|
|
|
return;
|
2001-01-09 15:22:45 +00:00
|
|
|
|
2002-11-08 18:40:54 +00:00
|
|
|
err = php_iconv_string(in_buffer, (size_t)in_buffer_len,
|
|
|
|
&out_buffer, &out_len, in_charset, out_charset);
|
2002-10-26 08:52:17 +00:00
|
|
|
_php_iconv_show_error(err, in_charset, out_charset TSRMLS_CC);
|
|
|
|
if (out_buffer != NULL) {
|
2002-02-28 03:09:01 +00:00
|
|
|
RETVAL_STRINGL(out_buffer, out_len, 0);
|
2001-01-09 15:22:45 +00:00
|
|
|
} else {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
}
|
2001-01-14 07:40:16 +00:00
|
|
|
/* }}} */
|
2001-01-09 15:22:45 +00:00
|
|
|
|
2001-05-04 03:55:48 +00:00
|
|
|
/* {{{ proto string ob_iconv_handler(string contents, int status)
|
2001-01-09 15:53:09 +00:00
|
|
|
Returns str in output buffer converted to the iconv.output_encoding character set */
|
2001-01-09 15:22:45 +00:00
|
|
|
PHP_FUNCTION(ob_iconv_handler)
|
|
|
|
{
|
2002-08-05 18:26:06 +00:00
|
|
|
char *out_buffer, *content_type, *mimetype = NULL, *s;
|
2002-03-11 22:23:05 +00:00
|
|
|
zval *zv_string;
|
2002-02-01 08:32:04 +00:00
|
|
|
unsigned int out_len;
|
2002-10-29 01:28:21 +00:00
|
|
|
int status, mimetype_alloced = 0;
|
2001-01-09 15:22:45 +00:00
|
|
|
|
2002-03-11 22:23:05 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl", &zv_string, &status) == FAILURE)
|
|
|
|
return;
|
2001-01-09 15:22:45 +00:00
|
|
|
|
2002-03-11 22:23:05 +00:00
|
|
|
convert_to_string_ex(&zv_string);
|
2001-05-04 03:55:48 +00:00
|
|
|
|
2002-08-05 18:26:06 +00:00
|
|
|
if (SG(sapi_headers).mimetype &&
|
2002-10-26 08:52:17 +00:00
|
|
|
strncasecmp(SG(sapi_headers).mimetype, "text/", 5) == 0) {
|
2002-08-05 18:26:06 +00:00
|
|
|
if ((s = strchr(SG(sapi_headers).mimetype,';')) == NULL){
|
2002-10-26 08:52:17 +00:00
|
|
|
mimetype = SG(sapi_headers).mimetype;
|
2002-08-05 18:26:06 +00:00
|
|
|
} else {
|
2002-08-05 18:42:41 +00:00
|
|
|
mimetype = estrndup(SG(sapi_headers).mimetype, s-SG(sapi_headers).mimetype);
|
2002-10-26 08:52:17 +00:00
|
|
|
mimetype_alloced = 1;
|
2002-08-05 18:26:06 +00:00
|
|
|
}
|
|
|
|
} else if (SG(sapi_headers).send_default_content_type) {
|
2002-10-26 08:52:17 +00:00
|
|
|
mimetype =(SG(default_mimetype) ? SG(default_mimetype) : SAPI_DEFAULT_MIMETYPE);
|
2002-08-05 18:26:06 +00:00
|
|
|
}
|
2002-10-26 08:52:17 +00:00
|
|
|
if (mimetype != NULL) {
|
|
|
|
php_iconv_err_t err = php_iconv_string(Z_STRVAL_P(zv_string),
|
|
|
|
Z_STRLEN_P(zv_string), &out_buffer, &out_len,
|
|
|
|
ICONVG(internal_encoding), ICONVG(output_encoding));
|
|
|
|
_php_iconv_show_error(err, ICONVG(internal_encoding), ICONVG(output_encoding) TSRMLS_CC);
|
|
|
|
if (out_buffer != NULL) {
|
|
|
|
spprintf(&content_type, 0, "Content-Type:%s; charset=%s", mimetype, ICONVG(output_encoding));
|
|
|
|
if (content_type && sapi_add_header(content_type, strlen(content_type), 0) != FAILURE) {
|
|
|
|
SG(sapi_headers).send_default_content_type = 0;
|
|
|
|
}
|
|
|
|
RETURN_STRINGL(out_buffer, out_len, 0);
|
|
|
|
}
|
|
|
|
if (mimetype_alloced) {
|
|
|
|
efree(mimetype);
|
2002-08-05 18:26:06 +00:00
|
|
|
}
|
2001-01-09 15:22:45 +00:00
|
|
|
}
|
2002-10-26 08:52:17 +00:00
|
|
|
|
|
|
|
zval_dtor(return_value);
|
|
|
|
*return_value = *zv_string;
|
|
|
|
zval_copy_ctor(return_value);
|
2001-01-09 15:22:45 +00:00
|
|
|
}
|
2001-01-14 07:40:16 +00:00
|
|
|
/* }}} */
|
2001-01-09 15:22:45 +00:00
|
|
|
|
2001-02-26 15:41:38 +00:00
|
|
|
/* {{{ proto bool iconv_set_encoding(string type, string charset)
|
2001-01-09 15:53:09 +00:00
|
|
|
Sets internal encoding and output encoding for ob_iconv_handler() */
|
2001-01-09 15:22:45 +00:00
|
|
|
PHP_FUNCTION(iconv_set_encoding)
|
|
|
|
{
|
2002-03-11 22:23:05 +00:00
|
|
|
char *type, *charset;
|
|
|
|
int type_len, charset_len, retval;
|
|
|
|
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &type, &type_len, &charset, &charset_len) == FAILURE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(!strcasecmp("input_encoding", type)) {
|
|
|
|
retval = zend_alter_ini_entry("iconv.input_encoding", sizeof("iconv.input_encoding"), charset, charset_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
|
|
|
|
} else if(!strcasecmp("output_encoding", type)) {
|
|
|
|
retval = zend_alter_ini_entry("iconv.output_encoding", sizeof("iconv.output_encoding"), charset, charset_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
|
|
|
|
} else if(!strcasecmp("internal_encoding", type)) {
|
|
|
|
retval = zend_alter_ini_entry("iconv.internal_encoding", sizeof("iconv.internal_encoding"), charset, charset_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
|
2001-02-26 15:41:38 +00:00
|
|
|
} else {
|
|
|
|
RETURN_FALSE;
|
2001-01-09 15:22:45 +00:00
|
|
|
}
|
|
|
|
|
2002-03-10 09:22:31 +00:00
|
|
|
if (retval == SUCCESS) {
|
|
|
|
RETURN_TRUE;
|
|
|
|
} else {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2001-01-09 15:22:45 +00:00
|
|
|
}
|
2001-01-14 07:40:16 +00:00
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto array iconv_get_encoding([string type])
|
|
|
|
Get internal encoding and output encoding for ob_iconv_handler() */
|
|
|
|
PHP_FUNCTION(iconv_get_encoding)
|
|
|
|
{
|
2002-03-11 22:23:05 +00:00
|
|
|
char *type = "all";
|
|
|
|
int type_len;
|
2001-01-14 07:40:16 +00:00
|
|
|
|
2002-03-11 22:23:05 +00:00
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &type, &type_len) == FAILURE)
|
|
|
|
return;
|
2001-01-14 07:40:16 +00:00
|
|
|
|
2002-03-11 22:23:05 +00:00
|
|
|
if (!strcasecmp("all", type)) {
|
2001-01-14 07:40:16 +00:00
|
|
|
if (array_init(return_value) == FAILURE) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2002-04-28 01:37:54 +00:00
|
|
|
add_assoc_string(return_value, "input_encoding", ICONVG(input_encoding), 1);
|
|
|
|
add_assoc_string(return_value, "output_encoding", ICONVG(output_encoding), 1);
|
|
|
|
add_assoc_string(return_value, "internal_encoding", ICONVG(internal_encoding), 1);
|
2002-03-11 22:23:05 +00:00
|
|
|
} else if (!strcasecmp("input_encoding", type)) {
|
2001-02-26 15:41:38 +00:00
|
|
|
RETVAL_STRING(ICONVG(input_encoding), 1);
|
2002-03-11 22:23:05 +00:00
|
|
|
} else if (!strcasecmp("output_encoding", type)) {
|
2001-01-14 07:40:16 +00:00
|
|
|
RETVAL_STRING(ICONVG(output_encoding), 1);
|
2002-03-11 22:23:05 +00:00
|
|
|
} else if (!strcasecmp("internal_encoding", type)) {
|
2001-01-14 07:40:16 +00:00
|
|
|
RETVAL_STRING(ICONVG(internal_encoding), 1);
|
|
|
|
} else {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2001-01-09 15:22:45 +00:00
|
|
|
|
2001-01-14 07:40:16 +00:00
|
|
|
}
|
2001-01-09 15:22:45 +00:00
|
|
|
/* }}} */
|
2001-01-14 07:40:16 +00:00
|
|
|
|
2001-01-09 15:22:45 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Local variables:
|
|
|
|
* tab-width: 4
|
|
|
|
* c-basic-offset: 4
|
|
|
|
* End:
|
2001-09-09 13:29:31 +00:00
|
|
|
* vim600: sw=4 ts=4 fdm=marker
|
|
|
|
* vim<600: sw=4 ts=4
|
2001-01-09 15:22:45 +00:00
|
|
|
*/
|