summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/standard/basic_functions.c3
-rw-r--r--ext/standard/config.m410
-rw-r--r--ext/standard/php_string.h1
-rw-r--r--ext/standard/string.c53
-rw-r--r--ext/standard/tests/string/001.phpt13
5 files changed, 78 insertions, 2 deletions
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index 5bcea01d01..a02f419379 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -183,7 +183,7 @@ function_entry basic_functions[] = {
PHP_FE(implode, NULL)
PHP_FE(setlocale, NULL)
PHP_FE(soundex, NULL)
- PHP_FE(levenshtein, NULL)
+ PHP_FE(levenshtein, NULL)
PHP_FE(chr, NULL)
PHP_FE(ord, NULL)
PHP_FE(parse_str, second_arg_force_ref)
@@ -194,6 +194,7 @@ function_entry basic_functions[] = {
PHP_NAMED_FE(printf, PHP_FN(user_printf), NULL)
PHP_FE(sscanf, third_and_rest_force_ref)
PHP_FE(fscanf, third_and_rest_force_ref)
+ PHP_FE(iconv, NULL)
PHP_FE(parse_url, NULL)
PHP_FE(urlencode, NULL)
diff --git a/ext/standard/config.m4 b/ext/standard/config.m4
index fe532aa1d7..0e61522999 100644
--- a/ext/standard/config.m4
+++ b/ext/standard/config.m4
@@ -162,5 +162,13 @@ AC_ARG_WITH(system-regex,
fi
])
-PHP_EXTENSION(standard)
+AC_CHECK_LIB(c, iconv_open, [
+ AC_DEFINE(HAVE_ICONV, 1, [ ])
+], [
+ AC_CHECK_LIB(iconv, iconv_open, [
+ EXTRA_LIBS="$EXTRA_LIBS -liconv"
+ AC_DEFINE(HAVE_ICONV, 1, [ ])
+ ])
+])
+PHP_EXTENSION(standard)
diff --git a/ext/standard/php_string.h b/ext/standard/php_string.h
index d4d89c8778..c60c214830 100644
--- a/ext/standard/php_string.h
+++ b/ext/standard/php_string.h
@@ -78,6 +78,7 @@ PHP_FUNCTION(strnatcasecmp);
PHP_FUNCTION(substr_count);
PHP_FUNCTION(str_pad);
PHP_FUNCTION(sscanf);
+PHP_FUNCTION(iconv);
#define strnatcmp(a, b) \
strnatcmp_ex(a, strlen(a), b, strlen(b), 0)
diff --git a/ext/standard/string.c b/ext/standard/string.c
index f32c901a8e..39cdd923d2 100644
--- a/ext/standard/string.c
+++ b/ext/standard/string.c
@@ -30,6 +30,9 @@
#ifdef HAVE_LOCALE_H
# include <locale.h>
#endif
+#ifdef HAVE_ICONV
+# include <iconv.h>
+#endif
#include "scanf.h"
#include "zend_API.h"
#include "zend_execute.h"
@@ -2986,6 +2989,56 @@ PHP_FUNCTION(sscanf)
}
/* }}} */
+#ifdef HAVE_ICONV
+/* {{{ proto iconv(string in_charset, string out_charset, string str)
+ Returns str converted to the out_charset character set.
+*/
+PHP_FUNCTION(iconv)
+{
+ zval **in_charset, **out_charset, **in_buffer;
+ unsigned int in_size, out_size;
+ char *out_buffer, *in_p, *out_p;
+ iconv_t cd;
+ size_t result;
+ typedef unsigned int ucs4_t;
+
+ if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &in_charset, &out_charset, &in_buffer) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_string_ex(in_charset);
+ convert_to_string_ex(out_charset);
+ convert_to_string_ex(in_buffer);
+
+ in_size = Z_STRLEN_PP(in_buffer) * sizeof(char) + 1;
+ out_size = Z_STRLEN_PP(in_buffer) * sizeof(ucs4_t) + 1;
+
+ out_buffer = (char *) emalloc(out_size);
+
+ in_p = Z_STRVAL_PP(in_buffer);
+ out_p = out_buffer;
+
+ cd = iconv_open(Z_STRVAL_PP(out_charset), Z_STRVAL_PP(in_charset));
+
+ if (cd == (iconv_t)(-1)) {
+ php_error(E_WARNING, "iconv: cannot convert from `%s' to `%s'",
+ Z_STRVAL_PP(in_charset), Z_STRVAL_PP(out_charset));
+ efree(out_buffer);
+ RETURN_FALSE;
+ }
+
+ result = iconv(cd, (const char **) &in_p, &in_size, (char **)
+ &out_p, &out_size);
+
+ if (result == (size_t)(-1)) {
+ sprintf(out_buffer, "???") ;
+ }
+
+ iconv_close(cd);
+
+ RETVAL_STRING(out_buffer, 0);
+}
+#endif
/*
* Local variables:
diff --git a/ext/standard/tests/string/001.phpt b/ext/standard/tests/string/001.phpt
new file mode 100644
index 0000000000..ac7c5dccc9
--- /dev/null
+++ b/ext/standard/tests/string/001.phpt
@@ -0,0 +1,13 @@
+--TEST--
+iconv test
+--FILE--
+<?php
+
+$test = "Stig Sæther Bakken";
+print "$test\n";
+printf("%s\n", iconv("iso-8859-1", "utf-8", $test));
+
+?>
+--EXPECT--
+Stig Sæther Bakken
+Stig Sæther Bakken