summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
Diffstat (limited to 'ext')
-rw-r--r--ext/ftp/ftp.stub.php176
-rw-r--r--ext/ftp/ftp_arginfo.h60
-rw-r--r--ext/ftp/php_ftp.c304
-rw-r--r--ext/ftp/tests/007.phpt66
-rw-r--r--ext/ftp/tests/CONFLICTS1
-rw-r--r--ext/ftp/tests/dead-resource.phpt24
-rw-r--r--ext/ftp/tests/ftp_set_option_errors.phpt50
-rw-r--r--ext/ftp/tests/server.inc78
-rw-r--r--ext/gd/gd.c182
-rw-r--r--ext/gd/gd.stub.php19
-rw-r--r--ext/gd/gd_arginfo.h15
-rwxr-xr-xext/hash/bench.php76
-rw-r--r--ext/imap/php_imap.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_7bit.c18
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_7bit.h1
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_armscii8.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_ascii.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_big5.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_cp1251.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_cp1252.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_cp1254.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_cp5022x.c6
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_cp51932.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_cp850.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_cp866.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_cp932.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_cp936.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_euc_cn.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_euc_jp.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_euc_jp_2004.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_euc_jp_win.c4
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_euc_kr.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_euc_tw.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_gb18030.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_htmlent.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso2022_jp_ms.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_mobile.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso8859_1.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso8859_10.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso8859_13.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso8859_14.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso8859_15.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso8859_16.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso8859_2.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso8859_3.c17
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso8859_4.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso8859_5.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso8859_6.c17
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso8859_7.c17
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso8859_8.c17
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_iso8859_9.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_koi8r.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_koi8u.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_qprint.c5
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_sjis.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_sjis_2004.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_sjis_mac.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_sjis_mobile.c6
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_sjis_open.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_ucs2.c29
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_ucs2.h3
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_ucs4.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_uhc.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_utf16.c350
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_utf16.h3
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_utf32.c171
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_utf32.h3
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_utf7.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_utf7imap.c84
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_utf8.c2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.c8
-rw-r--r--ext/mbstring/libmbfl/filters/unicode_prop.h272
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfilter.c31
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfilter_8bit.c8
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfilter_8bit.h1
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfilter_pass.c2
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfl_convert.c2
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfl_encoding.c100
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfl_encoding.h14
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfl_ident.c74
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfl_ident.h4
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfl_memory_device.c142
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfl_memory_device.h2
-rw-r--r--ext/mbstring/libmbfl/mbfl/mbfl_string.c25
-rw-r--r--ext/mbstring/mbstring.c10
-rw-r--r--ext/mbstring/tests/data/8859-1.txt292
-rw-r--r--ext/mbstring/tests/data/8859-10.txt292
-rw-r--r--ext/mbstring/tests/data/8859-11.txt286
-rw-r--r--ext/mbstring/tests/data/8859-13.txt291
-rw-r--r--ext/mbstring/tests/data/8859-14.txt292
-rw-r--r--ext/mbstring/tests/data/8859-15.txt294
-rw-r--r--ext/mbstring/tests/data/8859-16.txt293
-rw-r--r--ext/mbstring/tests/data/8859-2.txt292
-rw-r--r--ext/mbstring/tests/data/8859-3.txt285
-rw-r--r--ext/mbstring/tests/data/8859-4.txt292
-rw-r--r--ext/mbstring/tests/data/8859-5.txt292
-rw-r--r--ext/mbstring/tests/data/8859-6.txt249
-rw-r--r--ext/mbstring/tests/data/8859-7.txt299
-rw-r--r--ext/mbstring/tests/data/8859-8.txt258
-rw-r--r--ext/mbstring/tests/data/8859-9.txt294
-rw-r--r--ext/mbstring/tests/encoding_tests.inc98
-rw-r--r--ext/mbstring/tests/iso8859_encodings.phpt75
-rw-r--r--ext/mbstring/tests/mb_convert_encoding_failed_detection.phpt2
-rw-r--r--ext/mysqlnd/mysqlnd_ps.c2
-rw-r--r--ext/opcache/ZendAccelerator.c30
-rw-r--r--ext/opcache/zend_accelerator_blacklist.c10
-rw-r--r--ext/opcache/zend_accelerator_debug.c24
-rw-r--r--ext/opcache/zend_accelerator_debug.h1
-rw-r--r--ext/opcache/zend_accelerator_hash.c4
-rw-r--r--ext/opcache/zend_shared_alloc.c20
-rw-r--r--ext/pdo/pdo_dbh.c8
-rw-r--r--ext/pdo/php_pdo_driver.h5
-rw-r--r--ext/pdo_dblib/dblib_driver.c3
-rw-r--r--ext/pdo_firebird/firebird_driver.c6
-rw-r--r--ext/pdo_mysql/mysql_driver.c3
-rw-r--r--ext/pdo_oci/oci_driver.c7
-rw-r--r--ext/pdo_odbc/odbc_driver.c6
-rw-r--r--ext/pdo_pgsql/pgsql_driver.c1
-rw-r--r--ext/pdo_sqlite/sqlite_driver.c22
-rw-r--r--ext/pdo_sqlite/tests/gc.phpt24
-rw-r--r--ext/pspell/pspell.c305
-rw-r--r--ext/pspell/pspell.stub.php61
-rw-r--r--ext/pspell/pspell_arginfo.h42
-rw-r--r--ext/pspell/tests/003.phpt2
-rw-r--r--ext/session/tests/003.phpt2
-rw-r--r--ext/session/tests/004.phpt10
-rw-r--r--ext/session/tests/005.phpt14
-rw-r--r--ext/session/tests/006.phpt2
-rw-r--r--ext/session/tests/009.phpt4
-rw-r--r--ext/session/tests/012.phpt2
-rw-r--r--ext/session/tests/013.phpt4
-rw-r--r--ext/session/tests/014.phpt2
-rw-r--r--ext/session/tests/015.phpt4
-rw-r--r--ext/session/tests/018.phpt4
-rw-r--r--ext/session/tests/019.phpt2
-rw-r--r--ext/session/tests/020.phpt4
-rw-r--r--ext/session/tests/021.phpt10
-rw-r--r--ext/session/tests/023.phpt2
-rw-r--r--ext/session/tests/024.phpt10
-rw-r--r--ext/session/tests/025.phpt14
-rw-r--r--ext/session/tests/026.phpt2
-rw-r--r--ext/session/tests/027.phpt4
-rw-r--r--ext/session/tests/CONFLICTS1
-rw-r--r--ext/session/tests/bug41600.phpt4
-rw-r--r--ext/session/tests/bug42596.phpt2
-rw-r--r--ext/session/tests/rfc1867.phpt8
-rw-r--r--ext/session/tests/rfc1867_cleanup.phpt8
-rw-r--r--ext/session/tests/rfc1867_disabled.phpt8
-rw-r--r--ext/session/tests/rfc1867_disabled_2.phpt8
-rw-r--r--ext/session/tests/rfc1867_inter.phpt8
-rw-r--r--ext/session/tests/rfc1867_no_name.phpt8
-rw-r--r--ext/session/tests/rfc1867_sid_cookie.phpt8
-rw-r--r--ext/session/tests/rfc1867_sid_get.phpt6
-rw-r--r--ext/session/tests/rfc1867_sid_get_2.phpt8
-rw-r--r--ext/session/tests/rfc1867_sid_only_cookie.phpt8
-rw-r--r--ext/session/tests/rfc1867_sid_only_cookie_2.phpt4
-rw-r--r--ext/session/tests/rfc1867_sid_post.phpt4
-rw-r--r--ext/session/tests/session_basic1.phpt12
-rw-r--r--ext/session/tests/session_basic2.phpt4
-rw-r--r--ext/session/tests/session_basic3.phpt72
-rw-r--r--ext/session/tests/session_basic5.phpt188
-rw-r--r--ext/session/tests/session_commit_variation4.phpt14
-rw-r--r--ext/session/tests/session_module_name_variation4.phpt3
-rw-r--r--ext/session/tests/session_save_path_variation4.phpt4
-rw-r--r--ext/session/tests/session_save_path_variation5.phpt4
-rw-r--r--ext/session/tests/session_set_save_handler_basic.phpt4
-rw-r--r--ext/session/tests/session_set_save_handler_variation2.phpt4
-rw-r--r--ext/session/tests/session_set_save_handler_variation3.phpt6
-rw-r--r--ext/session/tests/session_set_save_handler_variation4.phpt6
-rw-r--r--ext/session/tests/session_set_save_handler_variation5.phpt4
-rw-r--r--ext/session/tests/session_set_save_handler_variation6.phpt4
-rw-r--r--ext/soap/tests/bug73037.phpt2
-rw-r--r--ext/soap/tests/custom_content_type.phpt2
-rw-r--r--ext/sockets/sockets.c6
-rw-r--r--ext/sodium/config.m43
-rw-r--r--ext/standard/array.c73
-rwxr-xr-xext/standard/basic_functions.c10
-rw-r--r--ext/standard/basic_functions.h2
-rw-r--r--ext/standard/mail.c2
-rw-r--r--ext/standard/php_http.h1
-rw-r--r--ext/standard/tests/streams/bug64433.phpt2
-rw-r--r--ext/standard/tests/url/get_headers_error_003.phpt2
-rw-r--r--ext/zip/php_zip.c4
-rw-r--r--ext/zip/tests/bug64342_0.phpt2
-rw-r--r--ext/zip/tests/bug64342_1-mb.phpt3
-rw-r--r--ext/zip/tests/bug64342_1.phpt3
186 files changed, 6498 insertions, 1778 deletions
diff --git a/ext/ftp/ftp.stub.php b/ext/ftp/ftp.stub.php
index f4812655a4..698cfe215c 100644
--- a/ext/ftp/ftp.stub.php
+++ b/ext/ftp/ftp.stub.php
@@ -2,133 +2,57 @@
/** @generate-function-entries */
-/** @return resource|false */
-function ftp_connect(string $hostname, int $port = 21, int $timeout = 90) {}
+function ftp_connect(string $hostname, int $port = 21, int $timeout = 90): FTPConnection|false {}
#ifdef HAVE_FTP_SSL
-/** @return resource|false */
-function ftp_ssl_connect(string $hostname, int $port = 21, int $timeout = 90) {}
+function ftp_ssl_connect(string $hostname, int $port = 21, int $timeout = 90): FTPConnection|false {}
#endif
-/** @param resource $ftp */
-function ftp_login($ftp, string $username, string $password): bool {}
-
-/** @param resource $ftp */
-function ftp_pwd($ftp): string|false {}
-
-/** @param resource $ftp */
-function ftp_cdup($ftp): bool {}
-
-/** @param resource $ftp */
-function ftp_chdir($ftp, string $directory): bool {}
-
-/** @param resource $ftp */
-function ftp_exec($ftp, string $command): bool {}
-
-/** @param resource $ftp */
-function ftp_raw($ftp, string $command): array {}
-
-/** @param resource $ftp */
-function ftp_mkdir($ftp, string $directory): string|false {}
-
-/** @param resource $ftp */
-function ftp_rmdir($ftp, string $directory): bool {}
-
-/** @param resource $ftp */
-function ftp_chmod($ftp, int $permissions, string $filename): int|false {}
-
-/**
- * @param resource $ftp
- * @param string $response
- */
-function ftp_alloc($ftp, int $size, &$response = null): bool {}
-
-/** @param resource $ftp */
-function ftp_nlist($ftp, string $directory): array|false {}
-
-/** @param resource $ftp */
-function ftp_rawlist($ftp, string $directory, bool $recursive = false): array|false {}
-
-/** @param resource $ftp */
-function ftp_mlsd($ftp, string $directory): array|false {}
-
-/** @param resource $ftp */
-function ftp_systype($ftp): string|false {}
-
-/**
- * @param resource $ftp
- * @param resource $stream
- */
-function ftp_fget($ftp, $stream, string $remote_filename, int $mode = FTP_BINARY, int $offset = 0): bool {}
-
-/**
- * @param resource $ftp
- * @param resource $stream
- */
-function ftp_nb_fget($ftp, $stream, string $remote_filename, int $mode = FTP_BINARY, int $offset = 0): int {}
-
-/** @param resource $ftp */
-function ftp_pasv($ftp, bool $enable): bool {}
-
-/** @param resource $ftp */
-function ftp_get($ftp, string $local_filename, string $remote_filename, int $mode = FTP_BINARY, int $offset = 0): bool {}
-
-/** @param resource $ftp */
-function ftp_nb_get($ftp, string $local_filename, string $remote_filename, int $mode = FTP_BINARY, int $offset = 0): int {}
-
-/** @param resource $ftp */
-function ftp_nb_continue($ftp): int {}
-
-/**
- * @param resource $ftp
- * @param resource $stream
- */
-function ftp_fput($ftp, string $remote_filename, $stream, int $mode = FTP_BINARY, int $offset = 0): bool {}
-
-/**
- * @param resource $ftp
- * @param resource $stream
- */
-function ftp_nb_fput($ftp, string $remote_filename, $stream, int $mode = FTP_BINARY, int $offset = 0): int {}
-
-/** @param resource $ftp */
-function ftp_put($ftp, string $remote_filename, string $local_filename, int $mode = FTP_BINARY, int $offset = 0): bool {}
-
-/** @param resource $ftp */
-function ftp_append($ftp, string $remote_filename, string $local_filename, int $mode = FTP_BINARY): bool {}
-
-/** @param resource $ftp */
-function ftp_nb_put($ftp, string $remote_filename, string $local_filename, int $mode = FTP_BINARY, int $offset = 0): int|false {}
-
-/** @param resource $ftp */
-function ftp_size($ftp, string $filename): int {}
-
-/** @param resource $ftp */
-function ftp_mdtm($ftp, string $filename): int {}
-
-/** @param resource $ftp */
-function ftp_rename($ftp, string $from, string $to): bool {}
-
-/** @param resource $ftp */
-function ftp_delete($ftp, string $filename): bool {}
-
-/** @param resource $ftp */
-function ftp_site($ftp, string $command): bool {}
-
-/** @param resource $ftp */
-function ftp_close($ftp): bool {}
-
-/**
- * @param resource $ftp
- * @alias ftp_close
- */
-function ftp_quit($ftp): bool {}
-
-/**
- * @param resource $ftp
- * @param int|bool $value
- */
-function ftp_set_option($ftp, int $option, $value): bool {}
-
-/** @param resource $ftp */
-function ftp_get_option($ftp, int $option): int|bool {}
+function ftp_login(FTPConnection $ftp, string $username, string $password): bool {}
+function ftp_pwd(FTPConnection $ftp): string|false {}
+function ftp_cdup(FTPConnection $ftp): bool {}
+function ftp_chdir(FTPConnection $ftp, string $directory): bool {}
+function ftp_exec(FTPConnection $ftp, string $command): bool {}
+function ftp_raw(FTPConnection $ftp, string $command): array {}
+function ftp_mkdir(FTPConnection $ftp, string $directory): string|false {}
+function ftp_rmdir(FTPConnection $ftp, string $directory): bool {}
+function ftp_chmod(FTPConnection $ftp, int $permissions, string $filename): int|false {}
+
+/** @param string $response */
+function ftp_alloc(FTPConnection $ftp, int $size, &$response = null): bool {}
+function ftp_nlist(FTPConnection $ftp, string $directory): array|false {}
+function ftp_rawlist(FTPConnection $ftp, string $directory, bool $recursive = false): array|false {}
+function ftp_mlsd(FTPConnection $ftp, string $directory): array|false {}
+function ftp_systype(FTPConnection $ftp): string|false {}
+
+/** @param resource $stream */
+function ftp_fget(FTPConnection $ftp, $stream, string $remote_filename, int $mode = FTP_BINARY, int $offset = 0): bool {}
+
+/** @param resource $stream */
+function ftp_nb_fget(FTPConnection $ftp, $stream, string $remote_filename, int $mode = FTP_BINARY, int $offset = 0): int {}
+function ftp_pasv(FTPConnection $ftp, bool $enable): bool {}
+function ftp_get(FTPConnection $ftp, string $local_filename, string $remote_filename, int $mode = FTP_BINARY, int $offset = 0): bool {}
+function ftp_nb_get(FTPConnection $ftp, string $local_filename, string $remote_filename, int $mode = FTP_BINARY, int $offset = 0): int {}
+function ftp_nb_continue(FTPConnection $ftp): int {}
+
+/** @param resource $stream */
+function ftp_fput(FTPConnection $ftp, string $remote_filename, $stream, int $mode = FTP_BINARY, int $offset = 0): bool {}
+
+/** @param resource $stream */
+function ftp_nb_fput(FTPConnection $ftp, string $remote_filename, $stream, int $mode = FTP_BINARY, int $offset = 0): int {}
+function ftp_put(FTPConnection $ftp, string $remote_filename, string $local_filename, int $mode = FTP_BINARY, int $offset = 0): bool {}
+function ftp_append(FTPConnection $ftp, string $remote_filename, string $local_filename, int $mode = FTP_BINARY): bool {}
+function ftp_nb_put(FTPConnection $ftp, string $remote_filename, string $local_filename, int $mode = FTP_BINARY, int $offset = 0): int|false {}
+function ftp_size(FTPConnection $ftp, string $filename): int {}
+function ftp_mdtm(FTPConnection $ftp, string $filename): int {}
+function ftp_rename(FTPConnection $ftp, string $from, string $to): bool {}
+function ftp_delete(FTPConnection $ftp, string $filename): bool {}
+function ftp_site(FTPConnection $ftp, string $command): bool {}
+function ftp_close(FTPConnection $ftp): bool {}
+
+/** @alias ftp_close */
+function ftp_quit(FTPConnection $ftp): bool {}
+
+/** @param int|bool $value */
+function ftp_set_option(FTPConnection $ftp, int $option, $value): bool {}
+function ftp_get_option(FTPConnection $ftp, int $option): int|bool {}
diff --git a/ext/ftp/ftp_arginfo.h b/ext/ftp/ftp_arginfo.h
index e1a9d770bc..30251b87ee 100644
--- a/ext/ftp/ftp_arginfo.h
+++ b/ext/ftp/ftp_arginfo.h
@@ -1,14 +1,14 @@
/* This is a generated file, edit the .stub.php file instead.
- * Stub hash: 4957601533b387d70ebb15811821fc06507cdbc2 */
+ * Stub hash: 151310a13eeeb2bbf4df1ab38a3a29506b26a570 */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_connect, 0, 0, 1)
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_ftp_connect, 0, 1, FTPConnection, MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, hostname, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, port, IS_LONG, 0, "21")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timeout, IS_LONG, 0, "90")
ZEND_END_ARG_INFO()
#if defined(HAVE_FTP_SSL)
-ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_ssl_connect, 0, 0, 1)
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_ftp_ssl_connect, 0, 1, FTPConnection, MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, hostname, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, port, IS_LONG, 0, "21")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timeout, IS_LONG, 0, "90")
@@ -16,60 +16,60 @@ ZEND_END_ARG_INFO()
#endif
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_login, 0, 3, _IS_BOOL, 0)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, username, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, password, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_ftp_pwd, 0, 1, MAY_BE_STRING|MAY_BE_FALSE)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_cdup, 0, 1, _IS_BOOL, 0)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_chdir, 0, 2, _IS_BOOL, 0)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, directory, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_exec, 0, 2, _IS_BOOL, 0)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, command, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_raw, 0, 2, IS_ARRAY, 0)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, command, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_ftp_mkdir, 0, 2, MAY_BE_STRING|MAY_BE_FALSE)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, directory, IS_STRING, 0)
ZEND_END_ARG_INFO()
#define arginfo_ftp_rmdir arginfo_ftp_chdir
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_ftp_chmod, 0, 3, MAY_BE_LONG|MAY_BE_FALSE)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, permissions, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_alloc, 0, 2, _IS_BOOL, 0)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, size, IS_LONG, 0)
ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, response, "null")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_ftp_nlist, 0, 2, MAY_BE_ARRAY|MAY_BE_FALSE)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, directory, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_ftp_rawlist, 0, 2, MAY_BE_ARRAY|MAY_BE_FALSE)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, directory, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, recursive, _IS_BOOL, 0, "false")
ZEND_END_ARG_INFO()
@@ -79,7 +79,7 @@ ZEND_END_ARG_INFO()
#define arginfo_ftp_systype arginfo_ftp_pwd
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_fget, 0, 3, _IS_BOOL, 0)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_INFO(0, stream)
ZEND_ARG_TYPE_INFO(0, remote_filename, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "FTP_BINARY")
@@ -87,7 +87,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_fget, 0, 3, _IS_BOOL, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_nb_fget, 0, 3, IS_LONG, 0)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_INFO(0, stream)
ZEND_ARG_TYPE_INFO(0, remote_filename, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "FTP_BINARY")
@@ -95,12 +95,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_nb_fget, 0, 3, IS_LONG, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_pasv, 0, 2, _IS_BOOL, 0)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, enable, _IS_BOOL, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_get, 0, 3, _IS_BOOL, 0)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, local_filename, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, remote_filename, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "FTP_BINARY")
@@ -108,7 +108,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_get, 0, 3, _IS_BOOL, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_nb_get, 0, 3, IS_LONG, 0)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, local_filename, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, remote_filename, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "FTP_BINARY")
@@ -116,11 +116,11 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_nb_get, 0, 3, IS_LONG, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_nb_continue, 0, 1, IS_LONG, 0)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_fput, 0, 3, _IS_BOOL, 0)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, remote_filename, IS_STRING, 0)
ZEND_ARG_INFO(0, stream)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "FTP_BINARY")
@@ -128,7 +128,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_fput, 0, 3, _IS_BOOL, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_nb_fput, 0, 3, IS_LONG, 0)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, remote_filename, IS_STRING, 0)
ZEND_ARG_INFO(0, stream)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "FTP_BINARY")
@@ -136,7 +136,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_nb_fput, 0, 3, IS_LONG, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_put, 0, 3, _IS_BOOL, 0)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, remote_filename, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, local_filename, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "FTP_BINARY")
@@ -144,14 +144,14 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_put, 0, 3, _IS_BOOL, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_append, 0, 3, _IS_BOOL, 0)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, remote_filename, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, local_filename, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "FTP_BINARY")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_ftp_nb_put, 0, 3, MAY_BE_LONG|MAY_BE_FALSE)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, remote_filename, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, local_filename, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "FTP_BINARY")
@@ -159,20 +159,20 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_ftp_nb_put, 0, 3, MAY_BE_LONG|MA
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_size, 0, 2, IS_LONG, 0)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0)
ZEND_END_ARG_INFO()
#define arginfo_ftp_mdtm arginfo_ftp_size
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_rename, 0, 3, _IS_BOOL, 0)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, from, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, to, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_delete, 0, 2, _IS_BOOL, 0)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0)
ZEND_END_ARG_INFO()
@@ -183,13 +183,13 @@ ZEND_END_ARG_INFO()
#define arginfo_ftp_quit arginfo_ftp_cdup
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ftp_set_option, 0, 3, _IS_BOOL, 0)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, option, IS_LONG, 0)
ZEND_ARG_INFO(0, value)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_ftp_get_option, 0, 2, MAY_BE_LONG|MAY_BE_BOOL)
- ZEND_ARG_INFO(0, ftp)
+ ZEND_ARG_OBJ_INFO(0, ftp, FTPConnection, 0)
ZEND_ARG_TYPE_INFO(0, option, IS_LONG, 0)
ZEND_END_ARG_INFO()
diff --git a/ext/ftp/php_ftp.c b/ext/ftp/php_ftp.c
index a6dca8c874..30bffbdd8c 100644
--- a/ext/ftp/php_ftp.c
+++ b/ext/ftp/php_ftp.c
@@ -29,13 +29,15 @@
#include "ext/standard/info.h"
#include "ext/standard/file.h"
+#include "Zend/zend_exceptions.h"
+#include "Zend/zend_interfaces.h"
#include "php_ftp.h"
#include "ftp.h"
#include "ftp_arginfo.h"
-static int le_ftpbuf;
-#define le_ftpbuf_name "FTP Buffer"
+static zend_class_entry *php_ftp_ce = NULL;
+static zend_object_handlers ftp_object_handlers;
zend_module_entry php_ftp_module_entry = {
STANDARD_MODULE_HEADER_EX,
@@ -56,15 +58,42 @@ zend_module_entry php_ftp_module_entry = {
ZEND_GET_MODULE(php_ftp)
#endif
-static void ftp_destructor_ftpbuf(zend_resource *rsrc)
-{
- ftpbuf_t *ftp = (ftpbuf_t *)rsrc->ptr;
+typedef struct _php_ftp_object {
+ ftpbuf_t *ftp;
+ zend_object std;
+} php_ftp_object;
+
+static inline zend_object *ftp_object_to_zend_object(php_ftp_object *obj) {
+ return ((zend_object*)(obj + 1)) - 1;
+}
+
+static inline php_ftp_object *ftp_object_from_zend_object(zend_object *zobj) {
+ return ((php_ftp_object*)(zobj + 1)) - 1;
+}
+
+static zend_object* ftp_object_create(zend_class_entry* ce) {
+ php_ftp_object *obj = zend_object_alloc(sizeof(php_ftp_object), ce);
+ zend_object *zobj = ftp_object_to_zend_object(obj);
+ obj->ftp = NULL;
+ zend_object_std_init(zobj, ce);
+ object_properties_init(zobj, ce);
+ zobj->handlers = &ftp_object_handlers;
- ftp_close(ftp);
+ return zobj;
+}
+
+static void ftp_object_destroy(zend_object *zobj) {
+ php_ftp_object *obj = ftp_object_from_zend_object(zobj);
+
+ if (obj->ftp) {
+ ftp_close(obj->ftp);
+ }
}
PHP_MINIT_FUNCTION(ftp)
{
+ zend_class_entry ce;
+
#ifdef HAVE_FTP_SSL
#if OPENSSL_VERSION_NUMBER < 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER)
SSL_library_init();
@@ -76,7 +105,18 @@ PHP_MINIT_FUNCTION(ftp)
#endif
#endif
- le_ftpbuf = zend_register_list_destructors_ex(ftp_destructor_ftpbuf, NULL, le_ftpbuf_name, module_number);
+ INIT_CLASS_ENTRY(ce, "FTPConnection", NULL);
+ php_ftp_ce = zend_register_internal_class(&ce);
+ php_ftp_ce->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NO_DYNAMIC_PROPERTIES;
+ php_ftp_ce->create_object = ftp_object_create;
+ php_ftp_ce->serialize = zend_class_serialize_deny;
+ php_ftp_ce->unserialize = zend_class_unserialize_deny;
+
+ memcpy(&ftp_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
+ ftp_object_handlers.offset = XtOffsetOf(php_ftp_object, std);
+ ftp_object_handlers.dtor_obj = ftp_object_destroy;
+ ftp_object_handlers.clone_obj = NULL;
+
REGISTER_LONG_CONSTANT("FTP_ASCII", FTPTYPE_ASCII, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("FTP_TEXT", FTPTYPE_ASCII, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("FTP_BINARY", FTPTYPE_IMAGE, CONST_PERSISTENT | CONST_CS);
@@ -143,7 +183,8 @@ PHP_FUNCTION(ftp_connect)
ftp->use_ssl = 0;
#endif
- RETURN_RES(zend_register_resource(ftp, le_ftpbuf));
+ object_init_ex(return_value, php_ftp_ce);
+ ftp_object_from_zend_object(Z_OBJ_P(return_value))->ftp = ftp;
}
/* }}} */
@@ -177,11 +218,19 @@ PHP_FUNCTION(ftp_ssl_connect)
/* enable ssl */
ftp->use_ssl = 1;
- RETURN_RES(zend_register_resource(ftp, le_ftpbuf));
+ object_init_ex(return_value, php_ftp_ce);
+ ftp_object_from_zend_object(Z_OBJ_P(return_value))->ftp = ftp;
}
/* }}} */
#endif
+#define GET_FTPBUF(ftpbuf, zftp) \
+ ftpbuf = ftp_object_from_zend_object(Z_OBJ_P(zftp))->ftp; \
+ if (!ftpbuf) { \
+ zend_throw_exception(zend_ce_value_error, "FTPConnection is already closed", 0); \
+ RETURN_THROWS(); \
+ }
+
/* {{{ Logs into the FTP server */
PHP_FUNCTION(ftp_login)
{
@@ -190,13 +239,10 @@ PHP_FUNCTION(ftp_login)
char *user, *pass;
size_t user_len, pass_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rss", &z_ftp, &user, &user_len, &pass, &pass_len) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oss", &z_ftp, php_ftp_ce, &user, &user_len, &pass, &pass_len) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
/* log in */
if (!ftp_login(ftp, user, user_len, pass, pass_len)) {
@@ -215,13 +261,10 @@ PHP_FUNCTION(ftp_pwd)
ftpbuf_t *ftp;
const char *pwd;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &z_ftp) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &z_ftp, php_ftp_ce) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
if (!(pwd = ftp_pwd(ftp))) {
php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
@@ -238,13 +281,10 @@ PHP_FUNCTION(ftp_cdup)
zval *z_ftp;
ftpbuf_t *ftp;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &z_ftp) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &z_ftp, php_ftp_ce) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
if (!ftp_cdup(ftp)) {
php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
@@ -263,13 +303,10 @@ PHP_FUNCTION(ftp_chdir)
char *dir;
size_t dir_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &z_ftp, &dir, &dir_len) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &z_ftp, php_ftp_ce, &dir, &dir_len) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
/* change directories */
if (!ftp_chdir(ftp, dir, dir_len)) {
@@ -289,13 +326,10 @@ PHP_FUNCTION(ftp_exec)
char *cmd;
size_t cmd_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &z_ftp, &cmd, &cmd_len) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &z_ftp, php_ftp_ce, &cmd, &cmd_len) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
/* execute serverside command */
if (!ftp_exec(ftp, cmd, cmd_len)) {
@@ -315,13 +349,10 @@ PHP_FUNCTION(ftp_raw)
char *cmd;
size_t cmd_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &z_ftp, &cmd, &cmd_len) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &z_ftp, php_ftp_ce, &cmd, &cmd_len) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
/* execute arbitrary ftp command */
ftp_raw(ftp, cmd, cmd_len, return_value);
@@ -337,13 +368,10 @@ PHP_FUNCTION(ftp_mkdir)
zend_string *tmp;
size_t dir_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &z_ftp, &dir, &dir_len) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &z_ftp, php_ftp_ce, &dir, &dir_len) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
/* create directory */
if (NULL == (tmp = ftp_mkdir(ftp, dir, dir_len))) {
@@ -363,13 +391,10 @@ PHP_FUNCTION(ftp_rmdir)
char *dir;
size_t dir_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &z_ftp, &dir, &dir_len) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &z_ftp, php_ftp_ce, &dir, &dir_len) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
/* remove directorie */
if (!ftp_rmdir(ftp, dir, dir_len)) {
@@ -390,13 +415,10 @@ PHP_FUNCTION(ftp_chmod)
size_t filename_len;
zend_long mode;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlp", &z_ftp, &mode, &filename, &filename_len) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Olp", &z_ftp, php_ftp_ce, &mode, &filename, &filename_len) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
if (!ftp_chmod(ftp, mode, filename, filename_len)) {
php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
@@ -415,13 +437,10 @@ PHP_FUNCTION(ftp_alloc)
zend_long size, ret;
zend_string *response = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl|z", &z_ftp, &size, &zresponse) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol|z", &z_ftp, php_ftp_ce, &size, &zresponse) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
ret = ftp_alloc(ftp, size, zresponse ? &response : NULL);
@@ -445,13 +464,10 @@ PHP_FUNCTION(ftp_nlist)
char **nlist, **ptr, *dir;
size_t dir_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rp", &z_ftp, &dir, &dir_len) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Op", &z_ftp, php_ftp_ce, &dir, &dir_len) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
/* get list of files */
if (NULL == (nlist = ftp_nlist(ftp, dir, dir_len))) {
@@ -475,13 +491,10 @@ PHP_FUNCTION(ftp_rawlist)
size_t dir_len;
zend_bool recursive = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|b", &z_ftp, &dir, &dir_len, &recursive) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os|b", &z_ftp, php_ftp_ce, &dir, &dir_len, &recursive) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
/* get raw directory listing */
if (NULL == (llist = ftp_list(ftp, dir, dir_len, recursive))) {
@@ -505,13 +518,10 @@ PHP_FUNCTION(ftp_mlsd)
size_t dir_len;
zval entry;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &z_ftp, &dir, &dir_len) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &z_ftp, php_ftp_ce, &dir, &dir_len) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
/* get raw directory listing */
if (NULL == (llist = ftp_mlsd(ftp, dir, dir_len))) {
@@ -539,13 +549,10 @@ PHP_FUNCTION(ftp_systype)
ftpbuf_t *ftp;
const char *syst;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &z_ftp) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &z_ftp, php_ftp_ce) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
if (NULL == (syst = ftp_syst(ftp))) {
php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
@@ -567,13 +574,10 @@ PHP_FUNCTION(ftp_fget)
size_t file_len;
zend_long mode=FTPTYPE_IMAGE, resumepos=0;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrs|ll", &z_ftp, &z_file, &file, &file_len, &mode, &resumepos) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ors|ll", &z_ftp, php_ftp_ce, &z_file, &file, &file_len, &mode, &resumepos) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
php_stream_from_res(stream, Z_RES_P(z_file));
XTYPE(xtype, mode);
@@ -612,13 +616,10 @@ PHP_FUNCTION(ftp_nb_fget)
size_t file_len;
zend_long mode=FTPTYPE_IMAGE, resumepos=0, ret;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrs|ll", &z_ftp, &z_file, &file, &file_len, &mode, &resumepos) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ors|ll", &z_ftp, php_ftp_ce, &z_file, &file, &file_len, &mode, &resumepos) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
php_stream_from_res(stream, Z_RES_P(z_file));
XTYPE(xtype, mode);
@@ -657,13 +658,10 @@ PHP_FUNCTION(ftp_pasv)
ftpbuf_t *ftp;
zend_bool pasv;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rb", &z_ftp, &pasv) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ob", &z_ftp, php_ftp_ce, &pasv) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
if (!ftp_pasv(ftp, pasv ? 1 : 0)) {
RETURN_FALSE;
@@ -684,13 +682,10 @@ PHP_FUNCTION(ftp_get)
size_t local_len, remote_len;
zend_long mode=FTPTYPE_IMAGE, resumepos=0;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rpp|ll", &z_ftp, &local, &local_len, &remote, &remote_len, &mode, &resumepos) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Opp|ll", &z_ftp, php_ftp_ce, &local, &local_len, &remote, &remote_len, &mode, &resumepos) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
XTYPE(xtype, mode);
/* ignore autoresume if autoseek is switched off */
@@ -749,13 +744,10 @@ PHP_FUNCTION(ftp_nb_get)
int ret;
zend_long mode=FTPTYPE_IMAGE, resumepos=0;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rss|ll", &z_ftp, &local, &local_len, &remote, &remote_len, &mode, &resumepos) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oss|ll", &z_ftp, php_ftp_ce, &local, &local_len, &remote, &remote_len, &mode, &resumepos) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
XTYPE(xtype, mode);
/* ignore autoresume if autoseek is switched off */
@@ -816,13 +808,10 @@ PHP_FUNCTION(ftp_nb_continue)
ftpbuf_t *ftp;
zend_long ret;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &z_ftp) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &z_ftp, php_ftp_ce) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
if (!ftp->nb) {
php_error_docref(NULL, E_WARNING, "No nbronous transfer to continue");
@@ -859,13 +848,10 @@ PHP_FUNCTION(ftp_fput)
php_stream *stream;
char *remote;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsr|ll", &z_ftp, &remote, &remote_len, &z_file, &mode, &startpos) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Osr|ll", &z_ftp, php_ftp_ce, &remote, &remote_len, &z_file, &mode, &startpos) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
php_stream_from_zval(stream, z_file);
XTYPE(xtype, mode);
@@ -908,13 +894,10 @@ PHP_FUNCTION(ftp_nb_fput)
php_stream *stream;
char *remote;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsr|ll", &z_ftp, &remote, &remote_len, &z_file, &mode, &startpos) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Osr|ll", &z_ftp, php_ftp_ce, &remote, &remote_len, &z_file, &mode, &startpos) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
php_stream_from_res(stream, Z_RES_P(z_file));
XTYPE(xtype, mode);
@@ -961,13 +944,10 @@ PHP_FUNCTION(ftp_put)
zend_long mode=FTPTYPE_IMAGE, startpos=0;
php_stream *instream;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rpp|ll", &z_ftp, &remote, &remote_len, &local, &local_len, &mode, &startpos) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Opp|ll", &z_ftp, php_ftp_ce, &remote, &remote_len, &local, &local_len, &mode, &startpos) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
XTYPE(xtype, mode);
if (!(instream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt" : "rb", REPORT_ERRORS, NULL))) {
@@ -1014,13 +994,10 @@ PHP_FUNCTION(ftp_append)
zend_long mode=FTPTYPE_IMAGE;
php_stream *instream;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rpp|l", &z_ftp, &remote, &remote_len, &local, &local_len, &mode) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Opp|l", &z_ftp, php_ftp_ce, &remote, &remote_len, &local, &local_len, &mode) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
XTYPE(xtype, mode);
if (!(instream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt" : "rb", REPORT_ERRORS, NULL))) {
@@ -1049,13 +1026,10 @@ PHP_FUNCTION(ftp_nb_put)
zend_long mode=FTPTYPE_IMAGE, startpos=0, ret;
php_stream *instream;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rpp|ll", &z_ftp, &remote, &remote_len, &local, &local_len, &mode, &startpos) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Opp|ll", &z_ftp, php_ftp_ce, &remote, &remote_len, &local, &local_len, &mode, &startpos) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
XTYPE(xtype, mode);
if (!(instream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt" : "rb", REPORT_ERRORS, NULL))) {
@@ -1107,13 +1081,10 @@ PHP_FUNCTION(ftp_size)
char *file;
size_t file_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rp", &z_ftp, &file, &file_len) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Op", &z_ftp, php_ftp_ce, &file, &file_len) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
/* get file size */
RETURN_LONG(ftp_size(ftp, file, file_len));
@@ -1128,13 +1099,10 @@ PHP_FUNCTION(ftp_mdtm)
char *file;
size_t file_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rp", &z_ftp, &file, &file_len) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Op", &z_ftp, php_ftp_ce, &file, &file_len) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
/* get file mod time */
RETURN_LONG(ftp_mdtm(ftp, file, file_len));
@@ -1149,13 +1117,10 @@ PHP_FUNCTION(ftp_rename)
char *src, *dest;
size_t src_len, dest_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rss", &z_ftp, &src, &src_len, &dest, &dest_len) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oss", &z_ftp, php_ftp_ce, &src, &src_len, &dest, &dest_len) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
/* rename the file */
if (!ftp_rename(ftp, src, src_len, dest, dest_len)) {
@@ -1175,13 +1140,10 @@ PHP_FUNCTION(ftp_delete)
char *file;
size_t file_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &z_ftp, &file, &file_len) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &z_ftp, php_ftp_ce, &file, &file_len) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
/* delete the file */
if (!ftp_delete(ftp, file, file_len)) {
@@ -1201,13 +1163,10 @@ PHP_FUNCTION(ftp_site)
char *cmd;
size_t cmd_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &z_ftp, &cmd, &cmd_len) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &z_ftp, php_ftp_ce, &cmd, &cmd_len) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
/* send the site command */
if (!ftp_site(ftp, cmd, cmd_len)) {
@@ -1223,18 +1182,19 @@ PHP_FUNCTION(ftp_site)
PHP_FUNCTION(ftp_close)
{
zval *z_ftp;
- ftpbuf_t *ftp;
+ php_ftp_object *obj;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &z_ftp) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &z_ftp, php_ftp_ce) == FAILURE) {
RETURN_THROWS();
}
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
- RETURN_THROWS();
+ obj = ftp_object_from_zend_object(Z_OBJ_P(z_ftp));
+ if (obj->ftp) {
+ ftp_quit(obj->ftp);
+ ftp_close(obj->ftp);
+ obj->ftp = NULL;
}
- ftp_quit(ftp);
-
RETURN_TRUE;
}
/* }}} */
@@ -1246,13 +1206,10 @@ PHP_FUNCTION(ftp_set_option)
zend_long option;
ftpbuf_t *ftp;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlz", &z_ftp, &option, &z_value) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Olz", &z_ftp, php_ftp_ce, &option, &z_value) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
switch (option) {
case PHP_FTP_OPT_TIMEOUT_SEC:
@@ -1298,13 +1255,10 @@ PHP_FUNCTION(ftp_get_option)
zend_long option;
ftpbuf_t *ftp;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &z_ftp, &option) == FAILURE) {
- RETURN_THROWS();
- }
-
- if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &z_ftp, php_ftp_ce, &option) == FAILURE) {
RETURN_THROWS();
}
+ GET_FTPBUF(ftp, z_ftp);
switch (option) {
case PHP_FTP_OPT_TIMEOUT_SEC:
diff --git a/ext/ftp/tests/007.phpt b/ext/ftp/tests/007.phpt
index 0520b37293..1ae879f901 100644
--- a/ext/ftp/tests/007.phpt
+++ b/ext/ftp/tests/007.phpt
@@ -180,36 +180,36 @@ try {
fclose($ftp);
?>
--EXPECT--
-ftp_login(): supplied resource is not a valid FTP Buffer resource
-ftp_pwd(): supplied resource is not a valid FTP Buffer resource
-ftp_cdup(): supplied resource is not a valid FTP Buffer resource
-ftp_chdir(): supplied resource is not a valid FTP Buffer resource
-ftp_exec(): supplied resource is not a valid FTP Buffer resource
-ftp_raw(): supplied resource is not a valid FTP Buffer resource
-ftp_mkdir(): supplied resource is not a valid FTP Buffer resource
-ftp_rmdir(): supplied resource is not a valid FTP Buffer resource
-ftp_chmod(): supplied resource is not a valid FTP Buffer resource
-ftp_alloc(): supplied resource is not a valid FTP Buffer resource
-ftp_nlist(): supplied resource is not a valid FTP Buffer resource
-ftp_rawlist(): supplied resource is not a valid FTP Buffer resource
-ftp_mlsd(): supplied resource is not a valid FTP Buffer resource
-ftp_systype(): supplied resource is not a valid FTP Buffer resource
-ftp_fget(): supplied resource is not a valid FTP Buffer resource
-ftp_nb_fget(): supplied resource is not a valid FTP Buffer resource
-ftp_pasv(): supplied resource is not a valid FTP Buffer resource
-ftp_get(): supplied resource is not a valid FTP Buffer resource
-ftp_nb_get(): supplied resource is not a valid FTP Buffer resource
-ftp_nb_continue(): supplied resource is not a valid FTP Buffer resource
-ftp_fput(): supplied resource is not a valid FTP Buffer resource
-ftp_nb_fput(): supplied resource is not a valid FTP Buffer resource
-ftp_put(): supplied resource is not a valid FTP Buffer resource
-ftp_append(): supplied resource is not a valid FTP Buffer resource
-ftp_nb_put(): supplied resource is not a valid FTP Buffer resource
-ftp_size(): supplied resource is not a valid FTP Buffer resource
-ftp_mdtm(): supplied resource is not a valid FTP Buffer resource
-ftp_rename(): supplied resource is not a valid FTP Buffer resource
-ftp_delete(): supplied resource is not a valid FTP Buffer resource
-ftp_site(): supplied resource is not a valid FTP Buffer resource
-ftp_close(): supplied resource is not a valid FTP Buffer resource
-ftp_set_option(): supplied resource is not a valid FTP Buffer resource
-ftp_get_option(): supplied resource is not a valid FTP Buffer resource
+ftp_login(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_pwd(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_cdup(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_chdir(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_exec(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_raw(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_mkdir(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_rmdir(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_chmod(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_alloc(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_nlist(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_rawlist(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_mlsd(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_systype(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_fget(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_nb_fget(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_pasv(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_get(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_nb_get(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_nb_continue(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_fput(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_nb_fput(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_put(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_append(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_nb_put(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_size(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_mdtm(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_rename(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_delete(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_site(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_close(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_set_option(): Argument #1 ($ftp) must be of type FTPConnection, resource given
+ftp_get_option(): Argument #1 ($ftp) must be of type FTPConnection, resource given
diff --git a/ext/ftp/tests/CONFLICTS b/ext/ftp/tests/CONFLICTS
deleted file mode 100644
index 254defddb5..0000000000
--- a/ext/ftp/tests/CONFLICTS
+++ /dev/null
@@ -1 +0,0 @@
-server
diff --git a/ext/ftp/tests/dead-resource.phpt b/ext/ftp/tests/dead-resource.phpt
new file mode 100644
index 0000000000..75a9931d54
--- /dev/null
+++ b/ext/ftp/tests/dead-resource.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Attempt to use a closed FTPConnection
+--SKIPIF--
+<?php
+require 'skipif.inc';
+--FILE--
+<?php
+require 'server.inc';
+
+$ftp = ftp_connect('127.0.0.1', $port);
+if (!$ftp) die("Couldn't connect to the server");
+var_dump(ftp_login($ftp, 'user', 'pass'));
+var_dump(ftp_close($ftp));
+
+try {
+ var_dump(ftp_login($ftp, 'user', 'pass'));
+ echo "Login did not throw\n";
+} catch (ValueError $ex) {
+ echo "Exception: ", $ex->getMessage(), "\n";
+}
+--EXPECT--
+bool(true)
+bool(true)
+Exception: FTPConnection is already closed
diff --git a/ext/ftp/tests/ftp_set_option_errors.phpt b/ext/ftp/tests/ftp_set_option_errors.phpt
index 3f5476f6c3..5e5ef328f3 100644
--- a/ext/ftp/tests/ftp_set_option_errors.phpt
+++ b/ext/ftp/tests/ftp_set_option_errors.phpt
@@ -13,40 +13,22 @@ $ftp = ftp_connect('127.0.0.1', $port);
ftp_login($ftp, 'user', 'pass');
$ftp or die("Couldn't connect to the server");
-try {
- ftp_set_option($ftp, FTP_TIMEOUT_SEC, 0);
-} catch (ValueError $exception) {
- echo $exception->getMessage() . "\n";
+$options = [
+ [ 'option' => FTP_TIMEOUT_SEC, 'value' => 0 ],
+ [ 'option' => FTP_TIMEOUT_SEC, 'value' => '0' ],
+ [ 'option' => FTP_USEPASVADDRESS, 'value' => ['1'] ],
+ [ 'option' => FTP_AUTOSEEK, 'value' => 'true' ],
+ [ 'option' => FOO_BAR, 'value' => 1 ],
+];
+foreach ($options as $option) try {
+ var_dump(ftp_set_option($ftp, $option['option'], $option['value']));
+} catch (\Throwable $ex) {
+ echo "Exception: ", $ex->getMessage(), "\n";
}
-try {
- ftp_set_option($ftp, FTP_TIMEOUT_SEC, '0');
-} catch (TypeError $exception) {
- echo $exception->getMessage() . "\n";
-}
-
-try {
- ftp_set_option($ftp, FTP_USEPASVADDRESS, ['1']);
-} catch (TypeError $exception) {
- echo $exception->getMessage() . "\n";
-}
-
-try {
- ftp_set_option($ftp, FTP_AUTOSEEK, 'true');
-} catch (TypeError $exception) {
- echo $exception->getMessage() . "\n";
-}
-
-try {
- ftp_set_option($ftp, FOO_BAR, 1);
-} catch (ValueError $exception) {
- echo $exception->getMessage() . "\n";
-}
-
-?>
--EXPECT--
-ftp_set_option(): Argument #3 ($value) must be greater than 0 for the FTP_TIMEOUT_SEC option
-ftp_set_option(): Argument #3 ($value) must be of type int for the FTP_TIMEOUT_SEC option, string given
-ftp_set_option(): Argument #3 ($value) must be of type bool for the FTP_USEPASVADDRESS option, array given
-ftp_set_option(): Argument #3 ($value) must be of type bool for the FTP_AUTOSEEK option, string given
-ftp_set_option(): Argument #2 ($option) must be one of FTP_TIMEOUT_SEC, FTP_AUTOSEEK, or FTP_USEPASVADDRESS
+Exception: ftp_set_option(): Argument #3 ($value) must be greater than 0 for the FTP_TIMEOUT_SEC option
+Exception: ftp_set_option(): Argument #3 ($value) must be of type int for the FTP_TIMEOUT_SEC option, string given
+Exception: ftp_set_option(): Argument #3 ($value) must be of type bool for the FTP_USEPASVADDRESS option, array given
+Exception: ftp_set_option(): Argument #3 ($value) must be of type bool for the FTP_AUTOSEEK option, string given
+Exception: ftp_set_option(): Argument #2 ($option) must be one of FTP_TIMEOUT_SEC, FTP_AUTOSEEK, or FTP_USEPASVADDRESS
diff --git a/ext/ftp/tests/server.inc b/ext/ftp/tests/server.inc
index 38599391d6..8bc836fc40 100644
--- a/ext/ftp/tests/server.inc
+++ b/ext/ftp/tests/server.inc
@@ -4,59 +4,21 @@ $socket = null;
$errno = 0;
$context = stream_context_create(array('ssl' => array('local_cert' => dirname(__FILE__).'/cert.pem')));
-for ($i=0; $i<10 && !$socket; ++$i) {
- $port = rand(50000, 65535);
-
- $socket = @stream_socket_server("tcp://127.0.0.1:$port", $errno, $errstr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $context);
-}
-//set anther random port that is not the same as $port
-do{
- $pasv_port = rand(50000, 65535);
-}while($pasv_port == $port);
-
+$socket = stream_socket_server("tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $context);
if (!$socket) {
echo "$errstr ($errno)\n";
die("could not start/bind the ftp server\n");
}
-$pid = pcntl_fork();
+$socket_name = stream_socket_get_name($socket, false);
+$port = (int) substr($socket_name, strrpos($socket_name, ':') + 1);
-function pasv_listen($action){
- global $pasv_port, $tmp_file;
- $tmp_file = 'nm2.php';
- $pid = pcntl_fork();
- if($pid === 0){
- $soc = stream_socket_server("tcp://127.0.0.1:$pasv_port");
- $fs = stream_socket_accept($soc, 3);
- switch ($action) {
- case 'fget':
- case 'get':
- //listen for 3 seconds 3 seconds
- fputs($fs, "I am passive.\r\n");
- break;
- case 'put':
- file_put_contents($tmp_file, stream_get_contents($fs));
- break;
- case 'list':
- fputs($fs, "drwxr-x--- 3 owner group 4096 Jul 12 12:16 .\r\n");
- fputs($fs, "drwxr-x--- 3 owner group 4096 Jul 12 12:16 ..\r\n");
- fputs($fs, "drwxr-x--- 3 owner group 4096 Jul 12 12:16 public_ftp\r\n");
- break;
- case 'list_null':
- fputs($fs, "\r\n");
- break;
- }
- fclose($fs);
- exit;
- }
-}
+$pid = pcntl_fork();
if ($pid) {
-
function dump_and_exit($buf)
{
var_dump($buf);
- fclose($GLOBALS['s']);
exit;
}
@@ -90,10 +52,14 @@ if ($pid) {
if (!$s) die("Error accepting a new connection\n");
+ register_shutdown_function(function() use($pid, $s) {
+ fclose($s);
+ pcntl_waitpid($pid, $status);
+ });
+
fputs($s, "220----- PHP FTP server 0.3 -----\r\n220 Service ready\r\n");
$buf = fread($s, 2048);
-
function user_auth($buf) {
global $user, $s, $ssl, $bug37799;
@@ -143,7 +109,6 @@ if ($pid) {
$user = $m[1];
if ($user !== 'user' && $user !== 'anonymous') {
fputs($s, "530 Not logged in.\r\n");
- fclose($s);
exit;
}
@@ -163,7 +128,6 @@ if ($pid) {
fputs($s, "230 User logged in\r\n");
} else {
fputs($s, "530 Not logged in.\r\n");
- fclose($s);
exit;
}
}
@@ -432,25 +396,20 @@ if ($pid) {
$i=0;
if (empty($bug73457)) {
- do {
- if (!empty($ssl)) {
- $soc = @stream_socket_server("tcp://127.0.0.1:$pasv_port", $errno, $errstr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $context);
- } else {
- $soc = @stream_socket_server("tcp://127.0.0.1:$pasv_port");
- }
- /* Could bind port, Try another port */
- if (!$soc) {
- $pasv_port = rand(50000, 65535);
- }
- $i++;
- } while ($i<10 && !$soc);
-
+ if (!empty($ssl)) {
+ $soc = stream_socket_server("tcp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $context);
+ } else {
+ $soc = stream_socket_server("tcp://127.0.0.1:0");
+ }
if (!$soc) {
echo "$errstr ($errno)\n";
die("could not bind passive port\n");
}
+
+ $soc_name = stream_socket_get_name($soc, false);
+ $pasv_port = (int) substr($soc_name, strrpos($soc_name, ':') + 1);
} else {
- $pasv_port=1234;
+ $pasv_port = 1234;
}
$p2 = $pasv_port % ((int) 1 << 8);
@@ -548,7 +507,6 @@ if ($pid) {
dump_and_exit($buf);
}
}
- fclose($s);
exit;
}
diff --git a/ext/gd/gd.c b/ext/gd/gd.c
index 88d04824ea..d811b66866 100644
--- a/ext/gd/gd.c
+++ b/ext/gd/gd.c
@@ -57,8 +57,6 @@
#include "gd_compat.h"
-static int le_gd_font;
-
#include <gd.h>
#include <gd_errors.h>
#include <gdfontt.h> /* 1 Tiny font */
@@ -235,6 +233,75 @@ static void php_gd_object_minit_helper()
php_gd_image_object_handlers.offset = XtOffsetOf(php_gd_image_object, std);
}
+static zend_class_entry *gd_font_ce = NULL;
+static zend_object_handlers php_gd_font_object_handlers;
+
+typedef struct _php_gd_font_object {
+ gdFontPtr font;
+ zend_object std;
+} php_gd_font_object;
+
+static php_gd_font_object *php_gd_font_object_from_zend_object(zend_object *zobj)
+{
+ return ((php_gd_font_object*)(zobj + 1)) - 1;
+}
+
+static zend_object *php_gd_font_object_to_zend_object(php_gd_font_object *obj)
+{
+ return ((zend_object*)(obj + 1)) - 1;
+}
+
+static zend_object *php_gd_font_object_create(zend_class_entry *ce)
+{
+ php_gd_font_object *obj = zend_object_alloc(sizeof(php_gd_font_object), ce);
+ zend_object *zobj = php_gd_font_object_to_zend_object(obj);
+
+ obj->font = NULL;
+ zend_object_std_init(zobj, ce);
+ object_properties_init(zobj, ce);
+ zobj->handlers = &php_gd_font_object_handlers;
+
+ return zobj;
+}
+
+static void php_gd_font_object_free(zend_object *zobj)
+{
+ php_gd_font_object *obj = php_gd_font_object_from_zend_object(zobj);
+
+ if (obj->font) {
+ if (obj->font->data) {
+ efree(obj->font->data);
+ }
+ efree(obj->font);
+ obj->font = NULL;
+ }
+
+ zend_object_std_dtor(zobj);
+}
+
+static zend_function *php_gd_font_object_get_constructor(zend_object *object)
+{
+ zend_throw_error(NULL, "You cannot initialize a GdFont object except through helper functions");
+ return NULL;
+}
+
+static void php_gd_font_minit_helper()
+{
+ zend_class_entry ce;
+ INIT_CLASS_ENTRY(ce, "GdFont", class_GdFont_methods);
+ gd_font_ce = zend_register_internal_class(&ce);
+ gd_font_ce->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NO_DYNAMIC_PROPERTIES;
+ gd_font_ce->create_object = php_gd_font_object_create;
+ gd_font_ce->serialize = zend_class_serialize_deny;
+ gd_font_ce->unserialize = zend_class_unserialize_deny;
+
+ /* setting up the object handlers for the GdFont class */
+ memcpy(&php_gd_font_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
+ php_gd_font_object_handlers.clone_obj = NULL;
+ php_gd_font_object_handlers.free_obj = php_gd_font_object_free;
+ php_gd_font_object_handlers.get_constructor = php_gd_font_object_get_constructor;
+ php_gd_font_object_handlers.offset = XtOffsetOf(php_gd_font_object, std);
+}
/*********************************************************
*
@@ -265,19 +332,6 @@ PHP_INI_BEGIN()
PHP_INI_END()
/* }}} */
-/* {{{ php_free_gd_font */
-static void php_free_gd_font(zend_resource *rsrc)
-{
- gdFontPtr fp = (gdFontPtr) rsrc->ptr;
-
- if (fp->data) {
- efree(fp->data);
- }
-
- efree(fp);
-}
-/* }}} */
-
/* {{{ php_gd_error_method */
void php_gd_error_method(int type, const char *format, va_list args)
{
@@ -302,8 +356,8 @@ void php_gd_error_method(int type, const char *format, va_list args)
/* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(gd)
{
- le_gd_font = zend_register_list_destructors_ex(php_free_gd_font, NULL, "gd font", module_number);
php_gd_object_minit_helper();
+ php_gd_font_minit_helper();
#if defined(HAVE_GD_FREETYPE) && defined(HAVE_GD_BUNDLED)
gdFontCacheMutexSetup();
@@ -614,7 +668,6 @@ PHP_FUNCTION(gd_info)
/* {{{ Load a new font */
PHP_FUNCTION(imageloadfont)
{
- zval *ind;
zend_string *file;
int hdr_size = sizeof(gdFont) - sizeof(char *);
int body_size, n = 0, b, i, body_size_check;
@@ -625,7 +678,7 @@ PHP_FUNCTION(imageloadfont)
RETURN_THROWS();
}
- stream = php_stream_open_wrapper(ZSTR_VAL(file), "rb", IGNORE_PATH | IGNORE_URL_WIN | REPORT_ERRORS, NULL);
+ stream = php_stream_open_wrapper(ZSTR_VAL(file), "rb", IGNORE_PATH | REPORT_ERRORS, NULL);
if (stream == NULL) {
RETURN_FALSE;
}
@@ -704,13 +757,8 @@ PHP_FUNCTION(imageloadfont)
}
php_stream_close(stream);
- ind = zend_list_insert(font, le_gd_font);
-
- /* Adding 5 to the font index so we will never have font indices
- * that overlap with the old fonts (with indices 1-5). The first
- * list index given out is always 1.
- */
- RETURN_LONG(Z_RES_HANDLE_P(ind) + 5);
+ object_init_ex(return_value, gd_font_ce);
+ php_gd_font_object_from_zend_object(Z_OBJ_P(return_value))->font = font;
}
/* }}} */
@@ -1584,7 +1632,7 @@ static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type,
}
- stream = php_stream_open_wrapper(file, "rb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL);
+ stream = php_stream_open_wrapper(file, "rb", REPORT_ERRORS|IGNORE_PATH, NULL);
if (stream == NULL) {
RETURN_FALSE;
}
@@ -1883,7 +1931,7 @@ PHP_FUNCTION(imagexbm)
im = php_gd_libgdimageptr_from_zval_p(imgind);
if (file != NULL) {
- stream = php_stream_open_wrapper(file, "wb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL);
+ stream = php_stream_open_wrapper(file, "wb", REPORT_ERRORS|IGNORE_PATH, NULL);
if (stream == NULL) {
RETURN_FALSE;
}
@@ -2695,42 +2743,21 @@ PHP_FUNCTION(imagefilledpolygon)
/* }}} */
/* {{{ php_find_gd_font */
-static gdFontPtr php_find_gd_font(int size)
+static gdFontPtr php_find_gd_font(zend_object *font_obj, zend_long font_int)
{
- gdFontPtr font;
+ if (font_obj) {
+ return php_gd_font_object_from_zend_object(font_obj)->font;
+ }
- switch (size) {
- case 1:
- font = gdFontTiny;
- break;
- case 2:
- font = gdFontSmall;
- break;
- case 3:
- font = gdFontMediumBold;
- break;
- case 4:
- font = gdFontLarge;
- break;
- case 5:
- font = gdFontGiant;
- break;
- default: {
- zval *zv = zend_hash_index_find(&EG(regular_list), size - 5);
- if (!zv || (Z_RES_P(zv))->type != le_gd_font) {
- if (size < 1) {
- font = gdFontTiny;
- } else {
- font = gdFontGiant;
- }
- } else {
- font = (gdFontPtr)Z_RES_P(zv)->ptr;
- }
- }
- break;
- }
-
- return font;
+ switch (font_int) {
+ case 1: return gdFontTiny;
+ case 2: return gdFontSmall;
+ case 3: return gdFontMediumBold;
+ case 4: return gdFontLarge;
+ case 5: return gdFontGiant;
+ }
+
+ return font_int < 1 ? gdFontTiny : gdFontGiant;
}
/* }}} */
@@ -2740,14 +2767,15 @@ static gdFontPtr php_find_gd_font(int size)
*/
static void php_imagefontsize(INTERNAL_FUNCTION_PARAMETERS, int arg)
{
- zend_long SIZE;
+ zend_object *font_obj;
+ zend_long font_int;
gdFontPtr font;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &SIZE) == FAILURE) {
- RETURN_THROWS();
- }
+ ZEND_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_OBJ_OF_CLASS_OR_LONG(font_obj, gd_font_ce, font_int)
+ ZEND_PARSE_PARAMETERS_END();
- font = php_find_gd_font(SIZE);
+ font = php_find_gd_font(font_obj, font_int);
RETURN_LONG(arg ? font->h : font->w);
}
/* }}} */
@@ -2801,17 +2829,24 @@ static void php_gdimagecharup(gdImagePtr im, gdFontPtr f, int x, int y, int c, i
static void php_imagechar(INTERNAL_FUNCTION_PARAMETERS, int mode)
{
zval *IM;
- zend_long SIZE, X, Y, COL;
+ zend_long X, Y, COL;
char *C;
size_t C_len;
gdImagePtr im;
- int ch = 0, col, x, y, size, i, l = 0;
+ int ch = 0, col, x, y, i, l = 0;
unsigned char *str = NULL;
+ zend_object *font_obj;
+ zend_long font_int;
gdFontPtr font;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "Olllsl", &IM, gd_image_ce, &SIZE, &X, &Y, &C, &C_len, &COL) == FAILURE) {
- RETURN_THROWS();
- }
+ ZEND_PARSE_PARAMETERS_START(6, 6)
+ Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
+ Z_PARAM_OBJ_OF_CLASS_OR_LONG(font_obj, gd_font_ce, font_int)
+ Z_PARAM_LONG(X)
+ Z_PARAM_LONG(Y)
+ Z_PARAM_STRING(C, C_len)
+ Z_PARAM_LONG(COL)
+ ZEND_PARSE_PARAMETERS_END();
im = php_gd_libgdimageptr_from_zval_p(IM);
@@ -2826,9 +2861,8 @@ static void php_imagechar(INTERNAL_FUNCTION_PARAMETERS, int mode)
y = Y;
x = X;
- size = SIZE;
- font = php_find_gd_font(size);
+ font = php_find_gd_font(font_obj, font_int);
switch (mode) {
case 0:
@@ -4092,7 +4126,7 @@ static gdIOCtx *create_stream_context_from_zval(zval *to_zval) {
return NULL;
}
- stream = php_stream_open_wrapper(Z_STRVAL_P(to_zval), "wb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL);
+ stream = php_stream_open_wrapper(Z_STRVAL_P(to_zval), "wb", REPORT_ERRORS|IGNORE_PATH, NULL);
if (stream == NULL) {
return NULL;
}
diff --git a/ext/gd/gd.stub.php b/ext/gd/gd.stub.php
index fe0d5658ee..0ef410fc1e 100644
--- a/ext/gd/gd.stub.php
+++ b/ext/gd/gd.stub.php
@@ -2,13 +2,12 @@
/** @generate-function-entries */
-final class GdImage
-{
-}
+final class GdImage {}
+final class GdFont {}
function gd_info(): array {}
-function imageloadfont(string $filename): int|false {}
+function imageloadfont(string $filename): GdFont|false {}
function imagesetstyle(GdImage $image, array $style): bool {}
@@ -187,17 +186,17 @@ function imageopenpolygon(GdImage $image, array $points, int $num_points_or_colo
function imagefilledpolygon(GdImage $image, array $points, int $num_points_or_color, ?int $color = null): bool {}
-function imagefontwidth(int $font): int {}
+function imagefontwidth(GdFont|int $font): int {}
-function imagefontheight(int $font): int {}
+function imagefontheight(GdFont|int $font): int {}
-function imagechar(GdImage $image, int $font, int $x, int $y, string $char, int $color): bool {}
+function imagechar(GdImage $image, GdFont|int $font, int $x, int $y, string $char, int $color): bool {}
-function imagecharup(GdImage $image, int $font, int $x, int $y, string $char, int $color): bool {}
+function imagecharup(GdImage $image, GdFont|int $font, int $x, int $y, string $char, int $color): bool {}
-function imagestring(GdImage $image, int $font, int $x, int $y, string $string, int $color): bool {}
+function imagestring(GdImage $image, GdFont|int $font, int $x, int $y, string $string, int $color): bool {}
-function imagestringup(GdImage $image, int $font, int $x, int $y, string $string, int $color): bool {}
+function imagestringup(GdImage $image, GdFont|int $font, int $x, int $y, string $string, int $color): bool {}
function imagecopy(GdImage $dst_image, GdImage $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $src_width, int $src_height): bool {}
diff --git a/ext/gd/gd_arginfo.h b/ext/gd/gd_arginfo.h
index 4d59767b4e..ea61b08374 100644
--- a/ext/gd/gd_arginfo.h
+++ b/ext/gd/gd_arginfo.h
@@ -1,10 +1,10 @@
/* This is a generated file, edit the .stub.php file instead.
- * Stub hash: 59256d0de105f1a2f5d5fc1e20f8090031b42a76 */
+ * Stub hash: 23b7c8395c628239fb10d746ca6bba72871ee9f3 */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gd_info, 0, 0, IS_ARRAY, 0)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_imageloadfont, 0, 1, MAY_BE_LONG|MAY_BE_FALSE)
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_imageloadfont, 0, 1, GdFont, MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0)
ZEND_END_ARG_INFO()
@@ -380,14 +380,14 @@ ZEND_END_ARG_INFO()
#define arginfo_imagefilledpolygon arginfo_imagepolygon
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagefontwidth, 0, 1, IS_LONG, 0)
- ZEND_ARG_TYPE_INFO(0, font, IS_LONG, 0)
+ ZEND_ARG_OBJ_TYPE_MASK(0, font, GdFont, MAY_BE_LONG, NULL)
ZEND_END_ARG_INFO()
#define arginfo_imagefontheight arginfo_imagefontwidth
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagechar, 0, 6, _IS_BOOL, 0)
ZEND_ARG_OBJ_INFO(0, image, GdImage, 0)
- ZEND_ARG_TYPE_INFO(0, font, IS_LONG, 0)
+ ZEND_ARG_OBJ_TYPE_MASK(0, font, GdFont, MAY_BE_LONG, NULL)
ZEND_ARG_TYPE_INFO(0, x, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, y, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, char, IS_STRING, 0)
@@ -398,7 +398,7 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagestring, 0, 6, _IS_BOOL, 0)
ZEND_ARG_OBJ_INFO(0, image, GdImage, 0)
- ZEND_ARG_TYPE_INFO(0, font, IS_LONG, 0)
+ ZEND_ARG_OBJ_TYPE_MASK(0, font, GdFont, MAY_BE_LONG, NULL)
ZEND_ARG_TYPE_INFO(0, x, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, y, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, string, IS_STRING, 0)
@@ -831,3 +831,8 @@ static const zend_function_entry ext_functions[] = {
static const zend_function_entry class_GdImage_methods[] = {
ZEND_FE_END
};
+
+
+static const zend_function_entry class_GdFont_methods[] = {
+ ZEND_FE_END
+};
diff --git a/ext/hash/bench.php b/ext/hash/bench.php
index 436390f7d5..846163315b 100755
--- a/ext/hash/bench.php
+++ b/ext/hash/bench.php
@@ -1,81 +1,12 @@
#!/usr/bin/env php
<?php
-/*
- This gives rather interesting results :)
+error_reporting(E_ALL);
- Measures on a Notebook P4M-1.7 256MB Windows 2000:
- sha1 0.556691
- tiger160,3 0.774469
- tiger192,3 0.776314
- tiger128,3 0.777004
- ripemd128 0.896674
- sha256 1.011164
- md5 1.016032
- tiger160,4 1.056617
- tiger128,4 1.063101
- tiger192,4 1.069258
- haval160,3 1.125099
- haval128,3 1.125679
- haval224,3 1.128017
- haval192,3 1.130026
- haval256,3 1.134846
- ripemd160 1.150693
- haval128,4 1.686261
- haval192,4 1.687274
- haval160,4 1.693091
- haval256,4 1.699323
- haval224,4 1.743094
- haval160,5 2.003452
- haval192,5 2.008341
- haval256,5 2.009048
- haval128,5 2.009555
- haval224,5 2.015539
- sha384 3.370734
- sha512 3.381121
- whirlpool 6.912327
- snefru 9.268168
-
- Measures on a Desktop P4-2.4 512MB Debian (Linux-2.4):
- md5 0.147739
- haval128,3 0.317006
- haval192,3 0.317524
- haval256,3 0.317526
- haval160,3 0.323035
- haval224,3 0.333318
- ripemd128 0.353447
- sha1 0.376200
- ripemd160 0.413758
- sha256 0.435957
- haval160,4 0.452357
- haval224,4 0.454531
- haval128,4 0.458026
- haval256,4 0.459051
- haval192,4 0.468094
- haval128,5 0.524262
- haval160,5 0.529573
- haval224,5 0.533655
- haval256,5 0.534446
- haval192,5 0.543726
- tiger128,3 0.577975
- tiger160,3 0.579951
- tiger192,3 0.597111
- tiger192,4 0.781408
- tiger160,4 0.801243
- tiger128,4 0.812239
- sha512 1.298627
- sha384 1.313607
- whirlpool 1.556159
- snefru 5.703742
-
-*/
-
-error_reporting(E_ALL&~E_NOTICE);
-
-$data = file_get_contents(__FILE__);
+$data = str_repeat("\x00", (int) ($argv[1] ?? (2 * 1024)));
$time = array();
foreach (hash_algos() as $algo) {
- $time[$algo] = 0;
+ $time[$algo] = 0;
}
for ($j = 0; $j < 10; $j++) {
@@ -92,4 +23,3 @@ asort($time, SORT_NUMERIC);
foreach ($time as $a => $t) {
printf("%-12s %02.6f\n", $a, $t);
}
-?>
diff --git a/ext/imap/php_imap.c b/ext/imap/php_imap.c
index c561a5e72c..4c72c90ff6 100644
--- a/ext/imap/php_imap.c
+++ b/ext/imap/php_imap.c
@@ -2758,7 +2758,7 @@ PHP_FUNCTION(imap_sort)
}
array_init(return_value);
- if (slst != NIL && slst != 0) {
+ if (slst != NULL) {
for (sl = slst; *sl; sl++) {
add_next_index_long(return_value, *sl);
}
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_7bit.c b/ext/mbstring/libmbfl/filters/mbfilter_7bit.c
index 42ed23326d..331dc8e743 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_7bit.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_7bit.c
@@ -31,6 +31,8 @@
#include "mbfilter.h"
#include "mbfilter_7bit.h"
+static int mbfl_filt_ident_7bit(int c, mbfl_identify_filter *filter);
+
const mbfl_encoding mbfl_encoding_7bit = {
mbfl_no_encoding_7bit,
"7bit",
@@ -42,6 +44,12 @@ const mbfl_encoding mbfl_encoding_7bit = {
NULL
};
+const struct mbfl_identify_vtbl vtbl_identify_7bit = {
+ mbfl_no_encoding_7bit,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_7bit
+};
+
const struct mbfl_convert_vtbl vtbl_8bit_7bit = {
mbfl_no_encoding_8bit,
mbfl_no_encoding_7bit,
@@ -75,6 +83,16 @@ int mbfl_filt_conv_any_7bit(int c, mbfl_convert_filter *filter)
{
if (c >= 0 && c < 0x80) {
CK((*filter->output_function)(c, filter->data));
+ } else {
+ mbfl_filt_conv_illegal_output(c, filter);
+ }
+ return c;
+}
+
+static int mbfl_filt_ident_7bit(int c, mbfl_identify_filter *filter)
+{
+ if (c >= 0x80) {
+ filter->flag = 1;
}
return c;
}
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_7bit.h b/ext/mbstring/libmbfl/filters/mbfilter_7bit.h
index d0dfe2c518..f842a2ad3b 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_7bit.h
+++ b/ext/mbstring/libmbfl/filters/mbfilter_7bit.h
@@ -34,6 +34,7 @@
#include "mbfilter.h"
extern const mbfl_encoding mbfl_encoding_7bit;
+extern const struct mbfl_identify_vtbl vtbl_identify_7bit;
extern const struct mbfl_convert_vtbl vtbl_8bit_7bit;
extern const struct mbfl_convert_vtbl vtbl_7bit_8bit;
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_armscii8.c b/ext/mbstring/libmbfl/filters/mbfilter_armscii8.c
index 38c8f98bd1..e2fa8d86ea 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_armscii8.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_armscii8.c
@@ -38,7 +38,7 @@ const mbfl_encoding mbfl_encoding_armscii8 = {
mbfl_no_encoding_armscii8,
"ArmSCII-8",
"ArmSCII-8",
- (const char *(*)[])&mbfl_encoding_armscii8_aliases,
+ mbfl_encoding_armscii8_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_armscii8_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_ascii.c b/ext/mbstring/libmbfl/filters/mbfilter_ascii.c
index 43d659a46c..4e02c26aac 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_ascii.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_ascii.c
@@ -39,7 +39,7 @@ const mbfl_encoding mbfl_encoding_ascii = {
mbfl_no_encoding_ascii,
"ASCII",
"US-ASCII", /* preferred MIME name */
- (const char *(*)[])&mbfl_encoding_ascii_aliases,
+ mbfl_encoding_ascii_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_ascii_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_big5.c b/ext/mbstring/libmbfl/filters/mbfilter_big5.c
index 1e59924092..95c75a37e3 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_big5.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_big5.c
@@ -59,7 +59,7 @@ const mbfl_encoding mbfl_encoding_big5 = {
mbfl_no_encoding_big5,
"BIG-5",
"BIG5",
- (const char *(*)[])&mbfl_encoding_big5_aliases,
+ mbfl_encoding_big5_aliases,
mblen_table_big5,
MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE,
&vtbl_big5_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_cp1251.c b/ext/mbstring/libmbfl/filters/mbfilter_cp1251.c
index 470adf1a08..af05b5ec6d 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_cp1251.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_cp1251.c
@@ -39,7 +39,7 @@ const mbfl_encoding mbfl_encoding_cp1251 = {
mbfl_no_encoding_cp1251,
"Windows-1251",
"Windows-1251",
- (const char *(*)[])&mbfl_encoding_cp1251_aliases,
+ mbfl_encoding_cp1251_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_cp1251_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_cp1252.c b/ext/mbstring/libmbfl/filters/mbfilter_cp1252.c
index a274e4b796..1f6717d2ac 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_cp1252.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_cp1252.c
@@ -39,7 +39,7 @@ const mbfl_encoding mbfl_encoding_cp1252 = {
mbfl_no_encoding_cp1252,
"Windows-1252",
"Windows-1252",
- (const char *(*)[])&mbfl_encoding_cp1252_aliases,
+ mbfl_encoding_cp1252_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_cp1252_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_cp1254.c b/ext/mbstring/libmbfl/filters/mbfilter_cp1254.c
index 7e4bb4b148..eebd5b322a 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_cp1254.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_cp1254.c
@@ -39,7 +39,7 @@ const mbfl_encoding mbfl_encoding_cp1254 = {
mbfl_no_encoding_cp1254,
"Windows-1254",
"Windows-1254",
- (const char *(*)[])&mbfl_encoding_cp1254_aliases,
+ mbfl_encoding_cp1254_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_cp1254_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_cp5022x.c b/ext/mbstring/libmbfl/filters/mbfilter_cp5022x.c
index 3879f9eb5b..798487d342 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_cp5022x.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_cp5022x.c
@@ -59,7 +59,7 @@ const mbfl_encoding mbfl_encoding_cp50220 = {
mbfl_no_encoding_cp50220,
"CP50220",
"ISO-2022-JP",
- (const char *(*)[])NULL,
+ NULL,
NULL,
MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE,
&vtbl_cp50220_wchar,
@@ -70,7 +70,7 @@ const mbfl_encoding mbfl_encoding_cp50220raw = {
mbfl_no_encoding_cp50220raw,
"CP50220raw",
"ISO-2022-JP",
- (const char *(*)[])NULL,
+ NULL,
NULL,
MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE,
&vtbl_cp50220raw_wchar,
@@ -585,7 +585,7 @@ mbfl_filt_conv_wchar_cp50220_ctor(mbfl_convert_filter *filt)
ctx->last.opaque = ctx;
ctx->last.data = filt->data;
filt->filter_function = vtbl_tl_jisx0201_jisx0208.filter_function;
- filt->filter_flush = vtbl_tl_jisx0201_jisx0208.filter_flush;
+ filt->filter_flush = (filter_flush_t)vtbl_tl_jisx0201_jisx0208.filter_flush;
filt->output_function = (output_function_t)ctx->last.filter_function;
filt->flush_function = (flush_function_t)ctx->last.filter_flush;
filt->data = &ctx->last;
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_cp51932.c b/ext/mbstring/libmbfl/filters/mbfilter_cp51932.c
index da046c86b7..9b893bc638 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_cp51932.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_cp51932.c
@@ -68,7 +68,7 @@ const mbfl_encoding mbfl_encoding_cp51932 = {
mbfl_no_encoding_cp51932,
"CP51932",
"CP51932",
- (const char *(*)[])&mbfl_encoding_cp51932_aliases,
+ mbfl_encoding_cp51932_aliases,
mblen_table_eucjp,
MBFL_ENCTYPE_MBCS,
&vtbl_cp51932_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_cp850.c b/ext/mbstring/libmbfl/filters/mbfilter_cp850.c
index 5d6b265fc1..d9d705f70f 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_cp850.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_cp850.c
@@ -35,7 +35,7 @@ const mbfl_encoding mbfl_encoding_cp850 = {
mbfl_no_encoding_cp850,
"CP850",
"CP850",
- (const char *(*)[])&mbfl_encoding_cp850_aliases,
+ mbfl_encoding_cp850_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_cp850_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_cp866.c b/ext/mbstring/libmbfl/filters/mbfilter_cp866.c
index 504903bef0..9c548627b0 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_cp866.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_cp866.c
@@ -39,7 +39,7 @@ const mbfl_encoding mbfl_encoding_cp866 = {
mbfl_no_encoding_cp866,
"CP866",
"CP866",
- (const char *(*)[])&mbfl_encoding_cp866_aliases,
+ mbfl_encoding_cp866_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_cp866_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_cp932.c b/ext/mbstring/libmbfl/filters/mbfilter_cp932.c
index 3cbca1cb64..511d864465 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_cp932.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_cp932.c
@@ -60,7 +60,7 @@ const mbfl_encoding mbfl_encoding_cp932 = {
mbfl_no_encoding_cp932,
"CP932",
"Shift_JIS",
- (const char *(*)[])&mbfl_encoding_cp932_aliases,
+ mbfl_encoding_cp932_aliases,
mblen_table_sjis,
MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE,
&vtbl_cp932_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_cp936.c b/ext/mbstring/libmbfl/filters/mbfilter_cp936.c
index df6d77907f..d73954267f 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_cp936.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_cp936.c
@@ -59,7 +59,7 @@ const mbfl_encoding mbfl_encoding_cp936 = {
mbfl_no_encoding_cp936,
"CP936",
"CP936",
- (const char *(*)[])&mbfl_encoding_cp936_aliases,
+ mbfl_encoding_cp936_aliases,
mblen_table_cp936,
MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE,
&vtbl_cp936_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_euc_cn.c b/ext/mbstring/libmbfl/filters/mbfilter_euc_cn.c
index 53a8aac2a6..0a7edaa927 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_euc_cn.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_euc_cn.c
@@ -59,7 +59,7 @@ const mbfl_encoding mbfl_encoding_euc_cn = {
mbfl_no_encoding_euc_cn,
"EUC-CN",
"CN-GB",
- (const char *(*)[])&mbfl_encoding_euc_cn_aliases,
+ mbfl_encoding_euc_cn_aliases,
mblen_table_euccn,
MBFL_ENCTYPE_MBCS,
&vtbl_euccn_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_euc_jp.c b/ext/mbstring/libmbfl/filters/mbfilter_euc_jp.c
index 252a10a58d..61da27f043 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_euc_jp.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_euc_jp.c
@@ -60,7 +60,7 @@ const mbfl_encoding mbfl_encoding_euc_jp = {
mbfl_no_encoding_euc_jp,
"EUC-JP",
"EUC-JP",
- (const char *(*)[])&mbfl_encoding_euc_jp_aliases,
+ mbfl_encoding_euc_jp_aliases,
mblen_table_eucjp,
MBFL_ENCTYPE_MBCS,
&vtbl_eucjp_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_euc_jp_2004.c b/ext/mbstring/libmbfl/filters/mbfilter_euc_jp_2004.c
index 30d869cea5..c6c708b337 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_euc_jp_2004.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_euc_jp_2004.c
@@ -40,7 +40,7 @@ const mbfl_encoding mbfl_encoding_eucjp2004 = {
mbfl_no_encoding_eucjp2004,
"EUC-JP-2004",
"EUC-JP",
- (const char *(*)[])&mbfl_encoding_eucjp2004_aliases,
+ mbfl_encoding_eucjp2004_aliases,
mblen_table_eucjp,
MBFL_ENCTYPE_MBCS,
&vtbl_eucjp2004_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_euc_jp_win.c b/ext/mbstring/libmbfl/filters/mbfilter_euc_jp_win.c
index 5798bff0fc..7c1aebdea5 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_euc_jp_win.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_euc_jp_win.c
@@ -69,7 +69,7 @@ const mbfl_encoding mbfl_encoding_eucjp_win = {
mbfl_no_encoding_eucjp_win,
"eucJP-win",
"EUC-JP",
- (const char *(*)[])&mbfl_encoding_eucjp_win_aliases,
+ mbfl_encoding_eucjp_win_aliases,
mblen_table_eucjp,
MBFL_ENCTYPE_MBCS,
&vtbl_eucjpwin_wchar,
@@ -319,8 +319,6 @@ mbfl_filt_conv_wchar_eucjpwin(int c, mbfl_convert_filter *filter)
s1 = 0x2172;
} else if (c == 0xffe2) { /* FULLWIDTH NOT SIGN */
s1 = 0x224c;
- } else if (c == 0xff5e) { /* FULLWIDTH TILDE */
- s1 = 0x2141;
} else {
s1 = -1;
c1 = 0;
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_euc_kr.c b/ext/mbstring/libmbfl/filters/mbfilter_euc_kr.c
index e9b08e08c1..0c44a99860 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_euc_kr.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_euc_kr.c
@@ -58,7 +58,7 @@ const mbfl_encoding mbfl_encoding_euc_kr = {
mbfl_no_encoding_euc_kr,
"EUC-KR",
"EUC-KR",
- (const char *(*)[])&mbfl_encoding_euc_kr_aliases,
+ mbfl_encoding_euc_kr_aliases,
mblen_table_euckr,
MBFL_ENCTYPE_MBCS,
&vtbl_euckr_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_euc_tw.c b/ext/mbstring/libmbfl/filters/mbfilter_euc_tw.c
index c76eeb36bf..74bca29d47 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_euc_tw.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_euc_tw.c
@@ -60,7 +60,7 @@ const mbfl_encoding mbfl_encoding_euc_tw = {
mbfl_no_encoding_euc_tw,
"EUC-TW",
"EUC-TW",
- (const char *(*)[])&mbfl_encoding_euc_tw_aliases,
+ mbfl_encoding_euc_tw_aliases,
mblen_table_euctw,
MBFL_ENCTYPE_MBCS,
&vtbl_euctw_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_gb18030.c b/ext/mbstring/libmbfl/filters/mbfilter_gb18030.c
index b94d664f40..ec6e3973a5 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_gb18030.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_gb18030.c
@@ -41,7 +41,7 @@ const mbfl_encoding mbfl_encoding_gb18030 = {
mbfl_no_encoding_gb18030,
"GB18030",
"GB18030",
- (const char *(*)[])&mbfl_encoding_gb18030_aliases,
+ mbfl_encoding_gb18030_aliases,
NULL,
MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE,
&vtbl_gb18030_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_htmlent.c b/ext/mbstring/libmbfl/filters/mbfilter_htmlent.c
index 7176fd4717..95a0817103 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_htmlent.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_htmlent.c
@@ -57,7 +57,7 @@ const mbfl_encoding mbfl_encoding_html_ent = {
mbfl_no_encoding_html_ent,
"HTML-ENTITIES",
"HTML-ENTITIES",
- (const char *(*)[])&mbfl_encoding_html_ent_aliases,
+ mbfl_encoding_html_ent_aliases,
NULL,
MBFL_ENCTYPE_GL_UNSAFE,
&vtbl_html_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso2022_jp_ms.c b/ext/mbstring/libmbfl/filters/mbfilter_iso2022_jp_ms.c
index 1e9757eae6..32f4072ce2 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_iso2022_jp_ms.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso2022_jp_ms.c
@@ -42,7 +42,7 @@ const mbfl_encoding mbfl_encoding_2022jpms = {
mbfl_no_encoding_2022jpms,
"ISO-2022-JP-MS",
"ISO-2022-JP",
- (const char *(*)[])&mbfl_encoding_2022jpms_aliases,
+ mbfl_encoding_2022jpms_aliases,
NULL,
MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE,
&vtbl_2022jpms_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_mobile.c b/ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_mobile.c
index 32ea47712e..00f0ddeda8 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_mobile.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso2022jp_mobile.c
@@ -44,7 +44,7 @@ const mbfl_encoding mbfl_encoding_2022jp_kddi = {
mbfl_no_encoding_2022jp_kddi,
"ISO-2022-JP-MOBILE#KDDI",
"ISO-2022-JP",
- (const char *(*)[])&mbfl_encoding_2022jp_kddi_aliases,
+ mbfl_encoding_2022jp_kddi_aliases,
NULL,
MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE,
&vtbl_2022jp_kddi_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_1.c b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_1.c
index 1549ba81bf..899234f3b0 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_1.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_1.c
@@ -36,7 +36,7 @@ const mbfl_encoding mbfl_encoding_8859_1 = {
mbfl_no_encoding_8859_1,
"ISO-8859-1",
"ISO-8859-1",
- (const char *(*)[])&mbfl_encoding_8859_1_aliases,
+ mbfl_encoding_8859_1_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_8859_1_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_10.c b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_10.c
index 12cd960a88..e82c52f4b6 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_10.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_10.c
@@ -37,7 +37,7 @@ const mbfl_encoding mbfl_encoding_8859_10 = {
mbfl_no_encoding_8859_10,
"ISO-8859-10",
"ISO-8859-10",
- (const char *(*)[])&mbfl_encoding_8859_10_aliases,
+ mbfl_encoding_8859_10_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_8859_10_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_13.c b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_13.c
index 25526263b8..ec5d5348a3 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_13.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_13.c
@@ -37,7 +37,7 @@ const mbfl_encoding mbfl_encoding_8859_13 = {
mbfl_no_encoding_8859_13,
"ISO-8859-13",
"ISO-8859-13",
- (const char *(*)[])&mbfl_encoding_8859_13_aliases,
+ mbfl_encoding_8859_13_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_8859_13_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_14.c b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_14.c
index 06a2e4cd98..ac5b9a40d9 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_14.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_14.c
@@ -37,7 +37,7 @@ const mbfl_encoding mbfl_encoding_8859_14 = {
mbfl_no_encoding_8859_14,
"ISO-8859-14",
"ISO-8859-14",
- (const char *(*)[])&mbfl_encoding_8859_14_aliases,
+ mbfl_encoding_8859_14_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_8859_14_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_15.c b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_15.c
index 82b40796b8..7d9e21e5c3 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_15.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_15.c
@@ -37,7 +37,7 @@ const mbfl_encoding mbfl_encoding_8859_15 = {
mbfl_no_encoding_8859_15,
"ISO-8859-15",
"ISO-8859-15",
- (const char *(*)[])&mbfl_encoding_8859_15_aliases,
+ mbfl_encoding_8859_15_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_8859_15_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_16.c b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_16.c
index 80f1461364..5c8ae964be 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_16.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_16.c
@@ -37,7 +37,7 @@ const mbfl_encoding mbfl_encoding_8859_16 = {
mbfl_no_encoding_8859_16,
"ISO-8859-16",
"ISO-8859-16",
- (const char *(*)[])&mbfl_encoding_8859_16_aliases,
+ mbfl_encoding_8859_16_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_8859_16_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_2.c b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_2.c
index 86044e15d3..deacf0c0f4 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_2.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_2.c
@@ -37,7 +37,7 @@ const mbfl_encoding mbfl_encoding_8859_2 = {
mbfl_no_encoding_8859_2,
"ISO-8859-2",
"ISO-8859-2",
- (const char *(*)[])&mbfl_encoding_8859_2_aliases,
+ mbfl_encoding_8859_2_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_8859_2_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_3.c b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_3.c
index 64eb9b5cf9..5cd3bfce1d 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_3.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_3.c
@@ -31,13 +31,15 @@
#include "mbfilter_iso8859_3.h"
#include "unicode_table_iso8859_3.h"
+static int mbfl_filt_ident_iso8859_3(int c, mbfl_identify_filter *filter);
+
static const char *mbfl_encoding_8859_3_aliases[] = {"ISO8859-3", "latin3", NULL};
const mbfl_encoding mbfl_encoding_8859_3 = {
mbfl_no_encoding_8859_3,
"ISO-8859-3",
"ISO-8859-3",
- (const char *(*)[])&mbfl_encoding_8859_3_aliases,
+ mbfl_encoding_8859_3_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_8859_3_wchar,
@@ -47,7 +49,7 @@ const mbfl_encoding mbfl_encoding_8859_3 = {
const struct mbfl_identify_vtbl vtbl_identify_8859_3 = {
mbfl_no_encoding_8859_3,
mbfl_filt_ident_common_ctor,
- mbfl_filt_ident_true
+ mbfl_filt_ident_iso8859_3
};
const struct mbfl_convert_vtbl vtbl_8859_3_wchar = {
@@ -119,9 +121,6 @@ int mbfl_filt_conv_wchar_8859_3(int c, mbfl_convert_filter *filter)
}
n--;
}
- if (s <= 0 && (c & ~MBFL_WCSPLANE_MASK) == MBFL_WCSPLANE_8859_3) {
- s = c & MBFL_WCSPLANE_MASK;
- }
}
if (s >= 0) {
@@ -132,3 +131,11 @@ int mbfl_filt_conv_wchar_8859_3(int c, mbfl_convert_filter *filter)
return c;
}
+
+static int mbfl_filt_ident_iso8859_3(int c, mbfl_identify_filter *filter)
+{
+ if (c >= 0xA0 && !iso8859_3_ucs_table[c - 0xA0]) {
+ filter->status = 1;
+ }
+ return c;
+}
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_4.c b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_4.c
index 12a9f7cb10..263036f27b 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_4.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_4.c
@@ -37,7 +37,7 @@ const mbfl_encoding mbfl_encoding_8859_4 = {
mbfl_no_encoding_8859_4,
"ISO-8859-4",
"ISO-8859-4",
- (const char *(*)[])&mbfl_encoding_8859_4_aliases,
+ mbfl_encoding_8859_4_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_8859_4_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_5.c b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_5.c
index 70496d07e7..b9a6132029 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_5.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_5.c
@@ -37,7 +37,7 @@ const mbfl_encoding mbfl_encoding_8859_5 = {
mbfl_no_encoding_8859_5,
"ISO-8859-5",
"ISO-8859-5",
- (const char *(*)[])&mbfl_encoding_8859_5_aliases,
+ mbfl_encoding_8859_5_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_8859_5_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_6.c b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_6.c
index 59d981e9c2..8b1fc4bbad 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_6.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_6.c
@@ -31,13 +31,15 @@
#include "mbfilter_iso8859_6.h"
#include "unicode_table_iso8859_6.h"
+static int mbfl_filt_ident_iso8859_6(int c, mbfl_identify_filter *filter);
+
static const char *mbfl_encoding_8859_6_aliases[] = {"ISO8859-6", "arabic", NULL};
const mbfl_encoding mbfl_encoding_8859_6 = {
mbfl_no_encoding_8859_6,
"ISO-8859-6",
"ISO-8859-6",
- (const char *(*)[])&mbfl_encoding_8859_6_aliases,
+ mbfl_encoding_8859_6_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_8859_6_wchar,
@@ -47,7 +49,7 @@ const mbfl_encoding mbfl_encoding_8859_6 = {
const struct mbfl_identify_vtbl vtbl_identify_8859_6 = {
mbfl_no_encoding_8859_6,
mbfl_filt_ident_common_ctor,
- mbfl_filt_ident_true
+ mbfl_filt_ident_iso8859_6
};
const struct mbfl_convert_vtbl vtbl_8859_6_wchar = {
@@ -119,9 +121,6 @@ int mbfl_filt_conv_wchar_8859_6(int c, mbfl_convert_filter *filter)
}
n--;
}
- if (s <= 0 && (c & ~MBFL_WCSPLANE_MASK) == MBFL_WCSPLANE_8859_6) {
- s = c & MBFL_WCSPLANE_MASK;
- }
}
if (s >= 0) {
@@ -132,3 +131,11 @@ int mbfl_filt_conv_wchar_8859_6(int c, mbfl_convert_filter *filter)
return c;
}
+
+static int mbfl_filt_ident_iso8859_6(int c, mbfl_identify_filter *filter)
+{
+ if (c >= 0xA0 && !iso8859_6_ucs_table[c - 0xA0]) {
+ filter->status = 1;
+ }
+ return c;
+}
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_7.c b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_7.c
index 73ead533ea..e87ae0ec36 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_7.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_7.c
@@ -31,13 +31,15 @@
#include "mbfilter_iso8859_7.h"
#include "unicode_table_iso8859_7.h"
+static int mbfl_filt_ident_iso8859_7(int c, mbfl_identify_filter *filter);
+
static const char *mbfl_encoding_8859_7_aliases[] = {"ISO8859-7", "greek", NULL};
const mbfl_encoding mbfl_encoding_8859_7 = {
mbfl_no_encoding_8859_7,
"ISO-8859-7",
"ISO-8859-7",
- (const char *(*)[])&mbfl_encoding_8859_7_aliases,
+ mbfl_encoding_8859_7_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_8859_7_wchar,
@@ -47,7 +49,7 @@ const mbfl_encoding mbfl_encoding_8859_7 = {
const struct mbfl_identify_vtbl vtbl_identify_8859_7 = {
mbfl_no_encoding_8859_7,
mbfl_filt_ident_common_ctor,
- mbfl_filt_ident_true
+ mbfl_filt_ident_iso8859_7
};
const struct mbfl_convert_vtbl vtbl_8859_7_wchar = {
@@ -119,9 +121,6 @@ int mbfl_filt_conv_wchar_8859_7(int c, mbfl_convert_filter *filter)
}
n--;
}
- if (s <= 0 && (c & ~MBFL_WCSPLANE_MASK) == MBFL_WCSPLANE_8859_7) {
- s = c & MBFL_WCSPLANE_MASK;
- }
}
if (s >= 0) {
@@ -132,3 +131,11 @@ int mbfl_filt_conv_wchar_8859_7(int c, mbfl_convert_filter *filter)
return c;
}
+
+static int mbfl_filt_ident_iso8859_7(int c, mbfl_identify_filter *filter)
+{
+ /* These bytes are not mapped to any character in ISO-8859-7 */
+ if (c == 0xAE || c == 0xD2 || c == 0xFF)
+ filter->status = 1;
+ return c;
+}
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_8.c b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_8.c
index 05ca13f330..3436d8d3ea 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_8.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_8.c
@@ -31,13 +31,15 @@
#include "mbfilter_iso8859_8.h"
#include "unicode_table_iso8859_8.h"
+static int mbfl_filt_ident_iso8859_8(int c, mbfl_identify_filter *filter);
+
static const char *mbfl_encoding_8859_8_aliases[] = {"ISO8859-8", "hebrew", NULL};
const mbfl_encoding mbfl_encoding_8859_8 = {
mbfl_no_encoding_8859_8,
"ISO-8859-8",
"ISO-8859-8",
- (const char *(*)[])&mbfl_encoding_8859_8_aliases,
+ mbfl_encoding_8859_8_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_8859_8_wchar,
@@ -47,7 +49,7 @@ const mbfl_encoding mbfl_encoding_8859_8 = {
const struct mbfl_identify_vtbl vtbl_identify_8859_8 = {
mbfl_no_encoding_8859_8,
mbfl_filt_ident_common_ctor,
- mbfl_filt_ident_true
+ mbfl_filt_ident_iso8859_8
};
const struct mbfl_convert_vtbl vtbl_8859_8_wchar = {
@@ -118,9 +120,6 @@ int mbfl_filt_conv_wchar_8859_8(int c, mbfl_convert_filter *filter)
}
n--;
}
- if (s <= 0 && (c & ~MBFL_WCSPLANE_MASK) == MBFL_WCSPLANE_8859_8) {
- s = c & MBFL_WCSPLANE_MASK;
- }
}
if (s >= 0) {
@@ -131,3 +130,11 @@ int mbfl_filt_conv_wchar_8859_8(int c, mbfl_convert_filter *filter)
return c;
}
+
+static int mbfl_filt_ident_iso8859_8(int c, mbfl_identify_filter *filter)
+{
+ if (c >= 0xA0 && !iso8859_8_ucs_table[c - 0xA0]) {
+ filter->status = 1;
+ }
+ return c;
+}
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_9.c b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_9.c
index 074f90bef2..a2b87d1174 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_iso8859_9.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_iso8859_9.c
@@ -37,7 +37,7 @@ const mbfl_encoding mbfl_encoding_8859_9 = {
mbfl_no_encoding_8859_9,
"ISO-8859-9",
"ISO-8859-9",
- (const char *(*)[])&mbfl_encoding_8859_9_aliases,
+ mbfl_encoding_8859_9_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_8859_9_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_koi8r.c b/ext/mbstring/libmbfl/filters/mbfilter_koi8r.c
index 7790be65bb..db00a73c4f 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_koi8r.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_koi8r.c
@@ -39,7 +39,7 @@ const mbfl_encoding mbfl_encoding_koi8r = {
mbfl_no_encoding_koi8r,
"KOI8-R",
"KOI8-R",
- (const char *(*)[])&mbfl_encoding_koi8r_aliases,
+ mbfl_encoding_koi8r_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_koi8r_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_koi8u.c b/ext/mbstring/libmbfl/filters/mbfilter_koi8u.c
index a62a1c596b..54c06d2663 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_koi8u.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_koi8u.c
@@ -36,7 +36,7 @@ const mbfl_encoding mbfl_encoding_koi8u = {
mbfl_no_encoding_koi8u,
"KOI8-U",
"KOI8-U",
- (const char *(*)[])&mbfl_encoding_koi8u_aliases,
+ mbfl_encoding_koi8u_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_koi8u_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_qprint.c b/ext/mbstring/libmbfl/filters/mbfilter_qprint.c
index d42cdca883..8f806def25 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_qprint.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_qprint.c
@@ -37,7 +37,7 @@ const mbfl_encoding mbfl_encoding_qprint = {
mbfl_no_encoding_qprint,
"Quoted-Printable",
"Quoted-Printable",
- (const char *(*)[])&mbfl_encoding_qprint_aliases,
+ mbfl_encoding_qprint_aliases,
NULL,
MBFL_ENCTYPE_GL_UNSAFE,
NULL,
@@ -110,8 +110,7 @@ int mbfl_filt_conv_qprintenc(int c, mbfl_convert_filter *filter)
}
if (s <= 0 || s >= 0x80 || s == 0x3d /* not ASCII or '=' */
- || ((filter->status & MBFL_QPRINT_STS_MIME_HEADER) != 0 &&
- (mbfl_charprop_table[s] & MBFL_CHP_MMHQENC) != 0)) {
+ || ((filter->status & MBFL_QPRINT_STS_MIME_HEADER) && mime_char_needs_qencode[s])) {
/* hex-octet */
CK((*filter->output_function)(0x3d, filter->data)); /* '=' */
n = (s >> 4) & 0xf;
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_sjis.c b/ext/mbstring/libmbfl/filters/mbfilter_sjis.c
index dc5c2e4882..d993c89d7f 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_sjis.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_sjis.c
@@ -63,7 +63,7 @@ const mbfl_encoding mbfl_encoding_sjis = {
mbfl_no_encoding_sjis,
"SJIS",
"Shift_JIS",
- (const char *(*)[])&mbfl_encoding_sjis_aliases,
+ mbfl_encoding_sjis_aliases,
mblen_table_sjis,
MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE,
&vtbl_sjis_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_sjis_2004.c b/ext/mbstring/libmbfl/filters/mbfilter_sjis_2004.c
index 04e1d3af17..e611f3f846 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_sjis_2004.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_sjis_2004.c
@@ -45,7 +45,7 @@ const mbfl_encoding mbfl_encoding_sjis2004 = {
mbfl_no_encoding_sjis2004,
"SJIS-2004",
"Shift_JIS",
- (const char *(*)[])&mbfl_encoding_sjis2004_aliases,
+ mbfl_encoding_sjis2004_aliases,
mblen_table_sjis,
MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE,
&vtbl_sjis2004_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_sjis_mac.c b/ext/mbstring/libmbfl/filters/mbfilter_sjis_mac.c
index dc3d3692f4..ff8d01937f 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_sjis_mac.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_sjis_mac.c
@@ -46,7 +46,7 @@ const mbfl_encoding mbfl_encoding_sjis_mac = {
mbfl_no_encoding_sjis_mac,
"SJIS-mac",
"Shift_JIS",
- (const char *(*)[])&mbfl_encoding_sjis_mac_aliases,
+ mbfl_encoding_sjis_mac_aliases,
mblen_table_sjis,
MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE,
&vtbl_sjis_mac_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_sjis_mobile.c b/ext/mbstring/libmbfl/filters/mbfilter_sjis_mobile.c
index 68084a0e0a..d5015a92a8 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_sjis_mobile.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_sjis_mobile.c
@@ -47,7 +47,7 @@ const mbfl_encoding mbfl_encoding_sjis_docomo = {
mbfl_no_encoding_sjis_docomo,
"SJIS-Mobile#DOCOMO",
"Shift_JIS",
- (const char *(*)[])&mbfl_encoding_sjis_docomo_aliases,
+ mbfl_encoding_sjis_docomo_aliases,
mblen_table_sjis,
MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE,
&vtbl_sjis_docomo_wchar,
@@ -58,7 +58,7 @@ const mbfl_encoding mbfl_encoding_sjis_kddi = {
mbfl_no_encoding_sjis_kddi,
"SJIS-Mobile#KDDI",
"Shift_JIS",
- (const char *(*)[])&mbfl_encoding_sjis_kddi_aliases,
+ mbfl_encoding_sjis_kddi_aliases,
mblen_table_sjis,
MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE,
&vtbl_sjis_kddi_wchar,
@@ -69,7 +69,7 @@ const mbfl_encoding mbfl_encoding_sjis_sb = {
mbfl_no_encoding_sjis_sb,
"SJIS-Mobile#SOFTBANK",
"Shift_JIS",
- (const char *(*)[])&mbfl_encoding_sjis_sb_aliases,
+ mbfl_encoding_sjis_sb_aliases,
mblen_table_sjis,
MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE,
&vtbl_sjis_sb_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_sjis_open.c b/ext/mbstring/libmbfl/filters/mbfilter_sjis_open.c
index 2535036e23..b3ec28740b 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_sjis_open.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_sjis_open.c
@@ -60,7 +60,7 @@ const mbfl_encoding mbfl_encoding_sjis_open = {
mbfl_no_encoding_sjis_open,
"SJIS-win",
"Shift_JIS",
- (const char *(*)[])&mbfl_encoding_sjis_open_aliases,
+ mbfl_encoding_sjis_open_aliases,
mblen_table_sjis,
MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE,
&vtbl_sjis_open_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_ucs2.c b/ext/mbstring/libmbfl/filters/mbfilter_ucs2.c
index 68172efbe6..258c564aae 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_ucs2.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_ucs2.c
@@ -30,13 +30,15 @@
#include "mbfilter.h"
#include "mbfilter_ucs2.h"
+static int mbfl_filt_ident_ucs2(int c, mbfl_identify_filter *filter);
+
static const char *mbfl_encoding_ucs2_aliases[] = {"ISO-10646-UCS-2", "UCS2" , "UNICODE", NULL};
const mbfl_encoding mbfl_encoding_ucs2 = {
mbfl_no_encoding_ucs2,
"UCS-2",
"UCS-2",
- (const char *(*)[])&mbfl_encoding_ucs2_aliases,
+ mbfl_encoding_ucs2_aliases,
NULL,
MBFL_ENCTYPE_WCS2BE,
&vtbl_ucs2_wchar,
@@ -65,6 +67,24 @@ const mbfl_encoding mbfl_encoding_ucs2le = {
&vtbl_wchar_ucs2le
};
+const struct mbfl_identify_vtbl vtbl_identify_ucs2 = {
+ mbfl_no_encoding_ucs2,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_ucs2
+};
+
+const struct mbfl_identify_vtbl vtbl_identify_ucs2be = {
+ mbfl_no_encoding_ucs2be,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_ucs2
+};
+
+const struct mbfl_identify_vtbl vtbl_identify_ucs2le = {
+ mbfl_no_encoding_ucs2le,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_ucs2
+};
+
const struct mbfl_convert_vtbl vtbl_ucs2_wchar = {
mbfl_no_encoding_ucs2,
mbfl_no_encoding_wchar,
@@ -237,3 +257,10 @@ int mbfl_filt_conv_wchar_ucs2le(int c, mbfl_convert_filter *filter)
return c;
}
+
+static int mbfl_filt_ident_ucs2(int c, mbfl_identify_filter *filter)
+{
+ /* Input string must be a multiple of 2 bytes */
+ filter->status = (filter->status + 1) % 2;
+ return c;
+}
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_ucs2.h b/ext/mbstring/libmbfl/filters/mbfilter_ucs2.h
index bbf567a493..f6d9b8b772 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_ucs2.h
+++ b/ext/mbstring/libmbfl/filters/mbfilter_ucs2.h
@@ -35,6 +35,9 @@
extern const mbfl_encoding mbfl_encoding_ucs2;
extern const mbfl_encoding mbfl_encoding_ucs2be;
extern const mbfl_encoding mbfl_encoding_ucs2le;
+extern const struct mbfl_identify_vtbl vtbl_identify_ucs2;
+extern const struct mbfl_identify_vtbl vtbl_identify_ucs2be;
+extern const struct mbfl_identify_vtbl vtbl_identify_ucs2le;
extern const struct mbfl_convert_vtbl vtbl_ucs2_wchar;
extern const struct mbfl_convert_vtbl vtbl_wchar_ucs2;
extern const struct mbfl_convert_vtbl vtbl_ucs2be_wchar;
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_ucs4.c b/ext/mbstring/libmbfl/filters/mbfilter_ucs4.c
index fcdd20d615..396bae91c5 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_ucs4.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_ucs4.c
@@ -36,7 +36,7 @@ const mbfl_encoding mbfl_encoding_ucs4 = {
mbfl_no_encoding_ucs4,
"UCS-4",
"UCS-4",
- (const char *(*)[])&mbfl_encoding_ucs4_aliases,
+ mbfl_encoding_ucs4_aliases,
NULL,
MBFL_ENCTYPE_WCS4BE,
&vtbl_ucs4_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_uhc.c b/ext/mbstring/libmbfl/filters/mbfilter_uhc.c
index 5dc4aa81a9..c86612bac2 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_uhc.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_uhc.c
@@ -59,7 +59,7 @@ const mbfl_encoding mbfl_encoding_uhc = {
mbfl_no_encoding_uhc,
"UHC",
"UHC",
- (const char *(*)[])&mbfl_encoding_uhc_aliases,
+ mbfl_encoding_uhc_aliases,
mblen_table_uhc,
MBFL_ENCTYPE_MBCS,
&vtbl_uhc_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf16.c b/ext/mbstring/libmbfl/filters/mbfilter_utf16.c
index 620e8a76f7..c23a432695 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_utf16.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_utf16.c
@@ -30,13 +30,18 @@
#include "mbfilter.h"
#include "mbfilter_utf16.h"
+static int mbfl_filt_ident_utf16(int c, mbfl_identify_filter *filter);
+static int mbfl_filt_ident_utf16le(int c, mbfl_identify_filter *filter);
+static int mbfl_filt_ident_utf16be(int c, mbfl_identify_filter *filter);
+static int mbfl_filt_conv_utf16_wchar_flush(mbfl_convert_filter *filter);
+
static const char *mbfl_encoding_utf16_aliases[] = {"utf16", NULL};
const mbfl_encoding mbfl_encoding_utf16 = {
mbfl_no_encoding_utf16,
"UTF-16",
"UTF-16",
- (const char *(*)[])&mbfl_encoding_utf16_aliases,
+ mbfl_encoding_utf16_aliases,
NULL,
MBFL_ENCTYPE_MWC2BE,
&vtbl_utf16_wchar,
@@ -65,13 +70,31 @@ const mbfl_encoding mbfl_encoding_utf16le = {
&vtbl_wchar_utf16le
};
+const struct mbfl_identify_vtbl vtbl_identify_utf16 = {
+ mbfl_no_encoding_utf16,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_utf16
+};
+
+const struct mbfl_identify_vtbl vtbl_identify_utf16le = {
+ mbfl_no_encoding_utf16le,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_utf16le
+};
+
+const struct mbfl_identify_vtbl vtbl_identify_utf16be = {
+ mbfl_no_encoding_utf16be,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_utf16be
+};
+
const struct mbfl_convert_vtbl vtbl_utf16_wchar = {
mbfl_no_encoding_utf16,
mbfl_no_encoding_wchar,
mbfl_filt_conv_common_ctor,
NULL,
mbfl_filt_conv_utf16_wchar,
- mbfl_filt_conv_common_flush,
+ mbfl_filt_conv_utf16_wchar_flush,
NULL,
};
@@ -91,7 +114,7 @@ const struct mbfl_convert_vtbl vtbl_utf16be_wchar = {
mbfl_filt_conv_common_ctor,
NULL,
mbfl_filt_conv_utf16be_wchar,
- mbfl_filt_conv_common_flush,
+ mbfl_filt_conv_utf16_wchar_flush,
NULL,
};
@@ -111,7 +134,7 @@ const struct mbfl_convert_vtbl vtbl_utf16le_wchar = {
mbfl_filt_conv_common_ctor,
NULL,
mbfl_filt_conv_utf16le_wchar,
- mbfl_filt_conv_common_flush,
+ mbfl_filt_conv_utf16_wchar_flush,
NULL,
};
@@ -127,111 +150,89 @@ const struct mbfl_convert_vtbl vtbl_wchar_utf16le = {
#define CK(statement) do { if ((statement) < 0) return (-1); } while (0)
-/*
- * UTF-16 => wchar
- */
int mbfl_filt_conv_utf16_wchar(int c, mbfl_convert_filter *filter)
{
- int n, endian;
-
- endian = filter->status & 0xff00;
- switch (filter->status & 0x0f) {
- case 0:
- if (endian) {
- n = c & 0xff;
- } else {
- n = (c & 0xff) << 8;
- }
- filter->cache |= n;
- filter->status++;
- break;
- default:
- if (endian) {
- n = (c & 0xff) << 8;
+ /* Start with the assumption that the string is big-endian;
+ * If we find a little-endian BOM, then we will change that assumption */
+ if (filter->status == 0) {
+ filter->cache = c & 0xFF;
+ filter->status = 1;
+ } else {
+ int n = (filter->cache << 8) | (c & 0xFF);
+ if (n == 0xFFFE) {
+ /* Switch to little-endian mode */
+ filter->filter_function = mbfl_filt_conv_utf16le_wchar;
+ filter->cache = filter->status = 0;
} else {
- n = c & 0xff;
- }
- n |= filter->cache & 0xffff;
- filter->status &= ~0x0f;
- if (n >= 0xd800 && n < 0xdc00) {
- filter->cache = ((n & 0x3ff) << 16) + 0x400000;
- } else if (n >= 0xdc00 && n < 0xe000) {
- n &= 0x3ff;
- n |= (filter->cache & 0xfff0000) >> 6;
- filter->cache = 0;
- if (n >= MBFL_WCSPLANE_SUPMIN && n < MBFL_WCSPLANE_SUPMAX) {
- CK((*filter->output_function)(n, filter->data));
- } else { /* illegal character */
- n &= MBFL_WCSGROUP_MASK;
- n |= MBFL_WCSGROUP_THROUGH;
+ filter->filter_function = mbfl_filt_conv_utf16be_wchar;
+ if (n >= 0xD800 && n <= 0xDBFF) {
+ filter->cache = n & 0x3FF; /* Pick out 10 data bits */
+ filter->status = 2;
+ return c;
+ } else if (n >= 0xDC00 && n <= 0xDFFF) {
+ /* This is wrong; second part of surrogate pair has come first */
+ CK((*filter->output_function)(n | MBFL_WCSGROUP_THROUGH, filter->data));
+ } else if (n != 0xFEFF) {
CK((*filter->output_function)(n, filter->data));
}
- } else {
- int is_first = filter->status & 0x10;
- filter->cache = 0;
- filter->status |= 0x10;
- if (!is_first) {
- if (n == 0xfffe) {
- if (endian) {
- filter->status &= ~0x100; /* big-endian */
- } else {
- filter->status |= 0x100; /* little-endian */
- }
- break;
- } else if (n == 0xfeff) {
- break;
- }
- }
- CK((*filter->output_function)(n, filter->data));
+ filter->cache = filter->status = 0;
}
- break;
}
return c;
}
-/*
- * UTF-16BE => wchar
- */
int mbfl_filt_conv_utf16be_wchar(int c, mbfl_convert_filter *filter)
{
int n;
switch (filter->status) {
- case 0:
+ case 0: /* First byte */
+ filter->cache = c & 0xFF;
filter->status = 1;
- n = (c & 0xff) << 8;
- filter->cache |= n;
break;
- default:
- filter->status = 0;
- n = (filter->cache & 0xff00) | (c & 0xff);
- if (n >= 0xd800 && n < 0xdc00) {
- filter->cache = ((n & 0x3ff) << 16) + 0x400000;
- } else if (n >= 0xdc00 && n < 0xe000) {
- n &= 0x3ff;
- n |= (filter->cache & 0xfff0000) >> 6;
- filter->cache = 0;
- if (n >= MBFL_WCSPLANE_SUPMIN && n < MBFL_WCSPLANE_SUPMAX) {
- CK((*filter->output_function)(n, filter->data));
- } else { /* illegal character */
- n &= MBFL_WCSGROUP_MASK;
- n |= MBFL_WCSGROUP_THROUGH;
- CK((*filter->output_function)(n, filter->data));
- }
+
+ case 1: /* Second byte */
+ n = (filter->cache << 8) | (c & 0xFF);
+ if (n >= 0xD800 && n <= 0xDBFF) {
+ filter->cache = n & 0x3FF; /* Pick out 10 data bits */
+ filter->status = 2;
+ } else if (n >= 0xDC00 && n <= 0xDFFF) {
+ /* This is wrong; second part of surrogate pair has come first */
+ CK((*filter->output_function)(n | MBFL_WCSGROUP_THROUGH, filter->data));
+ filter->status = 0;
} else {
- filter->cache = 0;
CK((*filter->output_function)(n, filter->data));
+ filter->status = 0;
}
break;
+
+ case 2: /* Second part of surrogate, first byte */
+ filter->cache = (filter->cache << 8) | (c & 0xFF);
+ filter->status = 3;
+ break;
+
+ case 3: /* Second part of surrogate, second byte */
+ n = ((filter->cache & 0xFF) << 8) | (c & 0xFF);
+ if (n >= 0xD800 && n <= 0xDBFF) {
+ /* Wrong; that's the first half of a surrogate pair, not the second */
+ CK((*filter->output_function)((0xD8 << 10) | (filter->cache >> 8) | MBFL_WCSGROUP_THROUGH, filter->data));
+ filter->cache = n & 0x3FF;
+ filter->status = 2;
+ } else if (n >= 0xDC00 && n <= 0xDFFF) {
+ n = ((filter->cache & 0x3FF00) << 2) + (n & 0x3FF) + 0x10000;
+ CK((*filter->output_function)(n, filter->data));
+ filter->status = 0;
+ } else {
+ CK((*filter->output_function)((0xD8 << 10) | (filter->cache >> 8) | MBFL_WCSGROUP_THROUGH, filter->data));
+ CK((*filter->output_function)(n, filter->data));
+ filter->status = 0;
+ }
}
return c;
}
-/*
- * wchar => UTF-16BE
- */
int mbfl_filt_conv_wchar_utf16be(int c, mbfl_convert_filter *filter)
{
int n;
@@ -253,38 +254,53 @@ int mbfl_filt_conv_wchar_utf16be(int c, mbfl_convert_filter *filter)
return c;
}
-/*
- * UTF-16LE => wchar
- */
int mbfl_filt_conv_utf16le_wchar(int c, mbfl_convert_filter *filter)
{
int n;
switch (filter->status) {
case 0:
+ filter->cache = c & 0xff;
filter->status = 1;
- n = c & 0xff;
- filter->cache |= n;
break;
- default:
- filter->status = 0;
- n = (filter->cache & 0xff) | ((c & 0xff) << 8);
- if (n >= 0xd800 && n < 0xdc00) {
- filter->cache = ((n & 0x3ff) << 16) + 0x400000;
- } else if (n >= 0xdc00 && n < 0xe000) {
- n &= 0x3ff;
- n |= (filter->cache & 0xfff0000) >> 6;
- filter->cache = 0;
- if (n >= MBFL_WCSPLANE_SUPMIN && n < MBFL_WCSPLANE_SUPMAX) {
- CK((*filter->output_function)(n, filter->data));
- } else { /* illegal character */
- n &= MBFL_WCSGROUP_MASK;
- n |= MBFL_WCSGROUP_THROUGH;
- CK((*filter->output_function)(n, filter->data));
- }
+
+ case 1:
+ if ((c & 0xfc) == 0xd8) {
+ /* Looks like we have a surrogate pair here */
+ filter->cache += ((c & 0x3) << 8);
+ filter->status = 2;
+ } else if ((c & 0xfc) == 0xdc) {
+ /* This is wrong; the second part of the surrogate pair has come first
+ * Flag it with `MBFL_WCSGROUP_THROUGH`; the following filter will handle
+ * the error */
+ n = (filter->cache + ((c & 0xff) << 8)) | MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(n, filter->data));
+ filter->status = 0;
} else {
- filter->cache = 0;
+ CK((*filter->output_function)(filter->cache + ((c & 0xff) << 8), filter->data));
+ filter->status = 0;
+ }
+ break;
+
+ case 2:
+ filter->cache = (filter->cache << 10) + (c & 0xff);
+ filter->status = 3;
+ break;
+
+ case 3:
+ n = (filter->cache & 0xFF) | ((c & 0xFF) << 8);
+ if (n >= 0xD800 && n <= 0xDBFF) {
+ CK((*filter->output_function)((0xD8 << 10) | (filter->cache >> 10) | MBFL_WCSGROUP_THROUGH, filter->data));
+ filter->cache = n & 0x3FF;
+ filter->status = 2;
+ } else if (n >= 0xDC00 && n <= 0xDFFF) {
+ n = filter->cache + ((c & 0x3) << 8) + 0x10000;
CK((*filter->output_function)(n, filter->data));
+ filter->status = 0;
+ } else {
+ CK((*filter->output_function)((0xD8 << 10) | (filter->cache >> 10) | MBFL_WCSGROUP_THROUGH, filter->data));
+ CK((*filter->output_function)(n, filter->data));
+ filter->status = 0;
}
break;
}
@@ -292,9 +308,6 @@ int mbfl_filt_conv_utf16le_wchar(int c, mbfl_convert_filter *filter)
return c;
}
-/*
- * wchar => UTF-16LE
- */
int mbfl_filt_conv_wchar_utf16le(int c, mbfl_convert_filter *filter)
{
int n;
@@ -315,3 +328,126 @@ int mbfl_filt_conv_wchar_utf16le(int c, mbfl_convert_filter *filter)
return c;
}
+
+static int mbfl_filt_conv_utf16_wchar_flush(mbfl_convert_filter *filter)
+{
+ int status = filter->status;
+ int cache = filter->cache;
+ filter->status = filter->cache = 0;
+
+ if (status) {
+ /* Input string was truncated */
+ CK((*filter->output_function)(cache | MBFL_WCSGROUP_THROUGH, filter->data));
+ }
+
+ if (filter->flush_function) {
+ (*filter->flush_function)(filter->data);
+ }
+
+ return 0;
+}
+
+static int mbfl_filt_ident_utf16(int c, mbfl_identify_filter *filter)
+{
+ if (filter->status == 0) {
+ if (c >= 0xfe) { /* could be a byte-order mark */
+ filter->status = c;
+ } else {
+ /* no byte-order mark at beginning of input; assume UTF-16BE */
+ filter->filter_function = mbfl_filt_ident_utf16be;
+ return (filter->filter_function)(c, filter);
+ }
+ } else {
+ unsigned short n = (filter->status << 8) | c;
+ filter->status = 0;
+
+ if (n == 0xfeff) {
+ /* it was a big-endian byte-order mark */
+ filter->filter_function = mbfl_filt_ident_utf16be;
+ } else if (n == 0xfffe) {
+ /* it was a little-endian byte-order mark */
+ filter->filter_function = mbfl_filt_ident_utf16le;
+ } else {
+ /* it wasn't a byte-order mark */
+ filter->filter_function = mbfl_filt_ident_utf16be;
+ (filter->filter_function)(n >> 8, filter);
+ return (filter->filter_function)(c, filter);
+ }
+ }
+ return c;
+}
+
+static int mbfl_filt_ident_utf16le(int c, mbfl_identify_filter *filter)
+{
+ switch (filter->status) {
+ case 0: /* 1st byte */
+ filter->status = 1;
+ break;
+
+ case 1: /* 2nd byte */
+ if ((c & 0xfc) == 0xd8) {
+ /* Looks like a surrogate pair */
+ filter->status = 2;
+ } else if ((c & 0xfc) == 0xdc) {
+ /* This is wrong; the second part of the surrogate pair has come first */
+ filter->flag = 1;
+ } else {
+ filter->status = 0; /* Just an ordinary 2-byte character */
+ }
+ break;
+
+ case 2: /* 3rd byte */
+ filter->status = 3;
+ break;
+
+ case 3: /* 4th byte */
+ if ((c & 0xfc) == 0xdc) {
+ filter->status = 0;
+ } else {
+ filter->flag = 1; /* Surrogate pair wrongly encoded */
+ }
+ break;
+ }
+
+ return c;
+}
+
+static int mbfl_filt_ident_utf16be(int c, mbfl_identify_filter *filter)
+{
+ switch (filter->status) {
+ case 0: /* 1st byte */
+ if ((c & 0xfc) == 0xd8) {
+ /* Looks like a surrogate pair */
+ filter->status = 2;
+ } else if ((c & 0xfc) == 0xdc) {
+ /* This is wrong; the second part of the surrogate pair has come first */
+ filter->flag = 1;
+ } else {
+ /* Just an ordinary 2-byte character */
+ filter->status = 1;
+ }
+ break;
+
+ case 1: /* 2nd byte, not surrogate pair */
+ filter->status = 0;
+ break;
+
+ case 2: /* 2nd byte, surrogate pair */
+ filter->status = 3;
+ break;
+
+ case 3: /* 3rd byte, surrogate pair */
+ if ((c & 0xfc) == 0xdc) {
+ filter->status = 4;
+ } else {
+ filter->flag = 1; /* Surrogate pair wrongly encoded */
+ }
+ break;
+
+ case 4: /* 4th byte, surrogate pair */
+ filter->status = 0;
+ break;
+ }
+
+ return c;
+}
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf16.h b/ext/mbstring/libmbfl/filters/mbfilter_utf16.h
index 4aa88619c7..601779add4 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_utf16.h
+++ b/ext/mbstring/libmbfl/filters/mbfilter_utf16.h
@@ -33,6 +33,9 @@
extern const mbfl_encoding mbfl_encoding_utf16;
extern const mbfl_encoding mbfl_encoding_utf16be;
extern const mbfl_encoding mbfl_encoding_utf16le;
+extern const struct mbfl_identify_vtbl vtbl_identify_utf16;
+extern const struct mbfl_identify_vtbl vtbl_identify_utf16le;
+extern const struct mbfl_identify_vtbl vtbl_identify_utf16be;
extern const struct mbfl_convert_vtbl vtbl_utf16_wchar;
extern const struct mbfl_convert_vtbl vtbl_wchar_utf16;
extern const struct mbfl_convert_vtbl vtbl_utf16be_wchar;
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf32.c b/ext/mbstring/libmbfl/filters/mbfilter_utf32.c
index b936ab4102..1d9f479595 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_utf32.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_utf32.c
@@ -30,13 +30,18 @@
#include "mbfilter.h"
#include "mbfilter_utf32.h"
+static int mbfl_filt_ident_utf32(int c, mbfl_identify_filter *filter);
+static int mbfl_filt_ident_utf32le(int c, mbfl_identify_filter *filter);
+static int mbfl_filt_ident_utf32be(int c, mbfl_identify_filter *filter);
+static int mbfl_filt_conv_utf32_wchar_flush(mbfl_convert_filter *filter);
+
static const char *mbfl_encoding_utf32_aliases[] = {"utf32", NULL};
const mbfl_encoding mbfl_encoding_utf32 = {
mbfl_no_encoding_utf32,
"UTF-32",
"UTF-32",
- (const char *(*)[])&mbfl_encoding_utf32_aliases,
+ mbfl_encoding_utf32_aliases,
NULL,
MBFL_ENCTYPE_WCS4BE,
&vtbl_utf32_wchar,
@@ -65,13 +70,31 @@ const mbfl_encoding mbfl_encoding_utf32le = {
&vtbl_wchar_utf32le
};
+const struct mbfl_identify_vtbl vtbl_identify_utf32 = {
+ mbfl_no_encoding_utf32,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_utf32
+};
+
+const struct mbfl_identify_vtbl vtbl_identify_utf32be = {
+ mbfl_no_encoding_utf32be,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_utf32be
+};
+
+const struct mbfl_identify_vtbl vtbl_identify_utf32le = {
+ mbfl_no_encoding_utf32le,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_utf32le
+};
+
const struct mbfl_convert_vtbl vtbl_utf32_wchar = {
mbfl_no_encoding_utf32,
mbfl_no_encoding_wchar,
mbfl_filt_conv_common_ctor,
NULL,
mbfl_filt_conv_utf32_wchar,
- mbfl_filt_conv_common_flush,
+ mbfl_filt_conv_utf32_wchar_flush,
NULL,
};
@@ -91,7 +114,7 @@ const struct mbfl_convert_vtbl vtbl_utf32be_wchar = {
mbfl_filt_conv_common_ctor,
NULL,
mbfl_filt_conv_utf32be_wchar,
- mbfl_filt_conv_common_flush,
+ mbfl_filt_conv_utf32_wchar_flush,
NULL,
};
@@ -111,7 +134,7 @@ const struct mbfl_convert_vtbl vtbl_utf32le_wchar = {
mbfl_filt_conv_common_ctor,
NULL,
mbfl_filt_conv_utf32le_wchar,
- mbfl_filt_conv_common_flush,
+ mbfl_filt_conv_utf32_wchar_flush,
NULL,
};
@@ -289,3 +312,143 @@ int mbfl_filt_conv_wchar_utf32le(int c, mbfl_convert_filter *filter)
return c;
}
+
+static int mbfl_filt_conv_utf32_wchar_flush(mbfl_convert_filter *filter)
+{
+ if (filter->status & 0xF) {
+ /* Input string was truncated */
+ CK((*filter->output_function)(filter->cache | MBFL_WCSGROUP_THROUGH, filter->data));
+ }
+
+ if (filter->flush_function) {
+ (*filter->flush_function)(filter->data);
+ }
+
+ filter->status = filter->cache = 0;
+ return 0;
+}
+
+static int mbfl_filt_ident_utf32(int c, mbfl_identify_filter *filter)
+{
+ /* The largest valid codepoint is 0x10FFFF; we don't want values above that
+ * Neither do we want to see surrogates
+ * For UTF-32 (not LE or BE), we do also need to look for a byte-order mark */
+ switch (filter->status) {
+ case 0: /* 1st byte */
+ if (c == 0xff) {
+ filter->status = 1;
+ return c;
+ }
+ filter->filter_function = mbfl_filt_ident_utf32be;
+ break;
+
+ case 1: /* 2nd byte */
+ if (c == 0xfe) {
+ filter->status = 2;
+ return c;
+ }
+ filter->filter_function = mbfl_filt_ident_utf32be;
+ (filter->filter_function)(0xff, filter);
+ break;
+
+ case 2: /* 3rd byte */
+ if (c == 0) {
+ filter->status = 3;
+ return c;
+ }
+ filter->filter_function = mbfl_filt_ident_utf32be;
+ (filter->filter_function)(0xff, filter);
+ (filter->filter_function)(0xfe, filter);
+ break;
+
+ case 3: /* 4th byte */
+ if (c == 0) {
+ /* We found a little-endian byte-order mark! */
+ filter->status = 0;
+ filter->filter_function = mbfl_filt_ident_utf32le;
+ return c;
+ }
+ filter->filter_function = mbfl_filt_ident_utf32be;
+ (filter->filter_function)(0xff, filter);
+ (filter->filter_function)(0xfe, filter);
+ (filter->filter_function)(0, filter);
+ break;
+ }
+
+ return (filter->filter_function)(c, filter);
+}
+
+static int mbfl_filt_ident_utf32le(int c, mbfl_identify_filter *filter)
+{
+ switch (filter->status) {
+ case 0: /* 1st byte */
+ filter->status = 1;
+ break;
+
+ case 1: /* 2nd byte */
+ if (c >= 0xD8 && c <= 0xDF) {
+ filter->status = 4; /* might be surrogate if we are in BMP */
+ } else {
+ filter->status = 2;
+ }
+ break;
+
+ case 2: /* 3rd byte */
+ if (c > 0x10) {
+ filter->flag = 1; /* too big */
+ }
+ filter->status = 3;
+ break;
+
+ case 3: /* 4th byte */
+ if (c) {
+ filter->flag = 1; /* too big */
+ }
+ filter->status = 0;
+ break;
+
+ case 4: /* 3rd byte, previous byte looked like surrogate */
+ if (!c) {
+ filter->flag = 1; /* yep, it's a surrogate */
+ }
+ filter->status = 3;
+ }
+ return c;
+}
+
+static int mbfl_filt_ident_utf32be(int c, mbfl_identify_filter *filter)
+{
+ switch (filter->status) {
+ case 0: /* 1st byte */
+ if (c) {
+ filter->flag = 1; /* too big */
+ }
+ filter->status = 1;
+ break;
+
+ case 1: /* 2nd byte */
+ if (c > 0x10) {
+ filter->flag = 1; /* too big */
+ } if (c) {
+ filter->status = 4; /* not in the BMP */
+ } else {
+ filter->status = 2;
+ }
+ break;
+
+ case 2: /* 3rd byte */
+ if (c >= 0xD8 && c <= 0xDF) {
+ filter->flag = 1; /* reserved range for surrogates */
+ }
+ filter->status = 3;
+ break;
+
+ case 3: /* 4th byte */
+ filter->status = 0;
+ break;
+
+ case 4: /* 3rd byte, not in BMP */
+ filter->status = 3;
+ }
+ return c;
+}
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf32.h b/ext/mbstring/libmbfl/filters/mbfilter_utf32.h
index 14b9fa4823..de1235e451 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_utf32.h
+++ b/ext/mbstring/libmbfl/filters/mbfilter_utf32.h
@@ -33,6 +33,9 @@
extern const mbfl_encoding mbfl_encoding_utf32;
extern const mbfl_encoding mbfl_encoding_utf32be;
extern const mbfl_encoding mbfl_encoding_utf32le;
+extern const struct mbfl_identify_vtbl vtbl_identify_utf32;
+extern const struct mbfl_identify_vtbl vtbl_identify_utf32be;
+extern const struct mbfl_identify_vtbl vtbl_identify_utf32le;
extern const struct mbfl_convert_vtbl vtbl_utf32_wchar;
extern const struct mbfl_convert_vtbl vtbl_wchar_utf32;
extern const struct mbfl_convert_vtbl vtbl_utf32be_wchar;
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf7.c b/ext/mbstring/libmbfl/filters/mbfilter_utf7.c
index b54bcf2b9c..ed931a8b1f 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_utf7.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_utf7.c
@@ -51,7 +51,7 @@ const mbfl_encoding mbfl_encoding_utf7 = {
mbfl_no_encoding_utf7,
"UTF-7",
"UTF-7",
- (const char *(*)[])&mbfl_encoding_utf7_aliases,
+ mbfl_encoding_utf7_aliases,
NULL,
MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE,
&vtbl_utf7_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf7imap.c b/ext/mbstring/libmbfl/filters/mbfilter_utf7imap.c
index c8fe70fc7f..4c1cd8712f 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_utf7imap.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_utf7imap.c
@@ -27,14 +27,64 @@
*
*/
+/* Modified UTF-7 used for 'international mailbox names' in the IMAP protocol
+ * Also known as mUTF-7
+ * Defined in RFC 3501 5.1.3 (https://tools.ietf.org/html/rfc3501)
+ *
+ * Quoting from the RFC:
+ *
+ ***********************************************************************
+ * In modified UTF-7, printable US-ASCII characters, except for "&",
+ * represent themselves; that is, characters with octet values 0x20-0x25
+ * and 0x27-0x7e. The character "&" (0x26) is represented by the
+ * two-octet sequence "&-".
+ *
+ * All other characters (octet values 0x00-0x1f and 0x7f-0xff) are
+ * represented in modified BASE64, with a further modification from
+ * UTF-7 that "," is used instead of "/". Modified BASE64 MUST NOT be
+ * used to represent any printing US-ASCII character which can represent
+ * itself.
+ *
+ * "&" is used to shift to modified BASE64 and "-" to shift back to
+ * US-ASCII. There is no implicit shift from BASE64 to US-ASCII, and
+ * null shifts ("-&" while in BASE64; note that "&-" while in US-ASCII
+ * means "&") are not permitted. However, all names start in US-ASCII,
+ * and MUST end in US-ASCII; that is, a name that ends with a non-ASCII
+ * ISO-10646 character MUST end with a "-").
+ ***********************************************************************
+ *
+ * The purpose of all this is: 1) to keep all parts of IMAP messages 7-bit clean,
+ * 2) to avoid giving special treatment to +, /, \, and ~, since these are
+ * commonly used in mailbox names, and 3) to ensure there is only one
+ * representation of any mailbox name (vanilla UTF-7 does allow multiple
+ * representations of the same string, by Base64-encoding characters which
+ * could have been included as ASCII literals.)
+ *
+ * RFC 2152 also applies, since it defines vanilla UTF-7 (minus IMAP modifications)
+ * The following paragraph is notable:
+ *
+ ***********************************************************************
+ * Unicode is encoded using Modified Base64 by first converting Unicode
+ * 16-bit quantities to an octet stream (with the most significant octet first).
+ * Surrogate pairs (UTF-16) are converted by treating each half of the pair as
+ * a separate 16 bit quantity (i.e., no special treatment). Text with an odd
+ * number of octets is ill-formed. ISO 10646 characters outside the range
+ * addressable via surrogate pairs cannot be encoded.
+ ***********************************************************************
+ *
+ * So after reversing the modified Base64 encoding on an encoded section,
+ * the contents are interpreted as UTF-16BE. */
+
#include "mbfilter.h"
#include "mbfilter_utf7imap.h"
+static const char *mbfl_encoding_utf7imap_aliases[] = {"mUTF-7", NULL};
+
const mbfl_encoding mbfl_encoding_utf7imap = {
mbfl_no_encoding_utf7imap,
"UTF7-IMAP",
NULL,
- NULL,
+ mbfl_encoding_utf7imap_aliases,
NULL,
MBFL_ENCTYPE_MBCS,
&vtbl_utf7imap_wchar,
@@ -106,7 +156,7 @@ int mbfl_filt_conv_utf7imap_wchar(int c, mbfl_convert_filter *filter)
case 0:
if (c == 0x26) { /* '&' shift character */
filter->status++;
- } else if (c >= 0 && c < 0x80) { /* ASCII */
+ } else if (c >= 0x20 && c <= 0x7E) { /* ASCII */
CK((*filter->output_function)(c, filter->data));
} else { /* illegal character */
s = c & MBFL_WCSGROUP_MASK;
@@ -145,7 +195,15 @@ int mbfl_filt_conv_utf7imap_wchar(int c, mbfl_convert_filter *filter)
}
} else {
filter->cache = n;
- CK((*filter->output_function)(s, filter->data));
+ /* Characters which can be expressed as literal, ASCII characters
+ * should not be Base64-encoded */
+ if (s < 0x20 || s > 0x7E || s == '&') {
+ CK((*filter->output_function)(s, filter->data));
+ } else {
+ s &= MBFL_WCSGROUP_MASK;
+ s |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(s, filter->data));
+ }
}
break;
@@ -177,7 +235,15 @@ int mbfl_filt_conv_utf7imap_wchar(int c, mbfl_convert_filter *filter)
}
} else {
filter->cache = n;
- CK((*filter->output_function)(s, filter->data));
+ /* Characters which can be expressed as literal, ASCII characters
+ * should not be Base64-encoded */
+ if (s < 0x20 || s > 0x7E || s == '&') {
+ CK((*filter->output_function)(s, filter->data));
+ } else {
+ s &= MBFL_WCSGROUP_MASK;
+ s |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(s, filter->data));
+ }
}
break;
@@ -204,7 +270,15 @@ int mbfl_filt_conv_utf7imap_wchar(int c, mbfl_convert_filter *filter)
}
} else {
filter->cache = 0;
- CK((*filter->output_function)(s, filter->data));
+ /* Characters which can be expressed as literal, ASCII characters
+ * should not be Base64-encoded */
+ if (s < 0x20 || s > 0x7E || s == '&') {
+ CK((*filter->output_function)(s, filter->data));
+ } else {
+ s &= MBFL_WCSGROUP_MASK;
+ s |= MBFL_WCSGROUP_THROUGH;
+ CK((*filter->output_function)(s, filter->data));
+ }
}
break;
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf8.c b/ext/mbstring/libmbfl/filters/mbfilter_utf8.c
index 9e97d5b069..3b7a76de47 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_utf8.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_utf8.c
@@ -57,7 +57,7 @@ const mbfl_encoding mbfl_encoding_utf8 = {
mbfl_no_encoding_utf8,
"UTF-8",
"UTF-8",
- (const char *(*)[])&mbfl_encoding_utf8_aliases,
+ mbfl_encoding_utf8_aliases,
mblen_table_utf8,
MBFL_ENCTYPE_MBCS,
&vtbl_utf8_wchar,
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.c b/ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.c
index ef8d4cc075..8f50d22781 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.c
@@ -46,7 +46,7 @@ const mbfl_encoding mbfl_encoding_utf8_docomo = {
mbfl_no_encoding_utf8_docomo,
"UTF-8-Mobile#DOCOMO",
"UTF-8",
- (const char *(*)[])&mbfl_encoding_utf8_docomo_aliases,
+ mbfl_encoding_utf8_docomo_aliases,
mblen_table_utf8,
MBFL_ENCTYPE_MBCS,
&vtbl_utf8_docomo_wchar,
@@ -57,7 +57,7 @@ const mbfl_encoding mbfl_encoding_utf8_kddi_a = {
mbfl_no_encoding_utf8_kddi_a,
"UTF-8-Mobile#KDDI-A",
"UTF-8",
- (const char *(*)[])&mbfl_encoding_utf8_kddi_a_aliases,
+ mbfl_encoding_utf8_kddi_a_aliases,
mblen_table_utf8,
MBFL_ENCTYPE_MBCS,
&vtbl_utf8_kddi_a_wchar,
@@ -68,7 +68,7 @@ const mbfl_encoding mbfl_encoding_utf8_kddi_b = {
mbfl_no_encoding_utf8_kddi_b,
"UTF-8-Mobile#KDDI-B",
"UTF-8",
- (const char *(*)[])&mbfl_encoding_utf8_kddi_b_aliases,
+ mbfl_encoding_utf8_kddi_b_aliases,
mblen_table_utf8,
MBFL_ENCTYPE_MBCS,
&vtbl_utf8_kddi_b_wchar,
@@ -79,7 +79,7 @@ const mbfl_encoding mbfl_encoding_utf8_sb = {
mbfl_no_encoding_utf8_sb,
"UTF-8-Mobile#SOFTBANK",
"UTF-8",
- (const char *(*)[])&mbfl_encoding_utf8_sb_aliases,
+ mbfl_encoding_utf8_sb_aliases,
mblen_table_utf8,
MBFL_ENCTYPE_MBCS,
&vtbl_utf8_sb_wchar,
diff --git a/ext/mbstring/libmbfl/filters/unicode_prop.h b/ext/mbstring/libmbfl/filters/unicode_prop.h
index 6eaefbc2e3..1ecf42c556 100644
--- a/ext/mbstring/libmbfl/filters/unicode_prop.h
+++ b/ext/mbstring/libmbfl/filters/unicode_prop.h
@@ -19,148 +19,136 @@
* Suite 330, Boston, MA 02111-1307 USA
*
* The authors of this file: PHP3 Internationalization team
- *
- */
-
-/* character property table */
-#define MBFL_CHP_CTL 0x01
-#define MBFL_CHP_DIGIT 0x02
-#define MBFL_CHP_UALPHA 0x04
-#define MBFL_CHP_LALPHA 0x08
-#define MBFL_CHP_MMHQENC 0x10 /* must Q-encoding in MIME Header encoded-word */
-#define MBFL_CHP_MSPECIAL 0x20 /* RFC822 Special characters */
-
-/*
- * Unicode table
*/
-static const unsigned char mbfl_charprop_table[] = {
-/* NUL 0 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC,
-/* SCH 1 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* SIX 2 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* EIX 3 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* EOT 4 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* ENQ 5 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* ACK 6 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* BEL 7 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* BS 8 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* HI 9 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* LF 10 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* VI 11 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* FF 12 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* CR 13 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* SO 14 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* SI 15 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* SLE 16 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* CSI 17 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* DC2 18 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* DC3 19 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* DC4 20 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* NAK 21 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* SYN 22 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* EIB 23 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* CAN 24 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* EM 25 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* SLB 26 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* ESC 27 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* FS 28 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* GS 29 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* RS 30 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* US 31 */ MBFL_CHP_CTL | MBFL_CHP_MMHQENC ,
-/* SP 32 */ MBFL_CHP_MMHQENC ,
-/* ! 33 */ 0 ,
-/* " 34 */ MBFL_CHP_MMHQENC | MBFL_CHP_MSPECIAL ,
-/* # 35 */ MBFL_CHP_MMHQENC ,
-/* $ 36 */ MBFL_CHP_MMHQENC ,
-/* % 37 */ MBFL_CHP_MMHQENC ,
-/* & 38 */ MBFL_CHP_MMHQENC ,
-/* ' 39 */ MBFL_CHP_MMHQENC ,
-/* ( 40 */ MBFL_CHP_MMHQENC | MBFL_CHP_MSPECIAL ,
-/* ) 41 */ MBFL_CHP_MMHQENC | MBFL_CHP_MSPECIAL ,
-/* * 42 */ 0 ,
-/* + 43 */ 0 ,
-/* , 44 */ MBFL_CHP_MMHQENC | MBFL_CHP_MSPECIAL ,
-/* - 45 */ 0 ,
-/* . 46 */ MBFL_CHP_MMHQENC | MBFL_CHP_MSPECIAL ,
-/* / 47 */ 0 ,
-/* 0 48 */ MBFL_CHP_DIGIT | MBFL_CHP_MMHQENC ,
-/* 1 49 */ MBFL_CHP_DIGIT | MBFL_CHP_MMHQENC ,
-/* 2 50 */ MBFL_CHP_DIGIT | MBFL_CHP_MMHQENC ,
-/* 3 51 */ MBFL_CHP_DIGIT | MBFL_CHP_MMHQENC ,
-/* 4 52 */ MBFL_CHP_DIGIT | MBFL_CHP_MMHQENC ,
-/* 5 53 */ MBFL_CHP_DIGIT | MBFL_CHP_MMHQENC ,
-/* 6 54 */ MBFL_CHP_DIGIT | MBFL_CHP_MMHQENC ,
-/* 7 55 */ MBFL_CHP_DIGIT | MBFL_CHP_MMHQENC ,
-/* 8 56 */ MBFL_CHP_DIGIT | MBFL_CHP_MMHQENC ,
-/* 9 57 */ MBFL_CHP_DIGIT | MBFL_CHP_MMHQENC ,
-/* : 58 */ MBFL_CHP_MMHQENC | MBFL_CHP_MSPECIAL ,
-/* ; 59 */ MBFL_CHP_MMHQENC | MBFL_CHP_MSPECIAL ,
-/* < 60 */ MBFL_CHP_MMHQENC | MBFL_CHP_MSPECIAL ,
-/* = 61 */ 0 ,
-/* > 62 */ MBFL_CHP_MMHQENC | MBFL_CHP_MSPECIAL ,
-/* ? 63 */ MBFL_CHP_MMHQENC ,
-/* @ 64 */ MBFL_CHP_MMHQENC | MBFL_CHP_MSPECIAL ,
-/* A 65 */ MBFL_CHP_UALPHA ,
-/* B 66 */ MBFL_CHP_UALPHA ,
-/* C 67 */ MBFL_CHP_UALPHA ,
-/* D 68 */ MBFL_CHP_UALPHA ,
-/* E 69 */ MBFL_CHP_UALPHA ,
-/* F 70 */ MBFL_CHP_UALPHA ,
-/* G 71 */ MBFL_CHP_UALPHA ,
-/* H 72 */ MBFL_CHP_UALPHA ,
-/* I 73 */ MBFL_CHP_UALPHA ,
-/* J 74 */ MBFL_CHP_UALPHA ,
-/* K 75 */ MBFL_CHP_UALPHA ,
-/* L 76 */ MBFL_CHP_UALPHA ,
-/* M 77 */ MBFL_CHP_UALPHA ,
-/* N 78 */ MBFL_CHP_UALPHA ,
-/* O 79 */ MBFL_CHP_UALPHA ,
-/* P 80 */ MBFL_CHP_UALPHA ,
-/* Q 81 */ MBFL_CHP_UALPHA ,
-/* R 82 */ MBFL_CHP_UALPHA ,
-/* S 83 */ MBFL_CHP_UALPHA ,
-/* T 84 */ MBFL_CHP_UALPHA ,
-/* U 85 */ MBFL_CHP_UALPHA ,
-/* V 86 */ MBFL_CHP_UALPHA ,
-/* W 87 */ MBFL_CHP_UALPHA ,
-/* X 88 */ MBFL_CHP_UALPHA ,
-/* Y 89 */ MBFL_CHP_UALPHA ,
-/* Z 90 */ MBFL_CHP_UALPHA ,
-/* [ 91 */ MBFL_CHP_MMHQENC | MBFL_CHP_MSPECIAL ,
-/* \ 92 */ MBFL_CHP_MMHQENC | MBFL_CHP_MSPECIAL ,
-/* ] 93 */ MBFL_CHP_MMHQENC | MBFL_CHP_MSPECIAL ,
-/* ^ 94 */ MBFL_CHP_MMHQENC ,
-/* _ 95 */ MBFL_CHP_MMHQENC ,
-/* ` 96 */ MBFL_CHP_MMHQENC ,
-/* a 97 */ MBFL_CHP_LALPHA ,
-/* b 98 */ MBFL_CHP_LALPHA ,
-/* c 99 */ MBFL_CHP_LALPHA ,
-/* d 100 */ MBFL_CHP_LALPHA ,
-/* e 101 */ MBFL_CHP_LALPHA ,
-/* f 102 */ MBFL_CHP_LALPHA ,
-/* g 103 */ MBFL_CHP_LALPHA ,
-/* h 104 */ MBFL_CHP_LALPHA ,
-/* i 105 */ MBFL_CHP_LALPHA ,
-/* j 106 */ MBFL_CHP_LALPHA ,
-/* k 107 */ MBFL_CHP_LALPHA ,
-/* l 108 */ MBFL_CHP_LALPHA ,
-/* m 109 */ MBFL_CHP_LALPHA ,
-/* n 110 */ MBFL_CHP_LALPHA ,
-/* o 111 */ MBFL_CHP_LALPHA ,
-/* p 112 */ MBFL_CHP_LALPHA ,
-/* q 113 */ MBFL_CHP_LALPHA ,
-/* r 114 */ MBFL_CHP_LALPHA ,
-/* s 115 */ MBFL_CHP_LALPHA ,
-/* t 116 */ MBFL_CHP_LALPHA ,
-/* u 117 */ MBFL_CHP_LALPHA ,
-/* v 118 */ MBFL_CHP_LALPHA ,
-/* w 119 */ MBFL_CHP_LALPHA ,
-/* x 120 */ MBFL_CHP_LALPHA ,
-/* y 121 */ MBFL_CHP_LALPHA ,
-/* z 122 */ MBFL_CHP_LALPHA ,
-/* { 123 */ MBFL_CHP_MMHQENC ,
-/* | 124 */ MBFL_CHP_MMHQENC ,
-/* } 125 */ MBFL_CHP_MMHQENC ,
-/* ~ 126 */ MBFL_CHP_MMHQENC ,
-/* DEL 127 */ MBFL_CHP_MMHQENC
+/* Should we use QPrint-encoding in MIME Header encoded-word? */
+static const unsigned char mime_char_needs_qencode[] = {
+/* NUL 0 */ 1,
+/* SCH 1 */ 1,
+/* SIX 2 */ 1,
+/* EIX 3 */ 1,
+/* EOT 4 */ 1,
+/* ENQ 5 */ 1,
+/* ACK 6 */ 1,
+/* BEL 7 */ 1,
+/* BS 8 */ 1,
+/* HI 9 */ 1,
+/* LF 10 */ 1,
+/* VI 11 */ 1,
+/* FF 12 */ 1,
+/* CR 13 */ 1,
+/* SO 14 */ 1,
+/* SI 15 */ 1,
+/* SLE 16 */ 1,
+/* CSI 17 */ 1,
+/* DC2 18 */ 1,
+/* DC3 19 */ 1,
+/* DC4 20 */ 1,
+/* NAK 21 */ 1,
+/* SYN 22 */ 1,
+/* EIB 23 */ 1,
+/* CAN 24 */ 1,
+/* EM 25 */ 1,
+/* SLB 26 */ 1,
+/* ESC 27 */ 1,
+/* FS 28 */ 1,
+/* GS 29 */ 1,
+/* RS 30 */ 1,
+/* US 31 */ 1,
+/* SP 32 */ 1,
+/* ! 33 */ 0,
+/* " 34 */ 1,
+/* # 35 */ 1,
+/* $ 36 */ 1,
+/* % 37 */ 1,
+/* & 38 */ 1,
+/* ' 39 */ 1,
+/* ( 40 */ 1,
+/* ) 41 */ 1,
+/* * 42 */ 0,
+/* + 43 */ 0,
+/* , 44 */ 1,
+/* - 45 */ 0,
+/* . 46 */ 1,
+/* / 47 */ 0,
+/* 0 48 */ 1,
+/* 1 49 */ 1,
+/* 2 50 */ 1,
+/* 3 51 */ 1,
+/* 4 52 */ 1,
+/* 5 53 */ 1,
+/* 6 54 */ 1,
+/* 7 55 */ 1,
+/* 8 56 */ 1,
+/* 9 57 */ 1,
+/* : 58 */ 1,
+/* ; 59 */ 1,
+/* < 60 */ 1,
+/* = 61 */ 0,
+/* > 62 */ 1,
+/* ? 63 */ 1,
+/* @ 64 */ 1,
+/* A 65 */ 0,
+/* B 66 */ 0,
+/* C 67 */ 0,
+/* D 68 */ 0,
+/* E 69 */ 0,
+/* F 70 */ 0,
+/* G 71 */ 0,
+/* H 72 */ 0,
+/* I 73 */ 0,
+/* J 74 */ 0,
+/* K 75 */ 0,
+/* L 76 */ 0,
+/* M 77 */ 0,
+/* N 78 */ 0,
+/* O 79 */ 0,
+/* P 80 */ 0,
+/* Q 81 */ 0,
+/* R 82 */ 0,
+/* S 83 */ 0,
+/* T 84 */ 0,
+/* U 85 */ 0,
+/* V 86 */ 0,
+/* W 87 */ 0,
+/* X 88 */ 0,
+/* Y 89 */ 0,
+/* Z 90 */ 0,
+/* [ 91 */ 1,
+/* \ 92 */ 1,
+/* ] 93 */ 1,
+/* ^ 94 */ 1,
+/* _ 95 */ 1,
+/* ` 96 */ 1,
+/* a 97 */ 0,
+/* b 98 */ 0,
+/* c 99 */ 0,
+/* d 100 */ 0,
+/* e 101 */ 0,
+/* f 102 */ 0,
+/* g 103 */ 0,
+/* h 104 */ 0,
+/* i 105 */ 0,
+/* j 106 */ 0,
+/* k 107 */ 0,
+/* l 108 */ 0,
+/* m 109 */ 0,
+/* n 110 */ 0,
+/* o 111 */ 0,
+/* p 112 */ 0,
+/* q 113 */ 0,
+/* r 114 */ 0,
+/* s 115 */ 0,
+/* t 116 */ 0,
+/* u 117 */ 0,
+/* v 118 */ 0,
+/* w 119 */ 0,
+/* x 120 */ 0,
+/* y 121 */ 0,
+/* z 122 */ 0,
+/* { 123 */ 1,
+/* | 124 */ 1,
+/* } 125 */ 1,
+/* ~ 126 */ 1,
+/* DEL 127 */ 1
};
diff --git a/ext/mbstring/libmbfl/mbfl/mbfilter.c b/ext/mbstring/libmbfl/mbfl/mbfilter.c
index 793dd8e078..68cb39fa90 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfilter.c
+++ b/ext/mbstring/libmbfl/mbfl/mbfilter.c
@@ -200,7 +200,6 @@ size_t mbfl_buffer_converter_feed(mbfl_buffer_converter *convd, mbfl_string *str
size_t n;
unsigned char *p;
mbfl_convert_filter *filter;
- int (*filter_function)(int c, mbfl_convert_filter *filter);
ZEND_ASSERT(convd);
ZEND_ASSERT(string);
@@ -212,9 +211,8 @@ size_t mbfl_buffer_converter_feed(mbfl_buffer_converter *convd, mbfl_string *str
filter = convd->filter1;
if (filter != NULL) {
- filter_function = filter->filter_function;
while (n > 0) {
- if ((*filter_function)(*p++, filter) < 0) {
+ if ((*filter->filter_function)(*p++, filter) < 0) {
return p - string->val;
}
n--;
@@ -396,18 +394,6 @@ const mbfl_encoding *mbfl_encoding_detector_judge(mbfl_encoding_detector *identd
}
n--;
}
-
- /* fallback judge */
- if (!encoding) {
- n = identd->filter_list_size - 1;
- while (n >= 0) {
- filter = identd->filter_list[n];
- if (!filter->flag) {
- encoding = filter->encoding;
- }
- n--;
- }
- }
}
return encoding;
@@ -486,7 +472,7 @@ mbfl_convert_encoding(
const mbfl_encoding *
mbfl_identify_encoding(mbfl_string *string, const mbfl_encoding **elist, int elistsz, int strict)
{
- int i, num, bad;
+ int i, bad;
size_t n;
unsigned char *p;
mbfl_identify_filter *flist, *filter;
@@ -495,12 +481,9 @@ mbfl_identify_encoding(mbfl_string *string, const mbfl_encoding **elist, int eli
/* flist is an array of mbfl_identify_filter instances */
flist = ecalloc(elistsz, sizeof(mbfl_identify_filter));
- num = 0;
if (elist != NULL) {
for (i = 0; i < elistsz; i++) {
- if (!mbfl_identify_filter_init2(&flist[num], elist[i])) {
- num++;
- }
+ mbfl_identify_filter_init2(&flist[i], elist[i]);
}
}
@@ -511,7 +494,7 @@ mbfl_identify_encoding(mbfl_string *string, const mbfl_encoding **elist, int eli
if (p != NULL) {
bad = 0;
while (n > 0) {
- for (i = 0; i < num; i++) {
+ for (i = 0; i < elistsz; i++) {
filter = &flist[i];
if (!filter->flag) {
(*filter->filter_function)(*p, filter);
@@ -520,7 +503,7 @@ mbfl_identify_encoding(mbfl_string *string, const mbfl_encoding **elist, int eli
}
}
}
- if ((num - 1) <= bad && !strict) {
+ if ((elistsz - 1) <= bad && !strict) {
break;
}
p++;
@@ -531,7 +514,7 @@ mbfl_identify_encoding(mbfl_string *string, const mbfl_encoding **elist, int eli
/* judge */
encoding = NULL;
- for (i = 0; i < num; i++) {
+ for (i = 0; i < elistsz; i++) {
filter = &flist[i];
if (!filter->flag) {
if (strict && filter->status) {
@@ -544,7 +527,7 @@ mbfl_identify_encoding(mbfl_string *string, const mbfl_encoding **elist, int eli
/* fall-back judge */
if (!encoding) {
- for (i = 0; i < num; i++) {
+ for (i = 0; i < elistsz; i++) {
filter = &flist[i];
if (!filter->flag && (!strict || !filter->status)) {
encoding = filter->encoding;
diff --git a/ext/mbstring/libmbfl/mbfl/mbfilter_8bit.c b/ext/mbstring/libmbfl/mbfl/mbfilter_8bit.c
index f4c74946c1..41081aa883 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfilter_8bit.c
+++ b/ext/mbstring/libmbfl/mbfl/mbfilter_8bit.c
@@ -43,13 +43,19 @@ const mbfl_encoding mbfl_encoding_8bit = {
mbfl_no_encoding_8bit,
"8bit",
"8bit",
- (const char *(*)[])&mbfl_encoding_8bit_aliases,
+ mbfl_encoding_8bit_aliases,
NULL,
MBFL_ENCTYPE_SBCS,
&vtbl_8bit_wchar,
&vtbl_wchar_8bit
};
+const struct mbfl_identify_vtbl vtbl_identify_8bit = {
+ mbfl_no_encoding_8bit,
+ mbfl_filt_ident_common_ctor,
+ mbfl_filt_ident_true
+};
+
const struct mbfl_convert_vtbl vtbl_8bit_wchar = {
mbfl_no_encoding_8bit,
mbfl_no_encoding_wchar,
diff --git a/ext/mbstring/libmbfl/mbfl/mbfilter_8bit.h b/ext/mbstring/libmbfl/mbfl/mbfilter_8bit.h
index acdf640fd7..64369b999d 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfilter_8bit.h
+++ b/ext/mbstring/libmbfl/mbfl/mbfilter_8bit.h
@@ -35,5 +35,6 @@
#include "mbfilter.h"
MBFLAPI extern const mbfl_encoding mbfl_encoding_8bit;
+extern const struct mbfl_identify_vtbl vtbl_identify_8bit;
#endif /* MBFL_MBFILTER_8BIT_H */
diff --git a/ext/mbstring/libmbfl/mbfl/mbfilter_pass.c b/ext/mbstring/libmbfl/mbfl/mbfilter_pass.c
index 3d7cffe9c1..e43f746ecc 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfilter_pass.c
+++ b/ext/mbstring/libmbfl/mbfl/mbfilter_pass.c
@@ -38,7 +38,7 @@ const mbfl_encoding mbfl_encoding_pass = {
mbfl_no_encoding_pass,
"pass",
NULL,
- (const char *(*)[])&mbfl_encoding_pass_aliases,
+ mbfl_encoding_pass_aliases,
NULL,
0,
NULL,
diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_convert.c b/ext/mbstring/libmbfl/mbfl/mbfl_convert.c
index 6a46c2b541..af6a3bba93 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfl_convert.c
+++ b/ext/mbstring/libmbfl/mbfl/mbfl_convert.c
@@ -136,7 +136,7 @@ static void mbfl_convert_filter_common_init(mbfl_convert_filter *filter, const m
filter->filter_ctor = vtbl->filter_ctor;
filter->filter_dtor = vtbl->filter_dtor;
filter->filter_function = vtbl->filter_function;
- filter->filter_flush = vtbl->filter_flush;
+ filter->filter_flush = (filter_flush_t)vtbl->filter_flush;
filter->filter_copy = vtbl->filter_copy;
(*filter->filter_ctor)(filter);
diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_encoding.c b/ext/mbstring/libmbfl/mbfl/mbfl_encoding.c
index 3ecb06553d..f740f7aec1 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfl_encoding.c
+++ b/ext/mbstring/libmbfl/mbfl/mbfl_encoding.c
@@ -199,44 +199,32 @@ static const mbfl_encoding *mbfl_encoding_ptr_list[] = {
NULL
};
-/* encoding resolver */
-const mbfl_encoding *
-mbfl_name2encoding(const char *name)
+const mbfl_encoding *mbfl_name2encoding(const char *name)
{
- const mbfl_encoding *encoding;
- int i, j;
+ const mbfl_encoding **encoding;
- if (name == NULL) {
- return NULL;
- }
-
- i = 0;
- while ((encoding = mbfl_encoding_ptr_list[i++]) != NULL){
- if (strcasecmp(encoding->name, name) == 0) {
- return encoding;
+ for (encoding = mbfl_encoding_ptr_list; *encoding; encoding++) {
+ if (strcasecmp((*encoding)->name, name) == 0) {
+ return *encoding;
}
}
- /* serch MIME charset name */
- i = 0;
- while ((encoding = mbfl_encoding_ptr_list[i++]) != NULL) {
- if (encoding->mime_name != NULL) {
- if (strcasecmp(encoding->mime_name, name) == 0) {
- return encoding;
+ /* search MIME charset name */
+ for (encoding = mbfl_encoding_ptr_list; *encoding; encoding++) {
+ if ((*encoding)->mime_name) {
+ if (strcasecmp((*encoding)->mime_name, name) == 0) {
+ return *encoding;
}
}
}
- /* serch aliases */
- i = 0;
- while ((encoding = mbfl_encoding_ptr_list[i++]) != NULL) {
- if (encoding->aliases != NULL) {
- j = 0;
- while ((*encoding->aliases)[j] != NULL) {
- if (strcasecmp((*encoding->aliases)[j], name) == 0) {
- return encoding;
+ /* search aliases */
+ for (encoding = mbfl_encoding_ptr_list; *encoding; encoding++) {
+ if ((*encoding)->aliases) {
+ for (const char **alias = (*encoding)->aliases; *alias; alias++) {
+ if (strcasecmp(*alias, name) == 0) {
+ return *encoding;
}
- j++;
}
}
}
@@ -244,63 +232,45 @@ mbfl_name2encoding(const char *name)
return NULL;
}
-const mbfl_encoding *
-mbfl_no2encoding(enum mbfl_no_encoding no_encoding)
+const mbfl_encoding *mbfl_no2encoding(enum mbfl_no_encoding no_encoding)
{
- const mbfl_encoding *encoding;
- int i;
+ const mbfl_encoding **encoding;
- i = 0;
- while ((encoding = mbfl_encoding_ptr_list[i++]) != NULL){
- if (encoding->no_encoding == no_encoding) {
- return encoding;
+ for (encoding = mbfl_encoding_ptr_list; *encoding; encoding++) {
+ if ((*encoding)->no_encoding == no_encoding) {
+ return *encoding;
}
}
return NULL;
}
-enum mbfl_no_encoding
-mbfl_name2no_encoding(const char *name)
+enum mbfl_no_encoding mbfl_name2no_encoding(const char *name)
{
- const mbfl_encoding *encoding;
-
- encoding = mbfl_name2encoding(name);
- if (encoding == NULL) {
- return mbfl_no_encoding_invalid;
- } else {
- return encoding->no_encoding;
- }
+ const mbfl_encoding *encoding = mbfl_name2encoding(name);
+ return encoding ? encoding->no_encoding : mbfl_no_encoding_invalid;
}
-const char *
-mbfl_no_encoding2name(enum mbfl_no_encoding no_encoding)
+const char *mbfl_no_encoding2name(enum mbfl_no_encoding no_encoding)
{
- const mbfl_encoding *encoding;
-
- encoding = mbfl_no2encoding(no_encoding);
- if (encoding == NULL) {
- return "";
- } else {
- return encoding->name;
- }
+ const mbfl_encoding *encoding = mbfl_no2encoding(no_encoding);
+ return encoding ? encoding->name : "";
}
-const mbfl_encoding **
-mbfl_get_supported_encodings(void)
+const mbfl_encoding **mbfl_get_supported_encodings(void)
{
return mbfl_encoding_ptr_list;
}
-const char *
-mbfl_no2preferred_mime_name(enum mbfl_no_encoding no_encoding)
+const char *mbfl_no2preferred_mime_name(enum mbfl_no_encoding no_encoding)
{
- const mbfl_encoding *encoding;
+ return mbfl_encoding_preferred_mime_name(mbfl_no2encoding(no_encoding));
+}
- encoding = mbfl_no2encoding(no_encoding);
- if (encoding != NULL && encoding->mime_name != NULL && encoding->mime_name[0] != '\0') {
+const char *mbfl_encoding_preferred_mime_name(const mbfl_encoding *encoding)
+{
+ if (encoding->mime_name && encoding->mime_name[0] != '\0') {
return encoding->mime_name;
- } else {
- return NULL;
}
+ return NULL;
}
diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_encoding.h b/ext/mbstring/libmbfl/mbfl/mbfl_encoding.h
index 0b39153c9d..f945b5dd03 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfl_encoding.h
+++ b/ext/mbstring/libmbfl/mbfl/mbfl_encoding.h
@@ -145,19 +145,19 @@ typedef struct _mbfl_encoding {
enum mbfl_no_encoding no_encoding;
const char *name;
const char *mime_name;
- const char *(*aliases)[];
+ const char **aliases;
const unsigned char *mblen_table;
unsigned int flag;
const struct mbfl_convert_vtbl *input_filter;
const struct mbfl_convert_vtbl *output_filter;
} mbfl_encoding;
-MBFLAPI extern const mbfl_encoding * mbfl_name2encoding(const char *name);
-MBFLAPI extern const mbfl_encoding * mbfl_no2encoding(enum mbfl_no_encoding no_encoding);
+MBFLAPI extern const mbfl_encoding *mbfl_name2encoding(const char *name);
+MBFLAPI extern const mbfl_encoding *mbfl_no2encoding(enum mbfl_no_encoding no_encoding);
MBFLAPI extern enum mbfl_no_encoding mbfl_name2no_encoding(const char *name);
-MBFLAPI extern const mbfl_encoding ** mbfl_get_supported_encodings();
-MBFLAPI extern const char * mbfl_no_encoding2name(enum mbfl_no_encoding no_encoding);
-MBFLAPI extern const char * mbfl_no2preferred_mime_name(enum mbfl_no_encoding no_encoding);
-
+MBFLAPI extern const mbfl_encoding **mbfl_get_supported_encodings();
+MBFLAPI extern const char *mbfl_no_encoding2name(enum mbfl_no_encoding no_encoding);
+MBFLAPI extern const char *mbfl_no2preferred_mime_name(enum mbfl_no_encoding no_encoding);
+MBFLAPI extern const char *mbfl_encoding_preferred_mime_name(const mbfl_encoding *encoding);
#endif /* MBFL_ENCODING_H */
diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_ident.c b/ext/mbstring/libmbfl/mbfl/mbfl_ident.c
index 18144eb030..a48762ee3d 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfl_ident.c
+++ b/ext/mbstring/libmbfl/mbfl/mbfl_ident.c
@@ -78,6 +78,7 @@
#include "filters/mbfilter_iso8859_13.h"
#include "filters/mbfilter_iso8859_14.h"
#include "filters/mbfilter_iso8859_15.h"
+#include "filters/mbfilter_iso8859_16.h"
#include "filters/mbfilter_base64.h"
#include "filters/mbfilter_qprint.h"
#include "filters/mbfilter_uuencode.h"
@@ -152,6 +153,7 @@ static const struct mbfl_identify_vtbl *mbfl_identify_filter_list[] = {
&vtbl_identify_8859_13,
&vtbl_identify_8859_14,
&vtbl_identify_8859_15,
+ &vtbl_identify_8859_16,
&vtbl_identify_armscii8,
&vtbl_identify_cp850,
&vtbl_identify_jis_ms,
@@ -159,97 +161,82 @@ static const struct mbfl_identify_vtbl *mbfl_identify_filter_list[] = {
&vtbl_identify_cp50221,
&vtbl_identify_cp50222,
&vtbl_identify_gb18030,
+ &vtbl_identify_7bit,
+ &vtbl_identify_utf16,
+ &vtbl_identify_utf16le,
+ &vtbl_identify_utf16be,
+ &vtbl_identify_8bit,
+ &vtbl_identify_ucs2,
+ &vtbl_identify_ucs2be,
+ &vtbl_identify_ucs2le,
+ &vtbl_identify_utf32,
+ &vtbl_identify_utf32be,
+ &vtbl_identify_utf32le,
&vtbl_identify_false,
NULL
};
-/*
- * identify filter
- */
-const struct mbfl_identify_vtbl * mbfl_identify_filter_get_vtbl(enum mbfl_no_encoding encoding)
+const struct mbfl_identify_vtbl* mbfl_identify_filter_get_vtbl(enum mbfl_no_encoding encoding)
{
- const struct mbfl_identify_vtbl * vtbl;
- int i;
+ const struct mbfl_identify_vtbl** vtbl;
- i = 0;
- while ((vtbl = mbfl_identify_filter_list[i++]) != NULL) {
- if (vtbl->encoding == encoding) {
- break;
+ for (vtbl = mbfl_identify_filter_list; *vtbl; vtbl++) {
+ if ((*vtbl)->encoding == encoding) {
+ return *vtbl;
}
}
- return vtbl;
+ return NULL;
}
mbfl_identify_filter *mbfl_identify_filter_new(enum mbfl_no_encoding encoding)
{
mbfl_identify_filter *filter = emalloc(sizeof(mbfl_identify_filter));
- if (mbfl_identify_filter_init(filter, encoding)) {
- efree(filter);
- return NULL;
- }
-
+ mbfl_identify_filter_init(filter, encoding);
return filter;
}
mbfl_identify_filter *mbfl_identify_filter_new2(const mbfl_encoding *encoding)
{
mbfl_identify_filter *filter = emalloc(sizeof(mbfl_identify_filter));
- if (mbfl_identify_filter_init2(filter, encoding)) {
- efree(filter);
- return NULL;
- }
-
+ mbfl_identify_filter_init2(filter, encoding);
return filter;
}
-
-int mbfl_identify_filter_init(mbfl_identify_filter *filter, enum mbfl_no_encoding encoding)
+void mbfl_identify_filter_init(mbfl_identify_filter *filter, enum mbfl_no_encoding encoding)
{
const mbfl_encoding *enc = mbfl_no2encoding(encoding);
- return mbfl_identify_filter_init2(filter, enc ? enc: &mbfl_encoding_pass);
+ mbfl_identify_filter_init2(filter, enc ? enc : &mbfl_encoding_pass);
}
-int mbfl_identify_filter_init2(mbfl_identify_filter *filter, const mbfl_encoding *encoding)
+void mbfl_identify_filter_init2(mbfl_identify_filter *filter, const mbfl_encoding *encoding)
{
- const struct mbfl_identify_vtbl *vtbl;
-
- /* encoding structure */
filter->encoding = encoding;
-
- filter->status = 0;
- filter->flag = 0;
- filter->score = 0;
+ filter->status = filter->flag = filter->score = 0;
/* setup the function table */
- vtbl = mbfl_identify_filter_get_vtbl(filter->encoding->no_encoding);
+ const struct mbfl_identify_vtbl *vtbl = mbfl_identify_filter_get_vtbl(filter->encoding->no_encoding);
if (vtbl == NULL) {
vtbl = &vtbl_identify_false;
}
filter->filter_ctor = vtbl->filter_ctor;
filter->filter_function = vtbl->filter_function;
- /* constructor */
(*filter->filter_ctor)(filter);
-
- return 0;
}
void mbfl_identify_filter_delete(mbfl_identify_filter *filter)
{
- if (filter == NULL) {
- return;
- }
-
- efree((void*)filter);
+ efree(filter);
}
void mbfl_filt_ident_common_ctor(mbfl_identify_filter *filter)
{
- filter->status = 0;
- filter->flag = 0;
+ filter->status = filter->flag = 0;
}
+/* A (useless) filter which says that _every_ string is invalid in a certain encoding.
+ * Obviously, that cannot be true. Remove after all encodings have proper identify filters */
int mbfl_filt_ident_false(int c, mbfl_identify_filter *filter)
{
filter->flag = 1; /* bad */
@@ -262,6 +249,7 @@ void mbfl_filt_ident_false_ctor(mbfl_identify_filter *filter)
filter->flag = 1;
}
+/* For encodings in which _every_ possible input string is valid */
int mbfl_filt_ident_true(int c, mbfl_identify_filter *filter)
{
return c;
diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_ident.h b/ext/mbstring/libmbfl/mbfl/mbfl_ident.h
index c9afd03fb4..39be183ef3 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfl_ident.h
+++ b/ext/mbstring/libmbfl/mbfl/mbfl_ident.h
@@ -58,8 +58,8 @@ MBFLAPI extern const struct mbfl_identify_vtbl * mbfl_identify_filter_get_vtbl(e
MBFLAPI extern mbfl_identify_filter * mbfl_identify_filter_new(enum mbfl_no_encoding encoding);
MBFLAPI extern mbfl_identify_filter * mbfl_identify_filter_new2(const mbfl_encoding *encoding);
MBFLAPI extern void mbfl_identify_filter_delete(mbfl_identify_filter *filter);
-MBFLAPI extern int mbfl_identify_filter_init(mbfl_identify_filter *filter, enum mbfl_no_encoding encoding);
-MBFLAPI extern int mbfl_identify_filter_init2(mbfl_identify_filter *filter, const mbfl_encoding *encoding);
+MBFLAPI extern void mbfl_identify_filter_init(mbfl_identify_filter *filter, enum mbfl_no_encoding encoding);
+MBFLAPI extern void mbfl_identify_filter_init2(mbfl_identify_filter *filter, const mbfl_encoding *encoding);
MBFLAPI extern void mbfl_filt_ident_common_ctor(mbfl_identify_filter *filter);
MBFLAPI extern void mbfl_filt_ident_false_ctor(mbfl_identify_filter *filter);
diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_memory_device.c b/ext/mbstring/libmbfl/mbfl/mbfl_memory_device.c
index 09746efcd0..cd064e5ee8 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfl_memory_device.c
+++ b/ext/mbstring/libmbfl/mbfl/mbfl_memory_device.c
@@ -37,106 +37,67 @@
/*
* memory device output functions
*/
-void
-mbfl_memory_device_init(mbfl_memory_device *device, size_t initsz, size_t allocsz)
+void mbfl_memory_device_init(mbfl_memory_device *device, size_t initsz, size_t allocsz)
{
- if (device) {
- device->length = 0;
- device->buffer = NULL;
- if (initsz > 0) {
- device->buffer = emalloc(initsz);
- device->length = initsz;
- }
- device->pos = 0;
- if (allocsz > MBFL_MEMORY_DEVICE_ALLOC_SIZE) {
- device->allocsz = allocsz;
- } else {
- device->allocsz = MBFL_MEMORY_DEVICE_ALLOC_SIZE;
- }
- }
+ device->buffer = (initsz > 0) ? emalloc(initsz) : NULL;
+ device->length = initsz;
+ device->pos = 0;
+ device->allocsz = MAX(allocsz, MBFL_MEMORY_DEVICE_ALLOC_SIZE);
}
-void
-mbfl_memory_device_realloc(mbfl_memory_device *device, size_t initsz, size_t allocsz)
+void mbfl_memory_device_realloc(mbfl_memory_device *device, size_t initsz, size_t allocsz)
{
- if (device) {
- if (initsz > device->length) {
- device->buffer = erealloc(device->buffer, initsz);
- device->length = initsz;
- }
- if (allocsz > MBFL_MEMORY_DEVICE_ALLOC_SIZE) {
- device->allocsz = allocsz;
- } else {
- device->allocsz = MBFL_MEMORY_DEVICE_ALLOC_SIZE;
- }
+ if (initsz > device->length) {
+ device->buffer = erealloc(device->buffer, initsz);
+ device->length = initsz;
}
+ device->allocsz = MAX(allocsz, MBFL_MEMORY_DEVICE_ALLOC_SIZE);
}
-void
-mbfl_memory_device_clear(mbfl_memory_device *device)
+void mbfl_memory_device_clear(mbfl_memory_device *device)
{
- if (device) {
- if (device->buffer) {
- efree(device->buffer);
- }
- device->buffer = NULL;
- device->length = 0;
- device->pos = 0;
+ if (device->buffer) {
+ efree(device->buffer);
}
+ device->buffer = NULL;
+ device->length = device->pos = 0;
}
-void
-mbfl_memory_device_reset(mbfl_memory_device *device)
+void mbfl_memory_device_reset(mbfl_memory_device *device)
{
- if (device) {
- device->pos = 0;
- }
+ device->pos = 0;
}
-void
-mbfl_memory_device_unput(mbfl_memory_device *device)
+void mbfl_memory_device_unput(mbfl_memory_device *device)
{
if (device->pos > 0) {
device->pos--;
}
}
-mbfl_string *
-mbfl_memory_device_result(mbfl_memory_device *device, mbfl_string *result)
+mbfl_string* mbfl_memory_device_result(mbfl_memory_device *device, mbfl_string *result)
{
- if (device && result) {
- result->len = device->pos;
- mbfl_memory_device_output('\0', device);
- result->val = device->buffer;
- device->buffer = NULL;
- device->length = 0;
- device->pos= 0;
- if (result->val == NULL) {
- result->len = 0;
- result = NULL;
- }
- } else {
- result = NULL;
- }
-
+ result->len = device->pos;
+ mbfl_memory_device_output('\0', device);
+ result->val = device->buffer;
+ device->buffer = NULL;
+ device->length = device->pos = 0;
return result;
}
-int
-mbfl_memory_device_output(int c, void *data)
+int mbfl_memory_device_output(int c, void *data)
{
mbfl_memory_device *device = (mbfl_memory_device *)data;
if (device->pos >= device->length) {
/* reallocate buffer */
- size_t newlen;
if (device->length > SIZE_MAX - device->allocsz) {
/* overflow */
return -1;
}
- newlen = device->length + device->allocsz;
+ size_t newlen = device->length + device->allocsz;
device->buffer = erealloc(device->buffer, newlen);
device->length = newlen;
}
@@ -145,20 +106,15 @@ mbfl_memory_device_output(int c, void *data)
return c;
}
-int
-mbfl_memory_device_strcat(mbfl_memory_device *device, const char *psrc)
+int mbfl_memory_device_strcat(mbfl_memory_device *device, const char *psrc)
{
return mbfl_memory_device_strncat(device, psrc, strlen(psrc));
}
-int
-mbfl_memory_device_strncat(mbfl_memory_device *device, const char *psrc, size_t len)
+int mbfl_memory_device_strncat(mbfl_memory_device *device, const char *psrc, size_t len)
{
- unsigned char *w;
-
if (len > device->length - device->pos) {
/* reallocate buffer */
- size_t newlen;
if (len > SIZE_MAX - MBFL_MEMORY_DEVICE_ALLOC_SIZE
|| device->length > SIZE_MAX - (len + MBFL_MEMORY_DEVICE_ALLOC_SIZE)) {
@@ -166,50 +122,41 @@ mbfl_memory_device_strncat(mbfl_memory_device *device, const char *psrc, size_t
return -1;
}
- newlen = device->length + len + MBFL_MEMORY_DEVICE_ALLOC_SIZE;
+ size_t newlen = device->length + len + MBFL_MEMORY_DEVICE_ALLOC_SIZE;
device->buffer = erealloc(device->buffer, newlen);
device->length = newlen;
}
- w = &device->buffer[device->pos];
+ unsigned char *w = &device->buffer[device->pos];
memcpy(w, psrc, len);
device->pos += len;
return 0;
}
-int
-mbfl_memory_device_devcat(mbfl_memory_device *dest, mbfl_memory_device *src)
+int mbfl_memory_device_devcat(mbfl_memory_device *dest, mbfl_memory_device *src)
{
- return mbfl_memory_device_strncat(dest, (const char *) src->buffer, src->pos);
+ return mbfl_memory_device_strncat(dest, (const char*)src->buffer, src->pos);
}
-void
-mbfl_wchar_device_init(mbfl_wchar_device *device)
+void mbfl_wchar_device_init(mbfl_wchar_device *device)
{
- if (device) {
- device->buffer = NULL;
- device->length = 0;
- device->pos= 0;
- device->allocsz = MBFL_MEMORY_DEVICE_ALLOC_SIZE;
- }
+ device->buffer = NULL;
+ device->length = 0;
+ device->pos = 0;
+ device->allocsz = MBFL_MEMORY_DEVICE_ALLOC_SIZE;
}
-void
-mbfl_wchar_device_clear(mbfl_wchar_device *device)
+void mbfl_wchar_device_clear(mbfl_wchar_device *device)
{
- if (device) {
- if (device->buffer) {
- efree(device->buffer);
- }
- device->buffer = NULL;
- device->length = 0;
- device->pos = 0;
+ if (device->buffer) {
+ efree(device->buffer);
}
+ device->buffer = NULL;
+ device->length = device->pos = 0;
}
-int
-mbfl_wchar_device_output(int c, void *data)
+int mbfl_wchar_device_output(int c, void *data)
{
mbfl_wchar_device *device = (mbfl_wchar_device *)data;
@@ -228,11 +175,10 @@ mbfl_wchar_device_output(int c, void *data)
return -1;
}
- device->buffer = erealloc(device->buffer, newlen*sizeof(int));
+ device->buffer = erealloc(device->buffer, newlen * sizeof(int));
device->length = newlen;
}
device->buffer[device->pos++] = c;
-
return c;
}
diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_memory_device.h b/ext/mbstring/libmbfl/mbfl/mbfl_memory_device.h
index 7e86db3e06..b8a188ec84 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfl_memory_device.h
+++ b/ext/mbstring/libmbfl/mbfl/mbfl_memory_device.h
@@ -69,6 +69,4 @@ MBFLAPI extern void mbfl_wchar_device_init(mbfl_wchar_device *device);
MBFLAPI extern int mbfl_wchar_device_output(int c, void *data);
MBFLAPI extern void mbfl_wchar_device_clear(mbfl_wchar_device *device);
-
-
#endif /* MBFL_MEMORY_DEVICE_H */
diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_string.c b/ext/mbstring/libmbfl/mbfl/mbfl_string.c
index a036356dd2..760634e65d 100644
--- a/ext/mbstring/libmbfl/mbfl/mbfl_string.c
+++ b/ext/mbstring/libmbfl/mbfl/mbfl_string.c
@@ -31,31 +31,22 @@
#include "mbfl_string.h"
#include "mbfilter_pass.h"
-/*
- * string object
- */
-void
-mbfl_string_init(mbfl_string *string)
+void mbfl_string_init_set(mbfl_string *string, const mbfl_encoding *encoding)
{
- string->encoding = &mbfl_encoding_pass;
- string->val = (unsigned char*)NULL;
+ string->encoding = encoding;
+ string->val = NULL;
string->len = 0;
}
-void
-mbfl_string_init_set(mbfl_string *string, const mbfl_encoding *encoding)
+void mbfl_string_init(mbfl_string *string)
{
- string->encoding = encoding;
- string->val = (unsigned char*)NULL;
- string->len = 0;
+ mbfl_string_init_set(string, &mbfl_encoding_pass);
}
-void
-mbfl_string_clear(mbfl_string *string)
+void mbfl_string_clear(mbfl_string *string)
{
- if (string->val != (unsigned char*)NULL) {
+ if (string->val) {
efree(string->val);
}
- string->val = (unsigned char*)NULL;
- string->len = 0;
+ mbfl_string_init_set(string, NULL); /* Poison it so any attempt to reuse will fail hard */
}
diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c
index b6395aecdd..e02b237bf7 100644
--- a/ext/mbstring/mbstring.c
+++ b/ext/mbstring/mbstring.c
@@ -1497,9 +1497,6 @@ PHP_FUNCTION(mb_preferred_mime_name)
}
/* }}} */
-#define IS_SJIS1(c) ((((c)>=0x81 && (c)<=0x9f) || ((c)>=0xe0 && (c)<=0xf5)) ? 1 : 0)
-#define IS_SJIS2(c) ((((c)>=0x40 && (c)<=0x7e) || ((c)>=0x80 && (c)<=0xfc)) ? 1 : 0)
-
/* {{{ Parses GET/POST/COOKIE data and sets global variables */
PHP_FUNCTION(mb_parse_str)
{
@@ -2764,8 +2761,7 @@ PHP_FUNCTION(mb_encoding_aliases)
array_init(return_value);
if (encoding->aliases != NULL) {
- const char **alias;
- for (alias = *encoding->aliases; *alias; ++alias) {
+ for (const char **alias = encoding->aliases; *alias; ++alias) {
add_next_index_string(return_value, (char *)*alias);
}
}
@@ -3649,7 +3645,7 @@ PHP_FUNCTION(mb_send_mail)
if (!suppressed_hdrs.cnt_type) {
mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER2, sizeof(PHP_MBSTR_MAIL_MIME_HEADER2) - 1);
- p = (char *)mbfl_no2preferred_mime_name(tran_cs->no_encoding);
+ p = (char *)mbfl_encoding_preferred_mime_name(tran_cs);
if (p != NULL) {
mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER3, sizeof(PHP_MBSTR_MAIL_MIME_HEADER3) - 1);
mbfl_memory_device_strcat(&device, p);
@@ -3658,7 +3654,7 @@ PHP_FUNCTION(mb_send_mail)
}
if (!suppressed_hdrs.cnt_trans_enc) {
mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER4, sizeof(PHP_MBSTR_MAIL_MIME_HEADER4) - 1);
- p = (char *)mbfl_no2preferred_mime_name(body_enc->no_encoding);
+ p = (char *)mbfl_encoding_preferred_mime_name(body_enc);
if (p == NULL) {
p = "7bit";
}
diff --git a/ext/mbstring/tests/data/8859-1.txt b/ext/mbstring/tests/data/8859-1.txt
new file mode 100644
index 0000000000..3a55afefc4
--- /dev/null
+++ b/ext/mbstring/tests/data/8859-1.txt
@@ -0,0 +1,292 @@
+# 8859-1.TXT
+# Date: 2015-12-02 20:19:00 GMT [KW]
+# © 2015 Unicode®, Inc.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
+#
+# Name: ISO/IEC 8859-1:1998 to Unicode
+# Unicode version: 3.0
+# Table version: 2.0
+# Table format: Format A
+# Date: 1999 July 27 (header updated: 2015 December 02)
+# Authors: Ken Whistler <ken@unicode.org>
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO/IEC 8859-1:1998 characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO/IEC 8859-1 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO/IEC 8859-1 order.
+#
+# Version history
+# 1.0 version: updates 0.1 version by adding mappings for all
+# control characters.
+# 2.0 version: updates to copyright notice and terms of use; no
+# changes to character mappings
+#
+# Updated versions of this file may be found in:
+# http://www.unicode.org/Public/MAPPINGS/
+#
+# Any comments or problems, contact us at:
+# http://www.unicode.org/reporting.html
+#
+0x00 0x0000 # NULL
+0x01 0x0001 # START OF HEADING
+0x02 0x0002 # START OF TEXT
+0x03 0x0003 # END OF TEXT
+0x04 0x0004 # END OF TRANSMISSION
+0x05 0x0005 # ENQUIRY
+0x06 0x0006 # ACKNOWLEDGE
+0x07 0x0007 # BELL
+0x08 0x0008 # BACKSPACE
+0x09 0x0009 # HORIZONTAL TABULATION
+0x0A 0x000A # LINE FEED
+0x0B 0x000B # VERTICAL TABULATION
+0x0C 0x000C # FORM FEED
+0x0D 0x000D # CARRIAGE RETURN
+0x0E 0x000E # SHIFT OUT
+0x0F 0x000F # SHIFT IN
+0x10 0x0010 # DATA LINK ESCAPE
+0x11 0x0011 # DEVICE CONTROL ONE
+0x12 0x0012 # DEVICE CONTROL TWO
+0x13 0x0013 # DEVICE CONTROL THREE
+0x14 0x0014 # DEVICE CONTROL FOUR
+0x15 0x0015 # NEGATIVE ACKNOWLEDGE
+0x16 0x0016 # SYNCHRONOUS IDLE
+0x17 0x0017 # END OF TRANSMISSION BLOCK
+0x18 0x0018 # CANCEL
+0x19 0x0019 # END OF MEDIUM
+0x1A 0x001A # SUBSTITUTE
+0x1B 0x001B # ESCAPE
+0x1C 0x001C # FILE SEPARATOR
+0x1D 0x001D # GROUP SEPARATOR
+0x1E 0x001E # RECORD SEPARATOR
+0x1F 0x001F # UNIT SEPARATOR
+0x20 0x0020 # SPACE
+0x21 0x0021 # EXCLAMATION MARK
+0x22 0x0022 # QUOTATION MARK
+0x23 0x0023 # NUMBER SIGN
+0x24 0x0024 # DOLLAR SIGN
+0x25 0x0025 # PERCENT SIGN
+0x26 0x0026 # AMPERSAND
+0x27 0x0027 # APOSTROPHE
+0x28 0x0028 # LEFT PARENTHESIS
+0x29 0x0029 # RIGHT PARENTHESIS
+0x2A 0x002A # ASTERISK
+0x2B 0x002B # PLUS SIGN
+0x2C 0x002C # COMMA
+0x2D 0x002D # HYPHEN-MINUS
+0x2E 0x002E # FULL STOP
+0x2F 0x002F # SOLIDUS
+0x30 0x0030 # DIGIT ZERO
+0x31 0x0031 # DIGIT ONE
+0x32 0x0032 # DIGIT TWO
+0x33 0x0033 # DIGIT THREE
+0x34 0x0034 # DIGIT FOUR
+0x35 0x0035 # DIGIT FIVE
+0x36 0x0036 # DIGIT SIX
+0x37 0x0037 # DIGIT SEVEN
+0x38 0x0038 # DIGIT EIGHT
+0x39 0x0039 # DIGIT NINE
+0x3A 0x003A # COLON
+0x3B 0x003B # SEMICOLON
+0x3C 0x003C # LESS-THAN SIGN
+0x3D 0x003D # EQUALS SIGN
+0x3E 0x003E # GREATER-THAN SIGN
+0x3F 0x003F # QUESTION MARK
+0x40 0x0040 # COMMERCIAL AT
+0x41 0x0041 # LATIN CAPITAL LETTER A
+0x42 0x0042 # LATIN CAPITAL LETTER B
+0x43 0x0043 # LATIN CAPITAL LETTER C
+0x44 0x0044 # LATIN CAPITAL LETTER D
+0x45 0x0045 # LATIN CAPITAL LETTER E
+0x46 0x0046 # LATIN CAPITAL LETTER F
+0x47 0x0047 # LATIN CAPITAL LETTER G
+0x48 0x0048 # LATIN CAPITAL LETTER H
+0x49 0x0049 # LATIN CAPITAL LETTER I
+0x4A 0x004A # LATIN CAPITAL LETTER J
+0x4B 0x004B # LATIN CAPITAL LETTER K
+0x4C 0x004C # LATIN CAPITAL LETTER L
+0x4D 0x004D # LATIN CAPITAL LETTER M
+0x4E 0x004E # LATIN CAPITAL LETTER N
+0x4F 0x004F # LATIN CAPITAL LETTER O
+0x50 0x0050 # LATIN CAPITAL LETTER P
+0x51 0x0051 # LATIN CAPITAL LETTER Q
+0x52 0x0052 # LATIN CAPITAL LETTER R
+0x53 0x0053 # LATIN CAPITAL LETTER S
+0x54 0x0054 # LATIN CAPITAL LETTER T
+0x55 0x0055 # LATIN CAPITAL LETTER U
+0x56 0x0056 # LATIN CAPITAL LETTER V
+0x57 0x0057 # LATIN CAPITAL LETTER W
+0x58 0x0058 # LATIN CAPITAL LETTER X
+0x59 0x0059 # LATIN CAPITAL LETTER Y
+0x5A 0x005A # LATIN CAPITAL LETTER Z
+0x5B 0x005B # LEFT SQUARE BRACKET
+0x5C 0x005C # REVERSE SOLIDUS
+0x5D 0x005D # RIGHT SQUARE BRACKET
+0x5E 0x005E # CIRCUMFLEX ACCENT
+0x5F 0x005F # LOW LINE
+0x60 0x0060 # GRAVE ACCENT
+0x61 0x0061 # LATIN SMALL LETTER A
+0x62 0x0062 # LATIN SMALL LETTER B
+0x63 0x0063 # LATIN SMALL LETTER C
+0x64 0x0064 # LATIN SMALL LETTER D
+0x65 0x0065 # LATIN SMALL LETTER E
+0x66 0x0066 # LATIN SMALL LETTER F
+0x67 0x0067 # LATIN SMALL LETTER G
+0x68 0x0068 # LATIN SMALL LETTER H
+0x69 0x0069 # LATIN SMALL LETTER I
+0x6A 0x006A # LATIN SMALL LETTER J
+0x6B 0x006B # LATIN SMALL LETTER K
+0x6C 0x006C # LATIN SMALL LETTER L
+0x6D 0x006D # LATIN SMALL LETTER M
+0x6E 0x006E # LATIN SMALL LETTER N
+0x6F 0x006F # LATIN SMALL LETTER O
+0x70 0x0070 # LATIN SMALL LETTER P
+0x71 0x0071 # LATIN SMALL LETTER Q
+0x72 0x0072 # LATIN SMALL LETTER R
+0x73 0x0073 # LATIN SMALL LETTER S
+0x74 0x0074 # LATIN SMALL LETTER T
+0x75 0x0075 # LATIN SMALL LETTER U
+0x76 0x0076 # LATIN SMALL LETTER V
+0x77 0x0077 # LATIN SMALL LETTER W
+0x78 0x0078 # LATIN SMALL LETTER X
+0x79 0x0079 # LATIN SMALL LETTER Y
+0x7A 0x007A # LATIN SMALL LETTER Z
+0x7B 0x007B # LEFT CURLY BRACKET
+0x7C 0x007C # VERTICAL LINE
+0x7D 0x007D # RIGHT CURLY BRACKET
+0x7E 0x007E # TILDE
+0x7F 0x007F # DELETE
+0x80 0x0080 # <control>
+0x81 0x0081 # <control>
+0x82 0x0082 # <control>
+0x83 0x0083 # <control>
+0x84 0x0084 # <control>
+0x85 0x0085 # <control>
+0x86 0x0086 # <control>
+0x87 0x0087 # <control>
+0x88 0x0088 # <control>
+0x89 0x0089 # <control>
+0x8A 0x008A # <control>
+0x8B 0x008B # <control>
+0x8C 0x008C # <control>
+0x8D 0x008D # <control>
+0x8E 0x008E # <control>
+0x8F 0x008F # <control>
+0x90 0x0090 # <control>
+0x91 0x0091 # <control>
+0x92 0x0092 # <control>
+0x93 0x0093 # <control>
+0x94 0x0094 # <control>
+0x95 0x0095 # <control>
+0x96 0x0096 # <control>
+0x97 0x0097 # <control>
+0x98 0x0098 # <control>
+0x99 0x0099 # <control>
+0x9A 0x009A # <control>
+0x9B 0x009B # <control>
+0x9C 0x009C # <control>
+0x9D 0x009D # <control>
+0x9E 0x009E # <control>
+0x9F 0x009F # <control>
+0xA0 0x00A0 # NO-BREAK SPACE
+0xA1 0x00A1 # INVERTED EXCLAMATION MARK
+0xA2 0x00A2 # CENT SIGN
+0xA3 0x00A3 # POUND SIGN
+0xA4 0x00A4 # CURRENCY SIGN
+0xA5 0x00A5 # YEN SIGN
+0xA6 0x00A6 # BROKEN BAR
+0xA7 0x00A7 # SECTION SIGN
+0xA8 0x00A8 # DIAERESIS
+0xA9 0x00A9 # COPYRIGHT SIGN
+0xAA 0x00AA # FEMININE ORDINAL INDICATOR
+0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC 0x00AC # NOT SIGN
+0xAD 0x00AD # SOFT HYPHEN
+0xAE 0x00AE # REGISTERED SIGN
+0xAF 0x00AF # MACRON
+0xB0 0x00B0 # DEGREE SIGN
+0xB1 0x00B1 # PLUS-MINUS SIGN
+0xB2 0x00B2 # SUPERSCRIPT TWO
+0xB3 0x00B3 # SUPERSCRIPT THREE
+0xB4 0x00B4 # ACUTE ACCENT
+0xB5 0x00B5 # MICRO SIGN
+0xB6 0x00B6 # PILCROW SIGN
+0xB7 0x00B7 # MIDDLE DOT
+0xB8 0x00B8 # CEDILLA
+0xB9 0x00B9 # SUPERSCRIPT ONE
+0xBA 0x00BA # MASCULINE ORDINAL INDICATOR
+0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC 0x00BC # VULGAR FRACTION ONE QUARTER
+0xBD 0x00BD # VULGAR FRACTION ONE HALF
+0xBE 0x00BE # VULGAR FRACTION THREE QUARTERS
+0xBF 0x00BF # INVERTED QUESTION MARK
+0xC0 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE
+0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE
+0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE
+0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6 0x00C6 # LATIN CAPITAL LETTER AE
+0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE
+0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE
+0xCA 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE
+0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE
+0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD0 0x00D0 # LATIN CAPITAL LETTER ETH (Icelandic)
+0xD1 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE
+0xD2 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE
+0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE
+0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE
+0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7 0x00D7 # MULTIPLICATION SIGN
+0xD8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE
+0xD9 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE
+0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE
+0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE
+0xDE 0x00DE # LATIN CAPITAL LETTER THORN (Icelandic)
+0xDF 0x00DF # LATIN SMALL LETTER SHARP S (German)
+0xE0 0x00E0 # LATIN SMALL LETTER A WITH GRAVE
+0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE
+0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3 0x00E3 # LATIN SMALL LETTER A WITH TILDE
+0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS
+0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE
+0xE6 0x00E6 # LATIN SMALL LETTER AE
+0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA
+0xE8 0x00E8 # LATIN SMALL LETTER E WITH GRAVE
+0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE
+0xEA 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS
+0xEC 0x00EC # LATIN SMALL LETTER I WITH GRAVE
+0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE
+0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS
+0xF0 0x00F0 # LATIN SMALL LETTER ETH (Icelandic)
+0xF1 0x00F1 # LATIN SMALL LETTER N WITH TILDE
+0xF2 0x00F2 # LATIN SMALL LETTER O WITH GRAVE
+0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE
+0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE
+0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS
+0xF7 0x00F7 # DIVISION SIGN
+0xF8 0x00F8 # LATIN SMALL LETTER O WITH STROKE
+0xF9 0x00F9 # LATIN SMALL LETTER U WITH GRAVE
+0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE
+0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS
+0xFD 0x00FD # LATIN SMALL LETTER Y WITH ACUTE
+0xFE 0x00FE # LATIN SMALL LETTER THORN (Icelandic)
+0xFF 0x00FF # LATIN SMALL LETTER Y WITH DIAERESIS
diff --git a/ext/mbstring/tests/data/8859-10.txt b/ext/mbstring/tests/data/8859-10.txt
new file mode 100644
index 0000000000..0ec67d72ee
--- /dev/null
+++ b/ext/mbstring/tests/data/8859-10.txt
@@ -0,0 +1,292 @@
+# 8859-10.TXT
+# Date: 2015-12-02 21:53:00 GMT [KW]
+# © 2015 Unicode®, Inc.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
+#
+# Name: ISO/IEC 8859-10:1998 to Unicode
+# Unicode version: 3.0
+# Table version: 2.0
+# Table format: Format A
+# Date: 1999 October 11 (header updated: 2015 December 02)
+# Authors: Ken Whistler <ken@unicode.org>
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO/IEC 8859-10:1998 characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO/IEC 8859-10 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO/IEC 8859-10 order.
+#
+# Version history
+# 1.0 version new.
+# 1.1 corrected mistake in mapping of 0xA4
+# 2.0 version: updates to copyright notice and terms of use; no
+# changes to character mappings
+#
+# Updated versions of this file may be found in:
+# http://www.unicode.org/Public/MAPPINGS/
+#
+# Any comments or problems, contact us at:
+# http://www.unicode.org/reporting.html
+#
+0x00 0x0000 # NULL
+0x01 0x0001 # START OF HEADING
+0x02 0x0002 # START OF TEXT
+0x03 0x0003 # END OF TEXT
+0x04 0x0004 # END OF TRANSMISSION
+0x05 0x0005 # ENQUIRY
+0x06 0x0006 # ACKNOWLEDGE
+0x07 0x0007 # BELL
+0x08 0x0008 # BACKSPACE
+0x09 0x0009 # HORIZONTAL TABULATION
+0x0A 0x000A # LINE FEED
+0x0B 0x000B # VERTICAL TABULATION
+0x0C 0x000C # FORM FEED
+0x0D 0x000D # CARRIAGE RETURN
+0x0E 0x000E # SHIFT OUT
+0x0F 0x000F # SHIFT IN
+0x10 0x0010 # DATA LINK ESCAPE
+0x11 0x0011 # DEVICE CONTROL ONE
+0x12 0x0012 # DEVICE CONTROL TWO
+0x13 0x0013 # DEVICE CONTROL THREE
+0x14 0x0014 # DEVICE CONTROL FOUR
+0x15 0x0015 # NEGATIVE ACKNOWLEDGE
+0x16 0x0016 # SYNCHRONOUS IDLE
+0x17 0x0017 # END OF TRANSMISSION BLOCK
+0x18 0x0018 # CANCEL
+0x19 0x0019 # END OF MEDIUM
+0x1A 0x001A # SUBSTITUTE
+0x1B 0x001B # ESCAPE
+0x1C 0x001C # FILE SEPARATOR
+0x1D 0x001D # GROUP SEPARATOR
+0x1E 0x001E # RECORD SEPARATOR
+0x1F 0x001F # UNIT SEPARATOR
+0x20 0x0020 # SPACE
+0x21 0x0021 # EXCLAMATION MARK
+0x22 0x0022 # QUOTATION MARK
+0x23 0x0023 # NUMBER SIGN
+0x24 0x0024 # DOLLAR SIGN
+0x25 0x0025 # PERCENT SIGN
+0x26 0x0026 # AMPERSAND
+0x27 0x0027 # APOSTROPHE
+0x28 0x0028 # LEFT PARENTHESIS
+0x29 0x0029 # RIGHT PARENTHESIS
+0x2A 0x002A # ASTERISK
+0x2B 0x002B # PLUS SIGN
+0x2C 0x002C # COMMA
+0x2D 0x002D # HYPHEN-MINUS
+0x2E 0x002E # FULL STOP
+0x2F 0x002F # SOLIDUS
+0x30 0x0030 # DIGIT ZERO
+0x31 0x0031 # DIGIT ONE
+0x32 0x0032 # DIGIT TWO
+0x33 0x0033 # DIGIT THREE
+0x34 0x0034 # DIGIT FOUR
+0x35 0x0035 # DIGIT FIVE
+0x36 0x0036 # DIGIT SIX
+0x37 0x0037 # DIGIT SEVEN
+0x38 0x0038 # DIGIT EIGHT
+0x39 0x0039 # DIGIT NINE
+0x3A 0x003A # COLON
+0x3B 0x003B # SEMICOLON
+0x3C 0x003C # LESS-THAN SIGN
+0x3D 0x003D # EQUALS SIGN
+0x3E 0x003E # GREATER-THAN SIGN
+0x3F 0x003F # QUESTION MARK
+0x40 0x0040 # COMMERCIAL AT
+0x41 0x0041 # LATIN CAPITAL LETTER A
+0x42 0x0042 # LATIN CAPITAL LETTER B
+0x43 0x0043 # LATIN CAPITAL LETTER C
+0x44 0x0044 # LATIN CAPITAL LETTER D
+0x45 0x0045 # LATIN CAPITAL LETTER E
+0x46 0x0046 # LATIN CAPITAL LETTER F
+0x47 0x0047 # LATIN CAPITAL LETTER G
+0x48 0x0048 # LATIN CAPITAL LETTER H
+0x49 0x0049 # LATIN CAPITAL LETTER I
+0x4A 0x004A # LATIN CAPITAL LETTER J
+0x4B 0x004B # LATIN CAPITAL LETTER K
+0x4C 0x004C # LATIN CAPITAL LETTER L
+0x4D 0x004D # LATIN CAPITAL LETTER M
+0x4E 0x004E # LATIN CAPITAL LETTER N
+0x4F 0x004F # LATIN CAPITAL LETTER O
+0x50 0x0050 # LATIN CAPITAL LETTER P
+0x51 0x0051 # LATIN CAPITAL LETTER Q
+0x52 0x0052 # LATIN CAPITAL LETTER R
+0x53 0x0053 # LATIN CAPITAL LETTER S
+0x54 0x0054 # LATIN CAPITAL LETTER T
+0x55 0x0055 # LATIN CAPITAL LETTER U
+0x56 0x0056 # LATIN CAPITAL LETTER V
+0x57 0x0057 # LATIN CAPITAL LETTER W
+0x58 0x0058 # LATIN CAPITAL LETTER X
+0x59 0x0059 # LATIN CAPITAL LETTER Y
+0x5A 0x005A # LATIN CAPITAL LETTER Z
+0x5B 0x005B # LEFT SQUARE BRACKET
+0x5C 0x005C # REVERSE SOLIDUS
+0x5D 0x005D # RIGHT SQUARE BRACKET
+0x5E 0x005E # CIRCUMFLEX ACCENT
+0x5F 0x005F # LOW LINE
+0x60 0x0060 # GRAVE ACCENT
+0x61 0x0061 # LATIN SMALL LETTER A
+0x62 0x0062 # LATIN SMALL LETTER B
+0x63 0x0063 # LATIN SMALL LETTER C
+0x64 0x0064 # LATIN SMALL LETTER D
+0x65 0x0065 # LATIN SMALL LETTER E
+0x66 0x0066 # LATIN SMALL LETTER F
+0x67 0x0067 # LATIN SMALL LETTER G
+0x68 0x0068 # LATIN SMALL LETTER H
+0x69 0x0069 # LATIN SMALL LETTER I
+0x6A 0x006A # LATIN SMALL LETTER J
+0x6B 0x006B # LATIN SMALL LETTER K
+0x6C 0x006C # LATIN SMALL LETTER L
+0x6D 0x006D # LATIN SMALL LETTER M
+0x6E 0x006E # LATIN SMALL LETTER N
+0x6F 0x006F # LATIN SMALL LETTER O
+0x70 0x0070 # LATIN SMALL LETTER P
+0x71 0x0071 # LATIN SMALL LETTER Q
+0x72 0x0072 # LATIN SMALL LETTER R
+0x73 0x0073 # LATIN SMALL LETTER S
+0x74 0x0074 # LATIN SMALL LETTER T
+0x75 0x0075 # LATIN SMALL LETTER U
+0x76 0x0076 # LATIN SMALL LETTER V
+0x77 0x0077 # LATIN SMALL LETTER W
+0x78 0x0078 # LATIN SMALL LETTER X
+0x79 0x0079 # LATIN SMALL LETTER Y
+0x7A 0x007A # LATIN SMALL LETTER Z
+0x7B 0x007B # LEFT CURLY BRACKET
+0x7C 0x007C # VERTICAL LINE
+0x7D 0x007D # RIGHT CURLY BRACKET
+0x7E 0x007E # TILDE
+0x7F 0x007F # DELETE
+0x80 0x0080 # <control>
+0x81 0x0081 # <control>
+0x82 0x0082 # <control>
+0x83 0x0083 # <control>
+0x84 0x0084 # <control>
+0x85 0x0085 # <control>
+0x86 0x0086 # <control>
+0x87 0x0087 # <control>
+0x88 0x0088 # <control>
+0x89 0x0089 # <control>
+0x8A 0x008A # <control>
+0x8B 0x008B # <control>
+0x8C 0x008C # <control>
+0x8D 0x008D # <control>
+0x8E 0x008E # <control>
+0x8F 0x008F # <control>
+0x90 0x0090 # <control>
+0x91 0x0091 # <control>
+0x92 0x0092 # <control>
+0x93 0x0093 # <control>
+0x94 0x0094 # <control>
+0x95 0x0095 # <control>
+0x96 0x0096 # <control>
+0x97 0x0097 # <control>
+0x98 0x0098 # <control>
+0x99 0x0099 # <control>
+0x9A 0x009A # <control>
+0x9B 0x009B # <control>
+0x9C 0x009C # <control>
+0x9D 0x009D # <control>
+0x9E 0x009E # <control>
+0x9F 0x009F # <control>
+0xA0 0x00A0 # NO-BREAK SPACE
+0xA1 0x0104 # LATIN CAPITAL LETTER A WITH OGONEK
+0xA2 0x0112 # LATIN CAPITAL LETTER E WITH MACRON
+0xA3 0x0122 # LATIN CAPITAL LETTER G WITH CEDILLA
+0xA4 0x012A # LATIN CAPITAL LETTER I WITH MACRON
+0xA5 0x0128 # LATIN CAPITAL LETTER I WITH TILDE
+0xA6 0x0136 # LATIN CAPITAL LETTER K WITH CEDILLA
+0xA7 0x00A7 # SECTION SIGN
+0xA8 0x013B # LATIN CAPITAL LETTER L WITH CEDILLA
+0xA9 0x0110 # LATIN CAPITAL LETTER D WITH STROKE
+0xAA 0x0160 # LATIN CAPITAL LETTER S WITH CARON
+0xAB 0x0166 # LATIN CAPITAL LETTER T WITH STROKE
+0xAC 0x017D # LATIN CAPITAL LETTER Z WITH CARON
+0xAD 0x00AD # SOFT HYPHEN
+0xAE 0x016A # LATIN CAPITAL LETTER U WITH MACRON
+0xAF 0x014A # LATIN CAPITAL LETTER ENG
+0xB0 0x00B0 # DEGREE SIGN
+0xB1 0x0105 # LATIN SMALL LETTER A WITH OGONEK
+0xB2 0x0113 # LATIN SMALL LETTER E WITH MACRON
+0xB3 0x0123 # LATIN SMALL LETTER G WITH CEDILLA
+0xB4 0x012B # LATIN SMALL LETTER I WITH MACRON
+0xB5 0x0129 # LATIN SMALL LETTER I WITH TILDE
+0xB6 0x0137 # LATIN SMALL LETTER K WITH CEDILLA
+0xB7 0x00B7 # MIDDLE DOT
+0xB8 0x013C # LATIN SMALL LETTER L WITH CEDILLA
+0xB9 0x0111 # LATIN SMALL LETTER D WITH STROKE
+0xBA 0x0161 # LATIN SMALL LETTER S WITH CARON
+0xBB 0x0167 # LATIN SMALL LETTER T WITH STROKE
+0xBC 0x017E # LATIN SMALL LETTER Z WITH CARON
+0xBD 0x2015 # HORIZONTAL BAR
+0xBE 0x016B # LATIN SMALL LETTER U WITH MACRON
+0xBF 0x014B # LATIN SMALL LETTER ENG
+0xC0 0x0100 # LATIN CAPITAL LETTER A WITH MACRON
+0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE
+0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE
+0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6 0x00C6 # LATIN CAPITAL LETTER AE
+0xC7 0x012E # LATIN CAPITAL LETTER I WITH OGONEK
+0xC8 0x010C # LATIN CAPITAL LETTER C WITH CARON
+0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE
+0xCA 0x0118 # LATIN CAPITAL LETTER E WITH OGONEK
+0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC 0x0116 # LATIN CAPITAL LETTER E WITH DOT ABOVE
+0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE
+0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD0 0x00D0 # LATIN CAPITAL LETTER ETH (Icelandic)
+0xD1 0x0145 # LATIN CAPITAL LETTER N WITH CEDILLA
+0xD2 0x014C # LATIN CAPITAL LETTER O WITH MACRON
+0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE
+0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE
+0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7 0x0168 # LATIN CAPITAL LETTER U WITH TILDE
+0xD8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE
+0xD9 0x0172 # LATIN CAPITAL LETTER U WITH OGONEK
+0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE
+0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE
+0xDE 0x00DE # LATIN CAPITAL LETTER THORN (Icelandic)
+0xDF 0x00DF # LATIN SMALL LETTER SHARP S (German)
+0xE0 0x0101 # LATIN SMALL LETTER A WITH MACRON
+0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE
+0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3 0x00E3 # LATIN SMALL LETTER A WITH TILDE
+0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS
+0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE
+0xE6 0x00E6 # LATIN SMALL LETTER AE
+0xE7 0x012F # LATIN SMALL LETTER I WITH OGONEK
+0xE8 0x010D # LATIN SMALL LETTER C WITH CARON
+0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE
+0xEA 0x0119 # LATIN SMALL LETTER E WITH OGONEK
+0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS
+0xEC 0x0117 # LATIN SMALL LETTER E WITH DOT ABOVE
+0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE
+0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS
+0xF0 0x00F0 # LATIN SMALL LETTER ETH (Icelandic)
+0xF1 0x0146 # LATIN SMALL LETTER N WITH CEDILLA
+0xF2 0x014D # LATIN SMALL LETTER O WITH MACRON
+0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE
+0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE
+0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS
+0xF7 0x0169 # LATIN SMALL LETTER U WITH TILDE
+0xF8 0x00F8 # LATIN SMALL LETTER O WITH STROKE
+0xF9 0x0173 # LATIN SMALL LETTER U WITH OGONEK
+0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE
+0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS
+0xFD 0x00FD # LATIN SMALL LETTER Y WITH ACUTE
+0xFE 0x00FE # LATIN SMALL LETTER THORN (Icelandic)
+0xFF 0x0138 # LATIN SMALL LETTER KRA
diff --git a/ext/mbstring/tests/data/8859-11.txt b/ext/mbstring/tests/data/8859-11.txt
new file mode 100644
index 0000000000..5334e3c276
--- /dev/null
+++ b/ext/mbstring/tests/data/8859-11.txt
@@ -0,0 +1,286 @@
+# 8859-11.TXT
+# Date: 2015-12-02 21:55:00 GMT [KW]
+# © 2015 Unicode®, Inc.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
+#
+# Name: ISO/IEC 8859-11:2001 to Unicode
+# Unicode version: 3.2
+# Table version: 2.0
+# Table format: Format A
+# Date: 2002 October 7 (header updated: 2015 December 02)
+# Authors: Ken Whistler <ken@unicode.org>
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO/IEC 8859-11:2001 characters map into Unicode.
+#
+# ISO/IEC 8859-11:2001 is equivalent to TIS 620-2533 (1990) with
+# the addition of 0xA0 NO-BREAK SPACE.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO/IEC 8859-11 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO/IEC 8859-11 order.
+#
+# Version history:
+# 2002 October 7 Created
+# 2.0 version: updates to copyright notice and terms of use; no
+# changes to character mappings
+#
+# Updated versions of this file may be found in:
+# http://www.unicode.org/Public/MAPPINGS/
+#
+# Any comments or problems, contact us at:
+# http://www.unicode.org/reporting.html
+#
+0x00 0x0000 # NULL
+0x01 0x0001 # START OF HEADING
+0x02 0x0002 # START OF TEXT
+0x03 0x0003 # END OF TEXT
+0x04 0x0004 # END OF TRANSMISSION
+0x05 0x0005 # ENQUIRY
+0x06 0x0006 # ACKNOWLEDGE
+0x07 0x0007 # BELL
+0x08 0x0008 # BACKSPACE
+0x09 0x0009 # HORIZONTAL TABULATION
+0x0A 0x000A # LINE FEED
+0x0B 0x000B # VERTICAL TABULATION
+0x0C 0x000C # FORM FEED
+0x0D 0x000D # CARRIAGE RETURN
+0x0E 0x000E # SHIFT OUT
+0x0F 0x000F # SHIFT IN
+0x10 0x0010 # DATA LINK ESCAPE
+0x11 0x0011 # DEVICE CONTROL ONE
+0x12 0x0012 # DEVICE CONTROL TWO
+0x13 0x0013 # DEVICE CONTROL THREE
+0x14 0x0014 # DEVICE CONTROL FOUR
+0x15 0x0015 # NEGATIVE ACKNOWLEDGE
+0x16 0x0016 # SYNCHRONOUS IDLE
+0x17 0x0017 # END OF TRANSMISSION BLOCK
+0x18 0x0018 # CANCEL
+0x19 0x0019 # END OF MEDIUM
+0x1A 0x001A # SUBSTITUTE
+0x1B 0x001B # ESCAPE
+0x1C 0x001C # FILE SEPARATOR
+0x1D 0x001D # GROUP SEPARATOR
+0x1E 0x001E # RECORD SEPARATOR
+0x1F 0x001F # UNIT SEPARATOR
+0x20 0x0020 # SPACE
+0x21 0x0021 # EXCLAMATION MARK
+0x22 0x0022 # QUOTATION MARK
+0x23 0x0023 # NUMBER SIGN
+0x24 0x0024 # DOLLAR SIGN
+0x25 0x0025 # PERCENT SIGN
+0x26 0x0026 # AMPERSAND
+0x27 0x0027 # APOSTROPHE
+0x28 0x0028 # LEFT PARENTHESIS
+0x29 0x0029 # RIGHT PARENTHESIS
+0x2A 0x002A # ASTERISK
+0x2B 0x002B # PLUS SIGN
+0x2C 0x002C # COMMA
+0x2D 0x002D # HYPHEN-MINUS
+0x2E 0x002E # FULL STOP
+0x2F 0x002F # SOLIDUS
+0x30 0x0030 # DIGIT ZERO
+0x31 0x0031 # DIGIT ONE
+0x32 0x0032 # DIGIT TWO
+0x33 0x0033 # DIGIT THREE
+0x34 0x0034 # DIGIT FOUR
+0x35 0x0035 # DIGIT FIVE
+0x36 0x0036 # DIGIT SIX
+0x37 0x0037 # DIGIT SEVEN
+0x38 0x0038 # DIGIT EIGHT
+0x39 0x0039 # DIGIT NINE
+0x3A 0x003A # COLON
+0x3B 0x003B # SEMICOLON
+0x3C 0x003C # LESS-THAN SIGN
+0x3D 0x003D # EQUALS SIGN
+0x3E 0x003E # GREATER-THAN SIGN
+0x3F 0x003F # QUESTION MARK
+0x40 0x0040 # COMMERCIAL AT
+0x41 0x0041 # LATIN CAPITAL LETTER A
+0x42 0x0042 # LATIN CAPITAL LETTER B
+0x43 0x0043 # LATIN CAPITAL LETTER C
+0x44 0x0044 # LATIN CAPITAL LETTER D
+0x45 0x0045 # LATIN CAPITAL LETTER E
+0x46 0x0046 # LATIN CAPITAL LETTER F
+0x47 0x0047 # LATIN CAPITAL LETTER G
+0x48 0x0048 # LATIN CAPITAL LETTER H
+0x49 0x0049 # LATIN CAPITAL LETTER I
+0x4A 0x004A # LATIN CAPITAL LETTER J
+0x4B 0x004B # LATIN CAPITAL LETTER K
+0x4C 0x004C # LATIN CAPITAL LETTER L
+0x4D 0x004D # LATIN CAPITAL LETTER M
+0x4E 0x004E # LATIN CAPITAL LETTER N
+0x4F 0x004F # LATIN CAPITAL LETTER O
+0x50 0x0050 # LATIN CAPITAL LETTER P
+0x51 0x0051 # LATIN CAPITAL LETTER Q
+0x52 0x0052 # LATIN CAPITAL LETTER R
+0x53 0x0053 # LATIN CAPITAL LETTER S
+0x54 0x0054 # LATIN CAPITAL LETTER T
+0x55 0x0055 # LATIN CAPITAL LETTER U
+0x56 0x0056 # LATIN CAPITAL LETTER V
+0x57 0x0057 # LATIN CAPITAL LETTER W
+0x58 0x0058 # LATIN CAPITAL LETTER X
+0x59 0x0059 # LATIN CAPITAL LETTER Y
+0x5A 0x005A # LATIN CAPITAL LETTER Z
+0x5B 0x005B # LEFT SQUARE BRACKET
+0x5C 0x005C # REVERSE SOLIDUS
+0x5D 0x005D # RIGHT SQUARE BRACKET
+0x5E 0x005E # CIRCUMFLEX ACCENT
+0x5F 0x005F # LOW LINE
+0x60 0x0060 # GRAVE ACCENT
+0x61 0x0061 # LATIN SMALL LETTER A
+0x62 0x0062 # LATIN SMALL LETTER B
+0x63 0x0063 # LATIN SMALL LETTER C
+0x64 0x0064 # LATIN SMALL LETTER D
+0x65 0x0065 # LATIN SMALL LETTER E
+0x66 0x0066 # LATIN SMALL LETTER F
+0x67 0x0067 # LATIN SMALL LETTER G
+0x68 0x0068 # LATIN SMALL LETTER H
+0x69 0x0069 # LATIN SMALL LETTER I
+0x6A 0x006A # LATIN SMALL LETTER J
+0x6B 0x006B # LATIN SMALL LETTER K
+0x6C 0x006C # LATIN SMALL LETTER L
+0x6D 0x006D # LATIN SMALL LETTER M
+0x6E 0x006E # LATIN SMALL LETTER N
+0x6F 0x006F # LATIN SMALL LETTER O
+0x70 0x0070 # LATIN SMALL LETTER P
+0x71 0x0071 # LATIN SMALL LETTER Q
+0x72 0x0072 # LATIN SMALL LETTER R
+0x73 0x0073 # LATIN SMALL LETTER S
+0x74 0x0074 # LATIN SMALL LETTER T
+0x75 0x0075 # LATIN SMALL LETTER U
+0x76 0x0076 # LATIN SMALL LETTER V
+0x77 0x0077 # LATIN SMALL LETTER W
+0x78 0x0078 # LATIN SMALL LETTER X
+0x79 0x0079 # LATIN SMALL LETTER Y
+0x7A 0x007A # LATIN SMALL LETTER Z
+0x7B 0x007B # LEFT CURLY BRACKET
+0x7C 0x007C # VERTICAL LINE
+0x7D 0x007D # RIGHT CURLY BRACKET
+0x7E 0x007E # TILDE
+0x7F 0x007F # DELETE
+0x80 0x0080 # <control>
+0x81 0x0081 # <control>
+0x82 0x0082 # <control>
+0x83 0x0083 # <control>
+0x84 0x0084 # <control>
+0x85 0x0085 # <control>
+0x86 0x0086 # <control>
+0x87 0x0087 # <control>
+0x88 0x0088 # <control>
+0x89 0x0089 # <control>
+0x8A 0x008A # <control>
+0x8B 0x008B # <control>
+0x8C 0x008C # <control>
+0x8D 0x008D # <control>
+0x8E 0x008E # <control>
+0x8F 0x008F # <control>
+0x90 0x0090 # <control>
+0x91 0x0091 # <control>
+0x92 0x0092 # <control>
+0x93 0x0093 # <control>
+0x94 0x0094 # <control>
+0x95 0x0095 # <control>
+0x96 0x0096 # <control>
+0x97 0x0097 # <control>
+0x98 0x0098 # <control>
+0x99 0x0099 # <control>
+0x9A 0x009A # <control>
+0x9B 0x009B # <control>
+0x9C 0x009C # <control>
+0x9D 0x009D # <control>
+0x9E 0x009E # <control>
+0x9F 0x009F # <control>
+0xA0 0x00A0 # NO-BREAK SPACE
+0xA1 0x0E01 # THAI CHARACTER KO KAI
+0xA2 0x0E02 # THAI CHARACTER KHO KHAI
+0xA3 0x0E03 # THAI CHARACTER KHO KHUAT
+0xA4 0x0E04 # THAI CHARACTER KHO KHWAI
+0xA5 0x0E05 # THAI CHARACTER KHO KHON
+0xA6 0x0E06 # THAI CHARACTER KHO RAKHANG
+0xA7 0x0E07 # THAI CHARACTER NGO NGU
+0xA8 0x0E08 # THAI CHARACTER CHO CHAN
+0xA9 0x0E09 # THAI CHARACTER CHO CHING
+0xAA 0x0E0A # THAI CHARACTER CHO CHANG
+0xAB 0x0E0B # THAI CHARACTER SO SO
+0xAC 0x0E0C # THAI CHARACTER CHO CHOE
+0xAD 0x0E0D # THAI CHARACTER YO YING
+0xAE 0x0E0E # THAI CHARACTER DO CHADA
+0xAF 0x0E0F # THAI CHARACTER TO PATAK
+0xB0 0x0E10 # THAI CHARACTER THO THAN
+0xB1 0x0E11 # THAI CHARACTER THO NANGMONTHO
+0xB2 0x0E12 # THAI CHARACTER THO PHUTHAO
+0xB3 0x0E13 # THAI CHARACTER NO NEN
+0xB4 0x0E14 # THAI CHARACTER DO DEK
+0xB5 0x0E15 # THAI CHARACTER TO TAO
+0xB6 0x0E16 # THAI CHARACTER THO THUNG
+0xB7 0x0E17 # THAI CHARACTER THO THAHAN
+0xB8 0x0E18 # THAI CHARACTER THO THONG
+0xB9 0x0E19 # THAI CHARACTER NO NU
+0xBA 0x0E1A # THAI CHARACTER BO BAIMAI
+0xBB 0x0E1B # THAI CHARACTER PO PLA
+0xBC 0x0E1C # THAI CHARACTER PHO PHUNG
+0xBD 0x0E1D # THAI CHARACTER FO FA
+0xBE 0x0E1E # THAI CHARACTER PHO PHAN
+0xBF 0x0E1F # THAI CHARACTER FO FAN
+0xC0 0x0E20 # THAI CHARACTER PHO SAMPHAO
+0xC1 0x0E21 # THAI CHARACTER MO MA
+0xC2 0x0E22 # THAI CHARACTER YO YAK
+0xC3 0x0E23 # THAI CHARACTER RO RUA
+0xC4 0x0E24 # THAI CHARACTER RU
+0xC5 0x0E25 # THAI CHARACTER LO LING
+0xC6 0x0E26 # THAI CHARACTER LU
+0xC7 0x0E27 # THAI CHARACTER WO WAEN
+0xC8 0x0E28 # THAI CHARACTER SO SALA
+0xC9 0x0E29 # THAI CHARACTER SO RUSI
+0xCA 0x0E2A # THAI CHARACTER SO SUA
+0xCB 0x0E2B # THAI CHARACTER HO HIP
+0xCC 0x0E2C # THAI CHARACTER LO CHULA
+0xCD 0x0E2D # THAI CHARACTER O ANG
+0xCE 0x0E2E # THAI CHARACTER HO NOKHUK
+0xCF 0x0E2F # THAI CHARACTER PAIYANNOI
+0xD0 0x0E30 # THAI CHARACTER SARA A
+0xD1 0x0E31 # THAI CHARACTER MAI HAN-AKAT
+0xD2 0x0E32 # THAI CHARACTER SARA AA
+0xD3 0x0E33 # THAI CHARACTER SARA AM
+0xD4 0x0E34 # THAI CHARACTER SARA I
+0xD5 0x0E35 # THAI CHARACTER SARA II
+0xD6 0x0E36 # THAI CHARACTER SARA UE
+0xD7 0x0E37 # THAI CHARACTER SARA UEE
+0xD8 0x0E38 # THAI CHARACTER SARA U
+0xD9 0x0E39 # THAI CHARACTER SARA UU
+0xDA 0x0E3A # THAI CHARACTER PHINTHU
+0xDF 0x0E3F # THAI CURRENCY SYMBOL BAHT
+0xE0 0x0E40 # THAI CHARACTER SARA E
+0xE1 0x0E41 # THAI CHARACTER SARA AE
+0xE2 0x0E42 # THAI CHARACTER SARA O
+0xE3 0x0E43 # THAI CHARACTER SARA AI MAIMUAN
+0xE4 0x0E44 # THAI CHARACTER SARA AI MAIMALAI
+0xE5 0x0E45 # THAI CHARACTER LAKKHANGYAO
+0xE6 0x0E46 # THAI CHARACTER MAIYAMOK
+0xE7 0x0E47 # THAI CHARACTER MAITAIKHU
+0xE8 0x0E48 # THAI CHARACTER MAI EK
+0xE9 0x0E49 # THAI CHARACTER MAI THO
+0xEA 0x0E4A # THAI CHARACTER MAI TRI
+0xEB 0x0E4B # THAI CHARACTER MAI CHATTAWA
+0xEC 0x0E4C # THAI CHARACTER THANTHAKHAT
+0xED 0x0E4D # THAI CHARACTER NIKHAHIT
+0xEE 0x0E4E # THAI CHARACTER YAMAKKAN
+0xEF 0x0E4F # THAI CHARACTER FONGMAN
+0xF0 0x0E50 # THAI DIGIT ZERO
+0xF1 0x0E51 # THAI DIGIT ONE
+0xF2 0x0E52 # THAI DIGIT TWO
+0xF3 0x0E53 # THAI DIGIT THREE
+0xF4 0x0E54 # THAI DIGIT FOUR
+0xF5 0x0E55 # THAI DIGIT FIVE
+0xF6 0x0E56 # THAI DIGIT SIX
+0xF7 0x0E57 # THAI DIGIT SEVEN
+0xF8 0x0E58 # THAI DIGIT EIGHT
+0xF9 0x0E59 # THAI DIGIT NINE
+0xFA 0x0E5A # THAI CHARACTER ANGKHANKHU
+0xFB 0x0E5B # THAI CHARACTER KHOMUT
diff --git a/ext/mbstring/tests/data/8859-13.txt b/ext/mbstring/tests/data/8859-13.txt
new file mode 100644
index 0000000000..b613dc00e1
--- /dev/null
+++ b/ext/mbstring/tests/data/8859-13.txt
@@ -0,0 +1,291 @@
+# 8859-13.TXT
+# Date: 2015-12-02 22:03:00 GMT [KW]
+# © 2015 Unicode®, Inc.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
+#
+# Name: ISO/IEC 8859-13:1998 to Unicode
+# Unicode version: 3.0
+# Table version: 2.0
+# Table format: Format A
+# Date: 1999 July 27 (header updated: 2015 December 02)
+# Authors: Ken Whistler <ken@unicode.org>
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO/IEC 8859-13:1998 characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO/IEC 8859-13 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO/IEC 8859-13 order.
+#
+# Version history
+# 1.0 version: created
+# 2.0 version: updates to copyright notice and terms of use; no
+# changes to character mappings
+#
+# Updated versions of this file may be found in:
+# http://www.unicode.org/Public/MAPPINGS/
+#
+# Any comments or problems, contact us at:
+# http://www.unicode.org/reporting.html
+#
+0x00 0x0000 # NULL
+0x01 0x0001 # START OF HEADING
+0x02 0x0002 # START OF TEXT
+0x03 0x0003 # END OF TEXT
+0x04 0x0004 # END OF TRANSMISSION
+0x05 0x0005 # ENQUIRY
+0x06 0x0006 # ACKNOWLEDGE
+0x07 0x0007 # BELL
+0x08 0x0008 # BACKSPACE
+0x09 0x0009 # HORIZONTAL TABULATION
+0x0A 0x000A # LINE FEED
+0x0B 0x000B # VERTICAL TABULATION
+0x0C 0x000C # FORM FEED
+0x0D 0x000D # CARRIAGE RETURN
+0x0E 0x000E # SHIFT OUT
+0x0F 0x000F # SHIFT IN
+0x10 0x0010 # DATA LINK ESCAPE
+0x11 0x0011 # DEVICE CONTROL ONE
+0x12 0x0012 # DEVICE CONTROL TWO
+0x13 0x0013 # DEVICE CONTROL THREE
+0x14 0x0014 # DEVICE CONTROL FOUR
+0x15 0x0015 # NEGATIVE ACKNOWLEDGE
+0x16 0x0016 # SYNCHRONOUS IDLE
+0x17 0x0017 # END OF TRANSMISSION BLOCK
+0x18 0x0018 # CANCEL
+0x19 0x0019 # END OF MEDIUM
+0x1A 0x001A # SUBSTITUTE
+0x1B 0x001B # ESCAPE
+0x1C 0x001C # FILE SEPARATOR
+0x1D 0x001D # GROUP SEPARATOR
+0x1E 0x001E # RECORD SEPARATOR
+0x1F 0x001F # UNIT SEPARATOR
+0x20 0x0020 # SPACE
+0x21 0x0021 # EXCLAMATION MARK
+0x22 0x0022 # QUOTATION MARK
+0x23 0x0023 # NUMBER SIGN
+0x24 0x0024 # DOLLAR SIGN
+0x25 0x0025 # PERCENT SIGN
+0x26 0x0026 # AMPERSAND
+0x27 0x0027 # APOSTROPHE
+0x28 0x0028 # LEFT PARENTHESIS
+0x29 0x0029 # RIGHT PARENTHESIS
+0x2A 0x002A # ASTERISK
+0x2B 0x002B # PLUS SIGN
+0x2C 0x002C # COMMA
+0x2D 0x002D # HYPHEN-MINUS
+0x2E 0x002E # FULL STOP
+0x2F 0x002F # SOLIDUS
+0x30 0x0030 # DIGIT ZERO
+0x31 0x0031 # DIGIT ONE
+0x32 0x0032 # DIGIT TWO
+0x33 0x0033 # DIGIT THREE
+0x34 0x0034 # DIGIT FOUR
+0x35 0x0035 # DIGIT FIVE
+0x36 0x0036 # DIGIT SIX
+0x37 0x0037 # DIGIT SEVEN
+0x38 0x0038 # DIGIT EIGHT
+0x39 0x0039 # DIGIT NINE
+0x3A 0x003A # COLON
+0x3B 0x003B # SEMICOLON
+0x3C 0x003C # LESS-THAN SIGN
+0x3D 0x003D # EQUALS SIGN
+0x3E 0x003E # GREATER-THAN SIGN
+0x3F 0x003F # QUESTION MARK
+0x40 0x0040 # COMMERCIAL AT
+0x41 0x0041 # LATIN CAPITAL LETTER A
+0x42 0x0042 # LATIN CAPITAL LETTER B
+0x43 0x0043 # LATIN CAPITAL LETTER C
+0x44 0x0044 # LATIN CAPITAL LETTER D
+0x45 0x0045 # LATIN CAPITAL LETTER E
+0x46 0x0046 # LATIN CAPITAL LETTER F
+0x47 0x0047 # LATIN CAPITAL LETTER G
+0x48 0x0048 # LATIN CAPITAL LETTER H
+0x49 0x0049 # LATIN CAPITAL LETTER I
+0x4A 0x004A # LATIN CAPITAL LETTER J
+0x4B 0x004B # LATIN CAPITAL LETTER K
+0x4C 0x004C # LATIN CAPITAL LETTER L
+0x4D 0x004D # LATIN CAPITAL LETTER M
+0x4E 0x004E # LATIN CAPITAL LETTER N
+0x4F 0x004F # LATIN CAPITAL LETTER O
+0x50 0x0050 # LATIN CAPITAL LETTER P
+0x51 0x0051 # LATIN CAPITAL LETTER Q
+0x52 0x0052 # LATIN CAPITAL LETTER R
+0x53 0x0053 # LATIN CAPITAL LETTER S
+0x54 0x0054 # LATIN CAPITAL LETTER T
+0x55 0x0055 # LATIN CAPITAL LETTER U
+0x56 0x0056 # LATIN CAPITAL LETTER V
+0x57 0x0057 # LATIN CAPITAL LETTER W
+0x58 0x0058 # LATIN CAPITAL LETTER X
+0x59 0x0059 # LATIN CAPITAL LETTER Y
+0x5A 0x005A # LATIN CAPITAL LETTER Z
+0x5B 0x005B # LEFT SQUARE BRACKET
+0x5C 0x005C # REVERSE SOLIDUS
+0x5D 0x005D # RIGHT SQUARE BRACKET
+0x5E 0x005E # CIRCUMFLEX ACCENT
+0x5F 0x005F # LOW LINE
+0x60 0x0060 # GRAVE ACCENT
+0x61 0x0061 # LATIN SMALL LETTER A
+0x62 0x0062 # LATIN SMALL LETTER B
+0x63 0x0063 # LATIN SMALL LETTER C
+0x64 0x0064 # LATIN SMALL LETTER D
+0x65 0x0065 # LATIN SMALL LETTER E
+0x66 0x0066 # LATIN SMALL LETTER F
+0x67 0x0067 # LATIN SMALL LETTER G
+0x68 0x0068 # LATIN SMALL LETTER H
+0x69 0x0069 # LATIN SMALL LETTER I
+0x6A 0x006A # LATIN SMALL LETTER J
+0x6B 0x006B # LATIN SMALL LETTER K
+0x6C 0x006C # LATIN SMALL LETTER L
+0x6D 0x006D # LATIN SMALL LETTER M
+0x6E 0x006E # LATIN SMALL LETTER N
+0x6F 0x006F # LATIN SMALL LETTER O
+0x70 0x0070 # LATIN SMALL LETTER P
+0x71 0x0071 # LATIN SMALL LETTER Q
+0x72 0x0072 # LATIN SMALL LETTER R
+0x73 0x0073 # LATIN SMALL LETTER S
+0x74 0x0074 # LATIN SMALL LETTER T
+0x75 0x0075 # LATIN SMALL LETTER U
+0x76 0x0076 # LATIN SMALL LETTER V
+0x77 0x0077 # LATIN SMALL LETTER W
+0x78 0x0078 # LATIN SMALL LETTER X
+0x79 0x0079 # LATIN SMALL LETTER Y
+0x7A 0x007A # LATIN SMALL LETTER Z
+0x7B 0x007B # LEFT CURLY BRACKET
+0x7C 0x007C # VERTICAL LINE
+0x7D 0x007D # RIGHT CURLY BRACKET
+0x7E 0x007E # TILDE
+0x7F 0x007F # DELETE
+0x80 0x0080 # <control>
+0x81 0x0081 # <control>
+0x82 0x0082 # <control>
+0x83 0x0083 # <control>
+0x84 0x0084 # <control>
+0x85 0x0085 # <control>
+0x86 0x0086 # <control>
+0x87 0x0087 # <control>
+0x88 0x0088 # <control>
+0x89 0x0089 # <control>
+0x8A 0x008A # <control>
+0x8B 0x008B # <control>
+0x8C 0x008C # <control>
+0x8D 0x008D # <control>
+0x8E 0x008E # <control>
+0x8F 0x008F # <control>
+0x90 0x0090 # <control>
+0x91 0x0091 # <control>
+0x92 0x0092 # <control>
+0x93 0x0093 # <control>
+0x94 0x0094 # <control>
+0x95 0x0095 # <control>
+0x96 0x0096 # <control>
+0x97 0x0097 # <control>
+0x98 0x0098 # <control>
+0x99 0x0099 # <control>
+0x9A 0x009A # <control>
+0x9B 0x009B # <control>
+0x9C 0x009C # <control>
+0x9D 0x009D # <control>
+0x9E 0x009E # <control>
+0x9F 0x009F # <control>
+0xA0 0x00A0 # NO-BREAK SPACE
+0xA1 0x201D # RIGHT DOUBLE QUOTATION MARK
+0xA2 0x00A2 # CENT SIGN
+0xA3 0x00A3 # POUND SIGN
+0xA4 0x00A4 # CURRENCY SIGN
+0xA5 0x201E # DOUBLE LOW-9 QUOTATION MARK
+0xA6 0x00A6 # BROKEN BAR
+0xA7 0x00A7 # SECTION SIGN
+0xA8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE
+0xA9 0x00A9 # COPYRIGHT SIGN
+0xAA 0x0156 # LATIN CAPITAL LETTER R WITH CEDILLA
+0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC 0x00AC # NOT SIGN
+0xAD 0x00AD # SOFT HYPHEN
+0xAE 0x00AE # REGISTERED SIGN
+0xAF 0x00C6 # LATIN CAPITAL LETTER AE
+0xB0 0x00B0 # DEGREE SIGN
+0xB1 0x00B1 # PLUS-MINUS SIGN
+0xB2 0x00B2 # SUPERSCRIPT TWO
+0xB3 0x00B3 # SUPERSCRIPT THREE
+0xB4 0x201C # LEFT DOUBLE QUOTATION MARK
+0xB5 0x00B5 # MICRO SIGN
+0xB6 0x00B6 # PILCROW SIGN
+0xB7 0x00B7 # MIDDLE DOT
+0xB8 0x00F8 # LATIN SMALL LETTER O WITH STROKE
+0xB9 0x00B9 # SUPERSCRIPT ONE
+0xBA 0x0157 # LATIN SMALL LETTER R WITH CEDILLA
+0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC 0x00BC # VULGAR FRACTION ONE QUARTER
+0xBD 0x00BD # VULGAR FRACTION ONE HALF
+0xBE 0x00BE # VULGAR FRACTION THREE QUARTERS
+0xBF 0x00E6 # LATIN SMALL LETTER AE
+0xC0 0x0104 # LATIN CAPITAL LETTER A WITH OGONEK
+0xC1 0x012E # LATIN CAPITAL LETTER I WITH OGONEK
+0xC2 0x0100 # LATIN CAPITAL LETTER A WITH MACRON
+0xC3 0x0106 # LATIN CAPITAL LETTER C WITH ACUTE
+0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6 0x0118 # LATIN CAPITAL LETTER E WITH OGONEK
+0xC7 0x0112 # LATIN CAPITAL LETTER E WITH MACRON
+0xC8 0x010C # LATIN CAPITAL LETTER C WITH CARON
+0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE
+0xCA 0x0179 # LATIN CAPITAL LETTER Z WITH ACUTE
+0xCB 0x0116 # LATIN CAPITAL LETTER E WITH DOT ABOVE
+0xCC 0x0122 # LATIN CAPITAL LETTER G WITH CEDILLA
+0xCD 0x0136 # LATIN CAPITAL LETTER K WITH CEDILLA
+0xCE 0x012A # LATIN CAPITAL LETTER I WITH MACRON
+0xCF 0x013B # LATIN CAPITAL LETTER L WITH CEDILLA
+0xD0 0x0160 # LATIN CAPITAL LETTER S WITH CARON
+0xD1 0x0143 # LATIN CAPITAL LETTER N WITH ACUTE
+0xD2 0x0145 # LATIN CAPITAL LETTER N WITH CEDILLA
+0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE
+0xD4 0x014C # LATIN CAPITAL LETTER O WITH MACRON
+0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE
+0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7 0x00D7 # MULTIPLICATION SIGN
+0xD8 0x0172 # LATIN CAPITAL LETTER U WITH OGONEK
+0xD9 0x0141 # LATIN CAPITAL LETTER L WITH STROKE
+0xDA 0x015A # LATIN CAPITAL LETTER S WITH ACUTE
+0xDB 0x016A # LATIN CAPITAL LETTER U WITH MACRON
+0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD 0x017B # LATIN CAPITAL LETTER Z WITH DOT ABOVE
+0xDE 0x017D # LATIN CAPITAL LETTER Z WITH CARON
+0xDF 0x00DF # LATIN SMALL LETTER SHARP S (German)
+0xE0 0x0105 # LATIN SMALL LETTER A WITH OGONEK
+0xE1 0x012F # LATIN SMALL LETTER I WITH OGONEK
+0xE2 0x0101 # LATIN SMALL LETTER A WITH MACRON
+0xE3 0x0107 # LATIN SMALL LETTER C WITH ACUTE
+0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS
+0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE
+0xE6 0x0119 # LATIN SMALL LETTER E WITH OGONEK
+0xE7 0x0113 # LATIN SMALL LETTER E WITH MACRON
+0xE8 0x010D # LATIN SMALL LETTER C WITH CARON
+0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE
+0xEA 0x017A # LATIN SMALL LETTER Z WITH ACUTE
+0xEB 0x0117 # LATIN SMALL LETTER E WITH DOT ABOVE
+0xEC 0x0123 # LATIN SMALL LETTER G WITH CEDILLA
+0xED 0x0137 # LATIN SMALL LETTER K WITH CEDILLA
+0xEE 0x012B # LATIN SMALL LETTER I WITH MACRON
+0xEF 0x013C # LATIN SMALL LETTER L WITH CEDILLA
+0xF0 0x0161 # LATIN SMALL LETTER S WITH CARON
+0xF1 0x0144 # LATIN SMALL LETTER N WITH ACUTE
+0xF2 0x0146 # LATIN SMALL LETTER N WITH CEDILLA
+0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE
+0xF4 0x014D # LATIN SMALL LETTER O WITH MACRON
+0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE
+0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS
+0xF7 0x00F7 # DIVISION SIGN
+0xF8 0x0173 # LATIN SMALL LETTER U WITH OGONEK
+0xF9 0x0142 # LATIN SMALL LETTER L WITH STROKE
+0xFA 0x015B # LATIN SMALL LETTER S WITH ACUTE
+0xFB 0x016B # LATIN SMALL LETTER U WITH MACRON
+0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS
+0xFD 0x017C # LATIN SMALL LETTER Z WITH DOT ABOVE
+0xFE 0x017E # LATIN SMALL LETTER Z WITH CARON
+0xFF 0x2019 # RIGHT SINGLE QUOTATION MARK
diff --git a/ext/mbstring/tests/data/8859-14.txt b/ext/mbstring/tests/data/8859-14.txt
new file mode 100644
index 0000000000..3c3a02466b
--- /dev/null
+++ b/ext/mbstring/tests/data/8859-14.txt
@@ -0,0 +1,292 @@
+# 8859-14.TXT
+# Date: 2015-12-02 22:05:00 GMT [KW]
+# © 2015 Unicode®, Inc.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
+#
+# Name: ISO/IEC 8859-14:1998 to Unicode
+# Unicode version: 3.0
+# Table version: 2.0
+# Table format: Format A
+# Date: 1999 July 27 (header updated: 2015 December 02)
+# Authors: Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>
+# Ken Whistler <ken@unicode.org>
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO/IEC 8859-14:1998 characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO/IEC 8859-14 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO/IEC 8859-14 order.
+#
+# Version history
+# 1.0 version: created
+# 2.0 version: updates to copyright notice and terms of use; no
+# changes to character mappings
+#
+# Updated versions of this file may be found in:
+# http://www.unicode.org/Public/MAPPINGS/
+#
+# Any comments or problems, contact us at:
+# http://www.unicode.org/reporting.html
+#
+0x00 0x0000 # NULL
+0x01 0x0001 # START OF HEADING
+0x02 0x0002 # START OF TEXT
+0x03 0x0003 # END OF TEXT
+0x04 0x0004 # END OF TRANSMISSION
+0x05 0x0005 # ENQUIRY
+0x06 0x0006 # ACKNOWLEDGE
+0x07 0x0007 # BELL
+0x08 0x0008 # BACKSPACE
+0x09 0x0009 # HORIZONTAL TABULATION
+0x0A 0x000A # LINE FEED
+0x0B 0x000B # VERTICAL TABULATION
+0x0C 0x000C # FORM FEED
+0x0D 0x000D # CARRIAGE RETURN
+0x0E 0x000E # SHIFT OUT
+0x0F 0x000F # SHIFT IN
+0x10 0x0010 # DATA LINK ESCAPE
+0x11 0x0011 # DEVICE CONTROL ONE
+0x12 0x0012 # DEVICE CONTROL TWO
+0x13 0x0013 # DEVICE CONTROL THREE
+0x14 0x0014 # DEVICE CONTROL FOUR
+0x15 0x0015 # NEGATIVE ACKNOWLEDGE
+0x16 0x0016 # SYNCHRONOUS IDLE
+0x17 0x0017 # END OF TRANSMISSION BLOCK
+0x18 0x0018 # CANCEL
+0x19 0x0019 # END OF MEDIUM
+0x1A 0x001A # SUBSTITUTE
+0x1B 0x001B # ESCAPE
+0x1C 0x001C # FILE SEPARATOR
+0x1D 0x001D # GROUP SEPARATOR
+0x1E 0x001E # RECORD SEPARATOR
+0x1F 0x001F # UNIT SEPARATOR
+0x20 0x0020 # SPACE
+0x21 0x0021 # EXCLAMATION MARK
+0x22 0x0022 # QUOTATION MARK
+0x23 0x0023 # NUMBER SIGN
+0x24 0x0024 # DOLLAR SIGN
+0x25 0x0025 # PERCENT SIGN
+0x26 0x0026 # AMPERSAND
+0x27 0x0027 # APOSTROPHE
+0x28 0x0028 # LEFT PARENTHESIS
+0x29 0x0029 # RIGHT PARENTHESIS
+0x2A 0x002A # ASTERISK
+0x2B 0x002B # PLUS SIGN
+0x2C 0x002C # COMMA
+0x2D 0x002D # HYPHEN-MINUS
+0x2E 0x002E # FULL STOP
+0x2F 0x002F # SOLIDUS
+0x30 0x0030 # DIGIT ZERO
+0x31 0x0031 # DIGIT ONE
+0x32 0x0032 # DIGIT TWO
+0x33 0x0033 # DIGIT THREE
+0x34 0x0034 # DIGIT FOUR
+0x35 0x0035 # DIGIT FIVE
+0x36 0x0036 # DIGIT SIX
+0x37 0x0037 # DIGIT SEVEN
+0x38 0x0038 # DIGIT EIGHT
+0x39 0x0039 # DIGIT NINE
+0x3A 0x003A # COLON
+0x3B 0x003B # SEMICOLON
+0x3C 0x003C # LESS-THAN SIGN
+0x3D 0x003D # EQUALS SIGN
+0x3E 0x003E # GREATER-THAN SIGN
+0x3F 0x003F # QUESTION MARK
+0x40 0x0040 # COMMERCIAL AT
+0x41 0x0041 # LATIN CAPITAL LETTER A
+0x42 0x0042 # LATIN CAPITAL LETTER B
+0x43 0x0043 # LATIN CAPITAL LETTER C
+0x44 0x0044 # LATIN CAPITAL LETTER D
+0x45 0x0045 # LATIN CAPITAL LETTER E
+0x46 0x0046 # LATIN CAPITAL LETTER F
+0x47 0x0047 # LATIN CAPITAL LETTER G
+0x48 0x0048 # LATIN CAPITAL LETTER H
+0x49 0x0049 # LATIN CAPITAL LETTER I
+0x4A 0x004A # LATIN CAPITAL LETTER J
+0x4B 0x004B # LATIN CAPITAL LETTER K
+0x4C 0x004C # LATIN CAPITAL LETTER L
+0x4D 0x004D # LATIN CAPITAL LETTER M
+0x4E 0x004E # LATIN CAPITAL LETTER N
+0x4F 0x004F # LATIN CAPITAL LETTER O
+0x50 0x0050 # LATIN CAPITAL LETTER P
+0x51 0x0051 # LATIN CAPITAL LETTER Q
+0x52 0x0052 # LATIN CAPITAL LETTER R
+0x53 0x0053 # LATIN CAPITAL LETTER S
+0x54 0x0054 # LATIN CAPITAL LETTER T
+0x55 0x0055 # LATIN CAPITAL LETTER U
+0x56 0x0056 # LATIN CAPITAL LETTER V
+0x57 0x0057 # LATIN CAPITAL LETTER W
+0x58 0x0058 # LATIN CAPITAL LETTER X
+0x59 0x0059 # LATIN CAPITAL LETTER Y
+0x5A 0x005A # LATIN CAPITAL LETTER Z
+0x5B 0x005B # LEFT SQUARE BRACKET
+0x5C 0x005C # REVERSE SOLIDUS
+0x5D 0x005D # RIGHT SQUARE BRACKET
+0x5E 0x005E # CIRCUMFLEX ACCENT
+0x5F 0x005F # LOW LINE
+0x60 0x0060 # GRAVE ACCENT
+0x61 0x0061 # LATIN SMALL LETTER A
+0x62 0x0062 # LATIN SMALL LETTER B
+0x63 0x0063 # LATIN SMALL LETTER C
+0x64 0x0064 # LATIN SMALL LETTER D
+0x65 0x0065 # LATIN SMALL LETTER E
+0x66 0x0066 # LATIN SMALL LETTER F
+0x67 0x0067 # LATIN SMALL LETTER G
+0x68 0x0068 # LATIN SMALL LETTER H
+0x69 0x0069 # LATIN SMALL LETTER I
+0x6A 0x006A # LATIN SMALL LETTER J
+0x6B 0x006B # LATIN SMALL LETTER K
+0x6C 0x006C # LATIN SMALL LETTER L
+0x6D 0x006D # LATIN SMALL LETTER M
+0x6E 0x006E # LATIN SMALL LETTER N
+0x6F 0x006F # LATIN SMALL LETTER O
+0x70 0x0070 # LATIN SMALL LETTER P
+0x71 0x0071 # LATIN SMALL LETTER Q
+0x72 0x0072 # LATIN SMALL LETTER R
+0x73 0x0073 # LATIN SMALL LETTER S
+0x74 0x0074 # LATIN SMALL LETTER T
+0x75 0x0075 # LATIN SMALL LETTER U
+0x76 0x0076 # LATIN SMALL LETTER V
+0x77 0x0077 # LATIN SMALL LETTER W
+0x78 0x0078 # LATIN SMALL LETTER X
+0x79 0x0079 # LATIN SMALL LETTER Y
+0x7A 0x007A # LATIN SMALL LETTER Z
+0x7B 0x007B # LEFT CURLY BRACKET
+0x7C 0x007C # VERTICAL LINE
+0x7D 0x007D # RIGHT CURLY BRACKET
+0x7E 0x007E # TILDE
+0x7F 0x007F # DELETE
+0x80 0x0080 # <control>
+0x81 0x0081 # <control>
+0x82 0x0082 # <control>
+0x83 0x0083 # <control>
+0x84 0x0084 # <control>
+0x85 0x0085 # <control>
+0x86 0x0086 # <control>
+0x87 0x0087 # <control>
+0x88 0x0088 # <control>
+0x89 0x0089 # <control>
+0x8A 0x008A # <control>
+0x8B 0x008B # <control>
+0x8C 0x008C # <control>
+0x8D 0x008D # <control>
+0x8E 0x008E # <control>
+0x8F 0x008F # <control>
+0x90 0x0090 # <control>
+0x91 0x0091 # <control>
+0x92 0x0092 # <control>
+0x93 0x0093 # <control>
+0x94 0x0094 # <control>
+0x95 0x0095 # <control>
+0x96 0x0096 # <control>
+0x97 0x0097 # <control>
+0x98 0x0098 # <control>
+0x99 0x0099 # <control>
+0x9A 0x009A # <control>
+0x9B 0x009B # <control>
+0x9C 0x009C # <control>
+0x9D 0x009D # <control>
+0x9E 0x009E # <control>
+0x9F 0x009F # <control>
+0xA0 0x00A0 # NO-BREAK SPACE
+0xA1 0x1E02 # LATIN CAPITAL LETTER B WITH DOT ABOVE
+0xA2 0x1E03 # LATIN SMALL LETTER B WITH DOT ABOVE
+0xA3 0x00A3 # POUND SIGN
+0xA4 0x010A # LATIN CAPITAL LETTER C WITH DOT ABOVE
+0xA5 0x010B # LATIN SMALL LETTER C WITH DOT ABOVE
+0xA6 0x1E0A # LATIN CAPITAL LETTER D WITH DOT ABOVE
+0xA7 0x00A7 # SECTION SIGN
+0xA8 0x1E80 # LATIN CAPITAL LETTER W WITH GRAVE
+0xA9 0x00A9 # COPYRIGHT SIGN
+0xAA 0x1E82 # LATIN CAPITAL LETTER W WITH ACUTE
+0xAB 0x1E0B # LATIN SMALL LETTER D WITH DOT ABOVE
+0xAC 0x1EF2 # LATIN CAPITAL LETTER Y WITH GRAVE
+0xAD 0x00AD # SOFT HYPHEN
+0xAE 0x00AE # REGISTERED SIGN
+0xAF 0x0178 # LATIN CAPITAL LETTER Y WITH DIAERESIS
+0xB0 0x1E1E # LATIN CAPITAL LETTER F WITH DOT ABOVE
+0xB1 0x1E1F # LATIN SMALL LETTER F WITH DOT ABOVE
+0xB2 0x0120 # LATIN CAPITAL LETTER G WITH DOT ABOVE
+0xB3 0x0121 # LATIN SMALL LETTER G WITH DOT ABOVE
+0xB4 0x1E40 # LATIN CAPITAL LETTER M WITH DOT ABOVE
+0xB5 0x1E41 # LATIN SMALL LETTER M WITH DOT ABOVE
+0xB6 0x00B6 # PILCROW SIGN
+0xB7 0x1E56 # LATIN CAPITAL LETTER P WITH DOT ABOVE
+0xB8 0x1E81 # LATIN SMALL LETTER W WITH GRAVE
+0xB9 0x1E57 # LATIN SMALL LETTER P WITH DOT ABOVE
+0xBA 0x1E83 # LATIN SMALL LETTER W WITH ACUTE
+0xBB 0x1E60 # LATIN CAPITAL LETTER S WITH DOT ABOVE
+0xBC 0x1EF3 # LATIN SMALL LETTER Y WITH GRAVE
+0xBD 0x1E84 # LATIN CAPITAL LETTER W WITH DIAERESIS
+0xBE 0x1E85 # LATIN SMALL LETTER W WITH DIAERESIS
+0xBF 0x1E61 # LATIN SMALL LETTER S WITH DOT ABOVE
+0xC0 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE
+0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE
+0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE
+0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6 0x00C6 # LATIN CAPITAL LETTER AE
+0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE
+0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE
+0xCA 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE
+0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE
+0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD0 0x0174 # LATIN CAPITAL LETTER W WITH CIRCUMFLEX
+0xD1 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE
+0xD2 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE
+0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE
+0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE
+0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7 0x1E6A # LATIN CAPITAL LETTER T WITH DOT ABOVE
+0xD8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE
+0xD9 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE
+0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE
+0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE
+0xDE 0x0176 # LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
+0xDF 0x00DF # LATIN SMALL LETTER SHARP S
+0xE0 0x00E0 # LATIN SMALL LETTER A WITH GRAVE
+0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE
+0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3 0x00E3 # LATIN SMALL LETTER A WITH TILDE
+0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS
+0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE
+0xE6 0x00E6 # LATIN SMALL LETTER AE
+0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA
+0xE8 0x00E8 # LATIN SMALL LETTER E WITH GRAVE
+0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE
+0xEA 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS
+0xEC 0x00EC # LATIN SMALL LETTER I WITH GRAVE
+0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE
+0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS
+0xF0 0x0175 # LATIN SMALL LETTER W WITH CIRCUMFLEX
+0xF1 0x00F1 # LATIN SMALL LETTER N WITH TILDE
+0xF2 0x00F2 # LATIN SMALL LETTER O WITH GRAVE
+0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE
+0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE
+0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS
+0xF7 0x1E6B # LATIN SMALL LETTER T WITH DOT ABOVE
+0xF8 0x00F8 # LATIN SMALL LETTER O WITH STROKE
+0xF9 0x00F9 # LATIN SMALL LETTER U WITH GRAVE
+0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE
+0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS
+0xFD 0x00FD # LATIN SMALL LETTER Y WITH ACUTE
+0xFE 0x0177 # LATIN SMALL LETTER Y WITH CIRCUMFLEX
+0xFF 0x00FF # LATIN SMALL LETTER Y WITH DIAERESIS
diff --git a/ext/mbstring/tests/data/8859-15.txt b/ext/mbstring/tests/data/8859-15.txt
new file mode 100644
index 0000000000..f21a763600
--- /dev/null
+++ b/ext/mbstring/tests/data/8859-15.txt
@@ -0,0 +1,294 @@
+# 8859-15.TXT
+# Date: 2015-12-02 22:06:00 GMT [KW]
+# © 2015 Unicode®, Inc.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
+#
+# Name: ISO/IEC 8859-15:1999 to Unicode
+# Unicode version: 3.0
+# Table version: 2.0
+# Table format: Format A
+# Date: 1999 July 27 (header updated: 2015 December 02)
+# Authors: Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>
+# Ken Whistler <ken@unicode.org>
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO/IEC 8859-15:1999 characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO/IEC 8859-15 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO/IEC 8859-15 order.
+#
+# Version history
+#
+# Version history
+# 1.0 version: created
+# 2.0 version: updates to copyright notice and terms of use; no
+# changes to character mappings
+#
+# Updated versions of this file may be found in:
+# http://www.unicode.org/Public/MAPPINGS/
+#
+# Any comments or problems, contact us at:
+# http://www.unicode.org/reporting.html
+#
+0x00 0x0000 # NULL
+0x01 0x0001 # START OF HEADING
+0x02 0x0002 # START OF TEXT
+0x03 0x0003 # END OF TEXT
+0x04 0x0004 # END OF TRANSMISSION
+0x05 0x0005 # ENQUIRY
+0x06 0x0006 # ACKNOWLEDGE
+0x07 0x0007 # BELL
+0x08 0x0008 # BACKSPACE
+0x09 0x0009 # HORIZONTAL TABULATION
+0x0A 0x000A # LINE FEED
+0x0B 0x000B # VERTICAL TABULATION
+0x0C 0x000C # FORM FEED
+0x0D 0x000D # CARRIAGE RETURN
+0x0E 0x000E # SHIFT OUT
+0x0F 0x000F # SHIFT IN
+0x10 0x0010 # DATA LINK ESCAPE
+0x11 0x0011 # DEVICE CONTROL ONE
+0x12 0x0012 # DEVICE CONTROL TWO
+0x13 0x0013 # DEVICE CONTROL THREE
+0x14 0x0014 # DEVICE CONTROL FOUR
+0x15 0x0015 # NEGATIVE ACKNOWLEDGE
+0x16 0x0016 # SYNCHRONOUS IDLE
+0x17 0x0017 # END OF TRANSMISSION BLOCK
+0x18 0x0018 # CANCEL
+0x19 0x0019 # END OF MEDIUM
+0x1A 0x001A # SUBSTITUTE
+0x1B 0x001B # ESCAPE
+0x1C 0x001C # FILE SEPARATOR
+0x1D 0x001D # GROUP SEPARATOR
+0x1E 0x001E # RECORD SEPARATOR
+0x1F 0x001F # UNIT SEPARATOR
+0x20 0x0020 # SPACE
+0x21 0x0021 # EXCLAMATION MARK
+0x22 0x0022 # QUOTATION MARK
+0x23 0x0023 # NUMBER SIGN
+0x24 0x0024 # DOLLAR SIGN
+0x25 0x0025 # PERCENT SIGN
+0x26 0x0026 # AMPERSAND
+0x27 0x0027 # APOSTROPHE
+0x28 0x0028 # LEFT PARENTHESIS
+0x29 0x0029 # RIGHT PARENTHESIS
+0x2A 0x002A # ASTERISK
+0x2B 0x002B # PLUS SIGN
+0x2C 0x002C # COMMA
+0x2D 0x002D # HYPHEN-MINUS
+0x2E 0x002E # FULL STOP
+0x2F 0x002F # SOLIDUS
+0x30 0x0030 # DIGIT ZERO
+0x31 0x0031 # DIGIT ONE
+0x32 0x0032 # DIGIT TWO
+0x33 0x0033 # DIGIT THREE
+0x34 0x0034 # DIGIT FOUR
+0x35 0x0035 # DIGIT FIVE
+0x36 0x0036 # DIGIT SIX
+0x37 0x0037 # DIGIT SEVEN
+0x38 0x0038 # DIGIT EIGHT
+0x39 0x0039 # DIGIT NINE
+0x3A 0x003A # COLON
+0x3B 0x003B # SEMICOLON
+0x3C 0x003C # LESS-THAN SIGN
+0x3D 0x003D # EQUALS SIGN
+0x3E 0x003E # GREATER-THAN SIGN
+0x3F 0x003F # QUESTION MARK
+0x40 0x0040 # COMMERCIAL AT
+0x41 0x0041 # LATIN CAPITAL LETTER A
+0x42 0x0042 # LATIN CAPITAL LETTER B
+0x43 0x0043 # LATIN CAPITAL LETTER C
+0x44 0x0044 # LATIN CAPITAL LETTER D
+0x45 0x0045 # LATIN CAPITAL LETTER E
+0x46 0x0046 # LATIN CAPITAL LETTER F
+0x47 0x0047 # LATIN CAPITAL LETTER G
+0x48 0x0048 # LATIN CAPITAL LETTER H
+0x49 0x0049 # LATIN CAPITAL LETTER I
+0x4A 0x004A # LATIN CAPITAL LETTER J
+0x4B 0x004B # LATIN CAPITAL LETTER K
+0x4C 0x004C # LATIN CAPITAL LETTER L
+0x4D 0x004D # LATIN CAPITAL LETTER M
+0x4E 0x004E # LATIN CAPITAL LETTER N
+0x4F 0x004F # LATIN CAPITAL LETTER O
+0x50 0x0050 # LATIN CAPITAL LETTER P
+0x51 0x0051 # LATIN CAPITAL LETTER Q
+0x52 0x0052 # LATIN CAPITAL LETTER R
+0x53 0x0053 # LATIN CAPITAL LETTER S
+0x54 0x0054 # LATIN CAPITAL LETTER T
+0x55 0x0055 # LATIN CAPITAL LETTER U
+0x56 0x0056 # LATIN CAPITAL LETTER V
+0x57 0x0057 # LATIN CAPITAL LETTER W
+0x58 0x0058 # LATIN CAPITAL LETTER X
+0x59 0x0059 # LATIN CAPITAL LETTER Y
+0x5A 0x005A # LATIN CAPITAL LETTER Z
+0x5B 0x005B # LEFT SQUARE BRACKET
+0x5C 0x005C # REVERSE SOLIDUS
+0x5D 0x005D # RIGHT SQUARE BRACKET
+0x5E 0x005E # CIRCUMFLEX ACCENT
+0x5F 0x005F # LOW LINE
+0x60 0x0060 # GRAVE ACCENT
+0x61 0x0061 # LATIN SMALL LETTER A
+0x62 0x0062 # LATIN SMALL LETTER B
+0x63 0x0063 # LATIN SMALL LETTER C
+0x64 0x0064 # LATIN SMALL LETTER D
+0x65 0x0065 # LATIN SMALL LETTER E
+0x66 0x0066 # LATIN SMALL LETTER F
+0x67 0x0067 # LATIN SMALL LETTER G
+0x68 0x0068 # LATIN SMALL LETTER H
+0x69 0x0069 # LATIN SMALL LETTER I
+0x6A 0x006A # LATIN SMALL LETTER J
+0x6B 0x006B # LATIN SMALL LETTER K
+0x6C 0x006C # LATIN SMALL LETTER L
+0x6D 0x006D # LATIN SMALL LETTER M
+0x6E 0x006E # LATIN SMALL LETTER N
+0x6F 0x006F # LATIN SMALL LETTER O
+0x70 0x0070 # LATIN SMALL LETTER P
+0x71 0x0071 # LATIN SMALL LETTER Q
+0x72 0x0072 # LATIN SMALL LETTER R
+0x73 0x0073 # LATIN SMALL LETTER S
+0x74 0x0074 # LATIN SMALL LETTER T
+0x75 0x0075 # LATIN SMALL LETTER U
+0x76 0x0076 # LATIN SMALL LETTER V
+0x77 0x0077 # LATIN SMALL LETTER W
+0x78 0x0078 # LATIN SMALL LETTER X
+0x79 0x0079 # LATIN SMALL LETTER Y
+0x7A 0x007A # LATIN SMALL LETTER Z
+0x7B 0x007B # LEFT CURLY BRACKET
+0x7C 0x007C # VERTICAL LINE
+0x7D 0x007D # RIGHT CURLY BRACKET
+0x7E 0x007E # TILDE
+0x7F 0x007F # DELETE
+0x80 0x0080 # <control>
+0x81 0x0081 # <control>
+0x82 0x0082 # <control>
+0x83 0x0083 # <control>
+0x84 0x0084 # <control>
+0x85 0x0085 # <control>
+0x86 0x0086 # <control>
+0x87 0x0087 # <control>
+0x88 0x0088 # <control>
+0x89 0x0089 # <control>
+0x8A 0x008A # <control>
+0x8B 0x008B # <control>
+0x8C 0x008C # <control>
+0x8D 0x008D # <control>
+0x8E 0x008E # <control>
+0x8F 0x008F # <control>
+0x90 0x0090 # <control>
+0x91 0x0091 # <control>
+0x92 0x0092 # <control>
+0x93 0x0093 # <control>
+0x94 0x0094 # <control>
+0x95 0x0095 # <control>
+0x96 0x0096 # <control>
+0x97 0x0097 # <control>
+0x98 0x0098 # <control>
+0x99 0x0099 # <control>
+0x9A 0x009A # <control>
+0x9B 0x009B # <control>
+0x9C 0x009C # <control>
+0x9D 0x009D # <control>
+0x9E 0x009E # <control>
+0x9F 0x009F # <control>
+0xA0 0x00A0 # NO-BREAK SPACE
+0xA1 0x00A1 # INVERTED EXCLAMATION MARK
+0xA2 0x00A2 # CENT SIGN
+0xA3 0x00A3 # POUND SIGN
+0xA4 0x20AC # EURO SIGN
+0xA5 0x00A5 # YEN SIGN
+0xA6 0x0160 # LATIN CAPITAL LETTER S WITH CARON
+0xA7 0x00A7 # SECTION SIGN
+0xA8 0x0161 # LATIN SMALL LETTER S WITH CARON
+0xA9 0x00A9 # COPYRIGHT SIGN
+0xAA 0x00AA # FEMININE ORDINAL INDICATOR
+0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC 0x00AC # NOT SIGN
+0xAD 0x00AD # SOFT HYPHEN
+0xAE 0x00AE # REGISTERED SIGN
+0xAF 0x00AF # MACRON
+0xB0 0x00B0 # DEGREE SIGN
+0xB1 0x00B1 # PLUS-MINUS SIGN
+0xB2 0x00B2 # SUPERSCRIPT TWO
+0xB3 0x00B3 # SUPERSCRIPT THREE
+0xB4 0x017D # LATIN CAPITAL LETTER Z WITH CARON
+0xB5 0x00B5 # MICRO SIGN
+0xB6 0x00B6 # PILCROW SIGN
+0xB7 0x00B7 # MIDDLE DOT
+0xB8 0x017E # LATIN SMALL LETTER Z WITH CARON
+0xB9 0x00B9 # SUPERSCRIPT ONE
+0xBA 0x00BA # MASCULINE ORDINAL INDICATOR
+0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC 0x0152 # LATIN CAPITAL LIGATURE OE
+0xBD 0x0153 # LATIN SMALL LIGATURE OE
+0xBE 0x0178 # LATIN CAPITAL LETTER Y WITH DIAERESIS
+0xBF 0x00BF # INVERTED QUESTION MARK
+0xC0 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE
+0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE
+0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE
+0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6 0x00C6 # LATIN CAPITAL LETTER AE
+0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE
+0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE
+0xCA 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE
+0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE
+0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD0 0x00D0 # LATIN CAPITAL LETTER ETH
+0xD1 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE
+0xD2 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE
+0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE
+0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE
+0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7 0x00D7 # MULTIPLICATION SIGN
+0xD8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE
+0xD9 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE
+0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE
+0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE
+0xDE 0x00DE # LATIN CAPITAL LETTER THORN
+0xDF 0x00DF # LATIN SMALL LETTER SHARP S
+0xE0 0x00E0 # LATIN SMALL LETTER A WITH GRAVE
+0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE
+0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3 0x00E3 # LATIN SMALL LETTER A WITH TILDE
+0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS
+0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE
+0xE6 0x00E6 # LATIN SMALL LETTER AE
+0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA
+0xE8 0x00E8 # LATIN SMALL LETTER E WITH GRAVE
+0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE
+0xEA 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS
+0xEC 0x00EC # LATIN SMALL LETTER I WITH GRAVE
+0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE
+0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS
+0xF0 0x00F0 # LATIN SMALL LETTER ETH
+0xF1 0x00F1 # LATIN SMALL LETTER N WITH TILDE
+0xF2 0x00F2 # LATIN SMALL LETTER O WITH GRAVE
+0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE
+0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE
+0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS
+0xF7 0x00F7 # DIVISION SIGN
+0xF8 0x00F8 # LATIN SMALL LETTER O WITH STROKE
+0xF9 0x00F9 # LATIN SMALL LETTER U WITH GRAVE
+0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE
+0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS
+0xFD 0x00FD # LATIN SMALL LETTER Y WITH ACUTE
+0xFE 0x00FE # LATIN SMALL LETTER THORN
+0xFF 0x00FF # LATIN SMALL LETTER Y WITH DIAERESIS
diff --git a/ext/mbstring/tests/data/8859-16.txt b/ext/mbstring/tests/data/8859-16.txt
new file mode 100644
index 0000000000..4a05225a78
--- /dev/null
+++ b/ext/mbstring/tests/data/8859-16.txt
@@ -0,0 +1,293 @@
+# 8859-16.TXT
+# Date: 2015-12-02 22:08:00 GMT [KW]
+# © 2015 Unicode®, Inc.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
+#
+# Name: ISO/IEC 8859-16:2001 to Unicode
+# Unicode version: 3.0
+# Table version: 2.0
+# Table format: Format A
+# Date: 2001 July 26 (header updated: 2015 December 02)
+# Authors: Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>
+#
+# Copyright (c) 1999-2001 Unicode, Inc. All Rights reserved.
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO/IEC 8859-16:2001 characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO/IEC 8859-16 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO/IEC 8859-16 order.
+#
+# Version history
+# 1.0 version: created
+# 2.0 version: updates to copyright notice and terms of use; no
+# changes to character mappings
+#
+# Updated versions of this file may be found in:
+# http://www.unicode.org/Public/MAPPINGS/
+#
+# Any comments or problems, contact us at:
+# http://www.unicode.org/reporting.html
+#
+0x00 0x0000 # NULL
+0x01 0x0001 # START OF HEADING
+0x02 0x0002 # START OF TEXT
+0x03 0x0003 # END OF TEXT
+0x04 0x0004 # END OF TRANSMISSION
+0x05 0x0005 # ENQUIRY
+0x06 0x0006 # ACKNOWLEDGE
+0x07 0x0007 # BELL
+0x08 0x0008 # BACKSPACE
+0x09 0x0009 # HORIZONTAL TABULATION
+0x0A 0x000A # LINE FEED
+0x0B 0x000B # VERTICAL TABULATION
+0x0C 0x000C # FORM FEED
+0x0D 0x000D # CARRIAGE RETURN
+0x0E 0x000E # SHIFT OUT
+0x0F 0x000F # SHIFT IN
+0x10 0x0010 # DATA LINK ESCAPE
+0x11 0x0011 # DEVICE CONTROL ONE
+0x12 0x0012 # DEVICE CONTROL TWO
+0x13 0x0013 # DEVICE CONTROL THREE
+0x14 0x0014 # DEVICE CONTROL FOUR
+0x15 0x0015 # NEGATIVE ACKNOWLEDGE
+0x16 0x0016 # SYNCHRONOUS IDLE
+0x17 0x0017 # END OF TRANSMISSION BLOCK
+0x18 0x0018 # CANCEL
+0x19 0x0019 # END OF MEDIUM
+0x1A 0x001A # SUBSTITUTE
+0x1B 0x001B # ESCAPE
+0x1C 0x001C # FILE SEPARATOR
+0x1D 0x001D # GROUP SEPARATOR
+0x1E 0x001E # RECORD SEPARATOR
+0x1F 0x001F # UNIT SEPARATOR
+0x20 0x0020 # SPACE
+0x21 0x0021 # EXCLAMATION MARK
+0x22 0x0022 # QUOTATION MARK
+0x23 0x0023 # NUMBER SIGN
+0x24 0x0024 # DOLLAR SIGN
+0x25 0x0025 # PERCENT SIGN
+0x26 0x0026 # AMPERSAND
+0x27 0x0027 # APOSTROPHE
+0x28 0x0028 # LEFT PARENTHESIS
+0x29 0x0029 # RIGHT PARENTHESIS
+0x2A 0x002A # ASTERISK
+0x2B 0x002B # PLUS SIGN
+0x2C 0x002C # COMMA
+0x2D 0x002D # HYPHEN-MINUS
+0x2E 0x002E # FULL STOP
+0x2F 0x002F # SOLIDUS
+0x30 0x0030 # DIGIT ZERO
+0x31 0x0031 # DIGIT ONE
+0x32 0x0032 # DIGIT TWO
+0x33 0x0033 # DIGIT THREE
+0x34 0x0034 # DIGIT FOUR
+0x35 0x0035 # DIGIT FIVE
+0x36 0x0036 # DIGIT SIX
+0x37 0x0037 # DIGIT SEVEN
+0x38 0x0038 # DIGIT EIGHT
+0x39 0x0039 # DIGIT NINE
+0x3A 0x003A # COLON
+0x3B 0x003B # SEMICOLON
+0x3C 0x003C # LESS-THAN SIGN
+0x3D 0x003D # EQUALS SIGN
+0x3E 0x003E # GREATER-THAN SIGN
+0x3F 0x003F # QUESTION MARK
+0x40 0x0040 # COMMERCIAL AT
+0x41 0x0041 # LATIN CAPITAL LETTER A
+0x42 0x0042 # LATIN CAPITAL LETTER B
+0x43 0x0043 # LATIN CAPITAL LETTER C
+0x44 0x0044 # LATIN CAPITAL LETTER D
+0x45 0x0045 # LATIN CAPITAL LETTER E
+0x46 0x0046 # LATIN CAPITAL LETTER F
+0x47 0x0047 # LATIN CAPITAL LETTER G
+0x48 0x0048 # LATIN CAPITAL LETTER H
+0x49 0x0049 # LATIN CAPITAL LETTER I
+0x4A 0x004A # LATIN CAPITAL LETTER J
+0x4B 0x004B # LATIN CAPITAL LETTER K
+0x4C 0x004C # LATIN CAPITAL LETTER L
+0x4D 0x004D # LATIN CAPITAL LETTER M
+0x4E 0x004E # LATIN CAPITAL LETTER N
+0x4F 0x004F # LATIN CAPITAL LETTER O
+0x50 0x0050 # LATIN CAPITAL LETTER P
+0x51 0x0051 # LATIN CAPITAL LETTER Q
+0x52 0x0052 # LATIN CAPITAL LETTER R
+0x53 0x0053 # LATIN CAPITAL LETTER S
+0x54 0x0054 # LATIN CAPITAL LETTER T
+0x55 0x0055 # LATIN CAPITAL LETTER U
+0x56 0x0056 # LATIN CAPITAL LETTER V
+0x57 0x0057 # LATIN CAPITAL LETTER W
+0x58 0x0058 # LATIN CAPITAL LETTER X
+0x59 0x0059 # LATIN CAPITAL LETTER Y
+0x5A 0x005A # LATIN CAPITAL LETTER Z
+0x5B 0x005B # LEFT SQUARE BRACKET
+0x5C 0x005C # REVERSE SOLIDUS
+0x5D 0x005D # RIGHT SQUARE BRACKET
+0x5E 0x005E # CIRCUMFLEX ACCENT
+0x5F 0x005F # LOW LINE
+0x60 0x0060 # GRAVE ACCENT
+0x61 0x0061 # LATIN SMALL LETTER A
+0x62 0x0062 # LATIN SMALL LETTER B
+0x63 0x0063 # LATIN SMALL LETTER C
+0x64 0x0064 # LATIN SMALL LETTER D
+0x65 0x0065 # LATIN SMALL LETTER E
+0x66 0x0066 # LATIN SMALL LETTER F
+0x67 0x0067 # LATIN SMALL LETTER G
+0x68 0x0068 # LATIN SMALL LETTER H
+0x69 0x0069 # LATIN SMALL LETTER I
+0x6A 0x006A # LATIN SMALL LETTER J
+0x6B 0x006B # LATIN SMALL LETTER K
+0x6C 0x006C # LATIN SMALL LETTER L
+0x6D 0x006D # LATIN SMALL LETTER M
+0x6E 0x006E # LATIN SMALL LETTER N
+0x6F 0x006F # LATIN SMALL LETTER O
+0x70 0x0070 # LATIN SMALL LETTER P
+0x71 0x0071 # LATIN SMALL LETTER Q
+0x72 0x0072 # LATIN SMALL LETTER R
+0x73 0x0073 # LATIN SMALL LETTER S
+0x74 0x0074 # LATIN SMALL LETTER T
+0x75 0x0075 # LATIN SMALL LETTER U
+0x76 0x0076 # LATIN SMALL LETTER V
+0x77 0x0077 # LATIN SMALL LETTER W
+0x78 0x0078 # LATIN SMALL LETTER X
+0x79 0x0079 # LATIN SMALL LETTER Y
+0x7A 0x007A # LATIN SMALL LETTER Z
+0x7B 0x007B # LEFT CURLY BRACKET
+0x7C 0x007C # VERTICAL LINE
+0x7D 0x007D # RIGHT CURLY BRACKET
+0x7E 0x007E # TILDE
+0x7F 0x007F # DELETE
+0x80 0x0080 # <control>
+0x81 0x0081 # <control>
+0x82 0x0082 # <control>
+0x83 0x0083 # <control>
+0x84 0x0084 # <control>
+0x85 0x0085 # <control>
+0x86 0x0086 # <control>
+0x87 0x0087 # <control>
+0x88 0x0088 # <control>
+0x89 0x0089 # <control>
+0x8A 0x008A # <control>
+0x8B 0x008B # <control>
+0x8C 0x008C # <control>
+0x8D 0x008D # <control>
+0x8E 0x008E # <control>
+0x8F 0x008F # <control>
+0x90 0x0090 # <control>
+0x91 0x0091 # <control>
+0x92 0x0092 # <control>
+0x93 0x0093 # <control>
+0x94 0x0094 # <control>
+0x95 0x0095 # <control>
+0x96 0x0096 # <control>
+0x97 0x0097 # <control>
+0x98 0x0098 # <control>
+0x99 0x0099 # <control>
+0x9A 0x009A # <control>
+0x9B 0x009B # <control>
+0x9C 0x009C # <control>
+0x9D 0x009D # <control>
+0x9E 0x009E # <control>
+0x9F 0x009F # <control>
+0xA0 0x00A0 # NO-BREAK SPACE
+0xA1 0x0104 # LATIN CAPITAL LETTER A WITH OGONEK
+0xA2 0x0105 # LATIN SMALL LETTER A WITH OGONEK
+0xA3 0x0141 # LATIN CAPITAL LETTER L WITH STROKE
+0xA4 0x20AC # EURO SIGN
+0xA5 0x201E # DOUBLE LOW-9 QUOTATION MARK
+0xA6 0x0160 # LATIN CAPITAL LETTER S WITH CARON
+0xA7 0x00A7 # SECTION SIGN
+0xA8 0x0161 # LATIN SMALL LETTER S WITH CARON
+0xA9 0x00A9 # COPYRIGHT SIGN
+0xAA 0x0218 # LATIN CAPITAL LETTER S WITH COMMA BELOW
+0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC 0x0179 # LATIN CAPITAL LETTER Z WITH ACUTE
+0xAD 0x00AD # SOFT HYPHEN
+0xAE 0x017A # LATIN SMALL LETTER Z WITH ACUTE
+0xAF 0x017B # LATIN CAPITAL LETTER Z WITH DOT ABOVE
+0xB0 0x00B0 # DEGREE SIGN
+0xB1 0x00B1 # PLUS-MINUS SIGN
+0xB2 0x010C # LATIN CAPITAL LETTER C WITH CARON
+0xB3 0x0142 # LATIN SMALL LETTER L WITH STROKE
+0xB4 0x017D # LATIN CAPITAL LETTER Z WITH CARON
+0xB5 0x201D # RIGHT DOUBLE QUOTATION MARK
+0xB6 0x00B6 # PILCROW SIGN
+0xB7 0x00B7 # MIDDLE DOT
+0xB8 0x017E # LATIN SMALL LETTER Z WITH CARON
+0xB9 0x010D # LATIN SMALL LETTER C WITH CARON
+0xBA 0x0219 # LATIN SMALL LETTER S WITH COMMA BELOW
+0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC 0x0152 # LATIN CAPITAL LIGATURE OE
+0xBD 0x0153 # LATIN SMALL LIGATURE OE
+0xBE 0x0178 # LATIN CAPITAL LETTER Y WITH DIAERESIS
+0xBF 0x017C # LATIN SMALL LETTER Z WITH DOT ABOVE
+0xC0 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE
+0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE
+0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3 0x0102 # LATIN CAPITAL LETTER A WITH BREVE
+0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5 0x0106 # LATIN CAPITAL LETTER C WITH ACUTE
+0xC6 0x00C6 # LATIN CAPITAL LETTER AE
+0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE
+0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE
+0xCA 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE
+0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE
+0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD0 0x0110 # LATIN CAPITAL LETTER D WITH STROKE
+0xD1 0x0143 # LATIN CAPITAL LETTER N WITH ACUTE
+0xD2 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE
+0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE
+0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5 0x0150 # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7 0x015A # LATIN CAPITAL LETTER S WITH ACUTE
+0xD8 0x0170 # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+0xD9 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE
+0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE
+0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD 0x0118 # LATIN CAPITAL LETTER E WITH OGONEK
+0xDE 0x021A # LATIN CAPITAL LETTER T WITH COMMA BELOW
+0xDF 0x00DF # LATIN SMALL LETTER SHARP S
+0xE0 0x00E0 # LATIN SMALL LETTER A WITH GRAVE
+0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE
+0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3 0x0103 # LATIN SMALL LETTER A WITH BREVE
+0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS
+0xE5 0x0107 # LATIN SMALL LETTER C WITH ACUTE
+0xE6 0x00E6 # LATIN SMALL LETTER AE
+0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA
+0xE8 0x00E8 # LATIN SMALL LETTER E WITH GRAVE
+0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE
+0xEA 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS
+0xEC 0x00EC # LATIN SMALL LETTER I WITH GRAVE
+0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE
+0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS
+0xF0 0x0111 # LATIN SMALL LETTER D WITH STROKE
+0xF1 0x0144 # LATIN SMALL LETTER N WITH ACUTE
+0xF2 0x00F2 # LATIN SMALL LETTER O WITH GRAVE
+0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE
+0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5 0x0151 # LATIN SMALL LETTER O WITH DOUBLE ACUTE
+0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS
+0xF7 0x015B # LATIN SMALL LETTER S WITH ACUTE
+0xF8 0x0171 # LATIN SMALL LETTER U WITH DOUBLE ACUTE
+0xF9 0x00F9 # LATIN SMALL LETTER U WITH GRAVE
+0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE
+0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS
+0xFD 0x0119 # LATIN SMALL LETTER E WITH OGONEK
+0xFE 0x021B # LATIN SMALL LETTER T WITH COMMA BELOW
+0xFF 0x00FF # LATIN SMALL LETTER Y WITH DIAERESIS
diff --git a/ext/mbstring/tests/data/8859-2.txt b/ext/mbstring/tests/data/8859-2.txt
new file mode 100644
index 0000000000..20da9ba993
--- /dev/null
+++ b/ext/mbstring/tests/data/8859-2.txt
@@ -0,0 +1,292 @@
+# 8859-2.TXT
+# Date: 2015-12-02 21:34:00 GMT [KW]
+# © 2015 Unicode®, Inc.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
+#
+# Name: ISO 8859-2:1999 to Unicode
+# Unicode version: 3.0
+# Table version: 2.0
+# Table format: Format A
+# Date: 1999 July 27 (header updated: 2015 December 02)
+# Authors: Ken Whistler <ken@unicode.org>
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO/IEC 8859-2:1999 characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO/IEC 8859-2 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO/IEC 8859-2 order.
+#
+# Version history
+# 1.0 version: updates 0.1 version by adding mappings for all
+# control characters.
+# 2.0 version: updates to copyright notice and terms of use; no
+# changes to character mappings
+#
+# Updated versions of this file may be found in:
+# http://www.unicode.org/Public/MAPPINGS/
+#
+# Any comments or problems, contact us at:
+# http://www.unicode.org/reporting.html
+#
+0x00 0x0000 # NULL
+0x01 0x0001 # START OF HEADING
+0x02 0x0002 # START OF TEXT
+0x03 0x0003 # END OF TEXT
+0x04 0x0004 # END OF TRANSMISSION
+0x05 0x0005 # ENQUIRY
+0x06 0x0006 # ACKNOWLEDGE
+0x07 0x0007 # BELL
+0x08 0x0008 # BACKSPACE
+0x09 0x0009 # HORIZONTAL TABULATION
+0x0A 0x000A # LINE FEED
+0x0B 0x000B # VERTICAL TABULATION
+0x0C 0x000C # FORM FEED
+0x0D 0x000D # CARRIAGE RETURN
+0x0E 0x000E # SHIFT OUT
+0x0F 0x000F # SHIFT IN
+0x10 0x0010 # DATA LINK ESCAPE
+0x11 0x0011 # DEVICE CONTROL ONE
+0x12 0x0012 # DEVICE CONTROL TWO
+0x13 0x0013 # DEVICE CONTROL THREE
+0x14 0x0014 # DEVICE CONTROL FOUR
+0x15 0x0015 # NEGATIVE ACKNOWLEDGE
+0x16 0x0016 # SYNCHRONOUS IDLE
+0x17 0x0017 # END OF TRANSMISSION BLOCK
+0x18 0x0018 # CANCEL
+0x19 0x0019 # END OF MEDIUM
+0x1A 0x001A # SUBSTITUTE
+0x1B 0x001B # ESCAPE
+0x1C 0x001C # FILE SEPARATOR
+0x1D 0x001D # GROUP SEPARATOR
+0x1E 0x001E # RECORD SEPARATOR
+0x1F 0x001F # UNIT SEPARATOR
+0x20 0x0020 # SPACE
+0x21 0x0021 # EXCLAMATION MARK
+0x22 0x0022 # QUOTATION MARK
+0x23 0x0023 # NUMBER SIGN
+0x24 0x0024 # DOLLAR SIGN
+0x25 0x0025 # PERCENT SIGN
+0x26 0x0026 # AMPERSAND
+0x27 0x0027 # APOSTROPHE
+0x28 0x0028 # LEFT PARENTHESIS
+0x29 0x0029 # RIGHT PARENTHESIS
+0x2A 0x002A # ASTERISK
+0x2B 0x002B # PLUS SIGN
+0x2C 0x002C # COMMA
+0x2D 0x002D # HYPHEN-MINUS
+0x2E 0x002E # FULL STOP
+0x2F 0x002F # SOLIDUS
+0x30 0x0030 # DIGIT ZERO
+0x31 0x0031 # DIGIT ONE
+0x32 0x0032 # DIGIT TWO
+0x33 0x0033 # DIGIT THREE
+0x34 0x0034 # DIGIT FOUR
+0x35 0x0035 # DIGIT FIVE
+0x36 0x0036 # DIGIT SIX
+0x37 0x0037 # DIGIT SEVEN
+0x38 0x0038 # DIGIT EIGHT
+0x39 0x0039 # DIGIT NINE
+0x3A 0x003A # COLON
+0x3B 0x003B # SEMICOLON
+0x3C 0x003C # LESS-THAN SIGN
+0x3D 0x003D # EQUALS SIGN
+0x3E 0x003E # GREATER-THAN SIGN
+0x3F 0x003F # QUESTION MARK
+0x40 0x0040 # COMMERCIAL AT
+0x41 0x0041 # LATIN CAPITAL LETTER A
+0x42 0x0042 # LATIN CAPITAL LETTER B
+0x43 0x0043 # LATIN CAPITAL LETTER C
+0x44 0x0044 # LATIN CAPITAL LETTER D
+0x45 0x0045 # LATIN CAPITAL LETTER E
+0x46 0x0046 # LATIN CAPITAL LETTER F
+0x47 0x0047 # LATIN CAPITAL LETTER G
+0x48 0x0048 # LATIN CAPITAL LETTER H
+0x49 0x0049 # LATIN CAPITAL LETTER I
+0x4A 0x004A # LATIN CAPITAL LETTER J
+0x4B 0x004B # LATIN CAPITAL LETTER K
+0x4C 0x004C # LATIN CAPITAL LETTER L
+0x4D 0x004D # LATIN CAPITAL LETTER M
+0x4E 0x004E # LATIN CAPITAL LETTER N
+0x4F 0x004F # LATIN CAPITAL LETTER O
+0x50 0x0050 # LATIN CAPITAL LETTER P
+0x51 0x0051 # LATIN CAPITAL LETTER Q
+0x52 0x0052 # LATIN CAPITAL LETTER R
+0x53 0x0053 # LATIN CAPITAL LETTER S
+0x54 0x0054 # LATIN CAPITAL LETTER T
+0x55 0x0055 # LATIN CAPITAL LETTER U
+0x56 0x0056 # LATIN CAPITAL LETTER V
+0x57 0x0057 # LATIN CAPITAL LETTER W
+0x58 0x0058 # LATIN CAPITAL LETTER X
+0x59 0x0059 # LATIN CAPITAL LETTER Y
+0x5A 0x005A # LATIN CAPITAL LETTER Z
+0x5B 0x005B # LEFT SQUARE BRACKET
+0x5C 0x005C # REVERSE SOLIDUS
+0x5D 0x005D # RIGHT SQUARE BRACKET
+0x5E 0x005E # CIRCUMFLEX ACCENT
+0x5F 0x005F # LOW LINE
+0x60 0x0060 # GRAVE ACCENT
+0x61 0x0061 # LATIN SMALL LETTER A
+0x62 0x0062 # LATIN SMALL LETTER B
+0x63 0x0063 # LATIN SMALL LETTER C
+0x64 0x0064 # LATIN SMALL LETTER D
+0x65 0x0065 # LATIN SMALL LETTER E
+0x66 0x0066 # LATIN SMALL LETTER F
+0x67 0x0067 # LATIN SMALL LETTER G
+0x68 0x0068 # LATIN SMALL LETTER H
+0x69 0x0069 # LATIN SMALL LETTER I
+0x6A 0x006A # LATIN SMALL LETTER J
+0x6B 0x006B # LATIN SMALL LETTER K
+0x6C 0x006C # LATIN SMALL LETTER L
+0x6D 0x006D # LATIN SMALL LETTER M
+0x6E 0x006E # LATIN SMALL LETTER N
+0x6F 0x006F # LATIN SMALL LETTER O
+0x70 0x0070 # LATIN SMALL LETTER P
+0x71 0x0071 # LATIN SMALL LETTER Q
+0x72 0x0072 # LATIN SMALL LETTER R
+0x73 0x0073 # LATIN SMALL LETTER S
+0x74 0x0074 # LATIN SMALL LETTER T
+0x75 0x0075 # LATIN SMALL LETTER U
+0x76 0x0076 # LATIN SMALL LETTER V
+0x77 0x0077 # LATIN SMALL LETTER W
+0x78 0x0078 # LATIN SMALL LETTER X
+0x79 0x0079 # LATIN SMALL LETTER Y
+0x7A 0x007A # LATIN SMALL LETTER Z
+0x7B 0x007B # LEFT CURLY BRACKET
+0x7C 0x007C # VERTICAL LINE
+0x7D 0x007D # RIGHT CURLY BRACKET
+0x7E 0x007E # TILDE
+0x7F 0x007F # DELETE
+0x80 0x0080 # <control>
+0x81 0x0081 # <control>
+0x82 0x0082 # <control>
+0x83 0x0083 # <control>
+0x84 0x0084 # <control>
+0x85 0x0085 # <control>
+0x86 0x0086 # <control>
+0x87 0x0087 # <control>
+0x88 0x0088 # <control>
+0x89 0x0089 # <control>
+0x8A 0x008A # <control>
+0x8B 0x008B # <control>
+0x8C 0x008C # <control>
+0x8D 0x008D # <control>
+0x8E 0x008E # <control>
+0x8F 0x008F # <control>
+0x90 0x0090 # <control>
+0x91 0x0091 # <control>
+0x92 0x0092 # <control>
+0x93 0x0093 # <control>
+0x94 0x0094 # <control>
+0x95 0x0095 # <control>
+0x96 0x0096 # <control>
+0x97 0x0097 # <control>
+0x98 0x0098 # <control>
+0x99 0x0099 # <control>
+0x9A 0x009A # <control>
+0x9B 0x009B # <control>
+0x9C 0x009C # <control>
+0x9D 0x009D # <control>
+0x9E 0x009E # <control>
+0x9F 0x009F # <control>
+0xA0 0x00A0 # NO-BREAK SPACE
+0xA1 0x0104 # LATIN CAPITAL LETTER A WITH OGONEK
+0xA2 0x02D8 # BREVE
+0xA3 0x0141 # LATIN CAPITAL LETTER L WITH STROKE
+0xA4 0x00A4 # CURRENCY SIGN
+0xA5 0x013D # LATIN CAPITAL LETTER L WITH CARON
+0xA6 0x015A # LATIN CAPITAL LETTER S WITH ACUTE
+0xA7 0x00A7 # SECTION SIGN
+0xA8 0x00A8 # DIAERESIS
+0xA9 0x0160 # LATIN CAPITAL LETTER S WITH CARON
+0xAA 0x015E # LATIN CAPITAL LETTER S WITH CEDILLA
+0xAB 0x0164 # LATIN CAPITAL LETTER T WITH CARON
+0xAC 0x0179 # LATIN CAPITAL LETTER Z WITH ACUTE
+0xAD 0x00AD # SOFT HYPHEN
+0xAE 0x017D # LATIN CAPITAL LETTER Z WITH CARON
+0xAF 0x017B # LATIN CAPITAL LETTER Z WITH DOT ABOVE
+0xB0 0x00B0 # DEGREE SIGN
+0xB1 0x0105 # LATIN SMALL LETTER A WITH OGONEK
+0xB2 0x02DB # OGONEK
+0xB3 0x0142 # LATIN SMALL LETTER L WITH STROKE
+0xB4 0x00B4 # ACUTE ACCENT
+0xB5 0x013E # LATIN SMALL LETTER L WITH CARON
+0xB6 0x015B # LATIN SMALL LETTER S WITH ACUTE
+0xB7 0x02C7 # CARON
+0xB8 0x00B8 # CEDILLA
+0xB9 0x0161 # LATIN SMALL LETTER S WITH CARON
+0xBA 0x015F # LATIN SMALL LETTER S WITH CEDILLA
+0xBB 0x0165 # LATIN SMALL LETTER T WITH CARON
+0xBC 0x017A # LATIN SMALL LETTER Z WITH ACUTE
+0xBD 0x02DD # DOUBLE ACUTE ACCENT
+0xBE 0x017E # LATIN SMALL LETTER Z WITH CARON
+0xBF 0x017C # LATIN SMALL LETTER Z WITH DOT ABOVE
+0xC0 0x0154 # LATIN CAPITAL LETTER R WITH ACUTE
+0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE
+0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3 0x0102 # LATIN CAPITAL LETTER A WITH BREVE
+0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5 0x0139 # LATIN CAPITAL LETTER L WITH ACUTE
+0xC6 0x0106 # LATIN CAPITAL LETTER C WITH ACUTE
+0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8 0x010C # LATIN CAPITAL LETTER C WITH CARON
+0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE
+0xCA 0x0118 # LATIN CAPITAL LETTER E WITH OGONEK
+0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC 0x011A # LATIN CAPITAL LETTER E WITH CARON
+0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE
+0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF 0x010E # LATIN CAPITAL LETTER D WITH CARON
+0xD0 0x0110 # LATIN CAPITAL LETTER D WITH STROKE
+0xD1 0x0143 # LATIN CAPITAL LETTER N WITH ACUTE
+0xD2 0x0147 # LATIN CAPITAL LETTER N WITH CARON
+0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE
+0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5 0x0150 # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7 0x00D7 # MULTIPLICATION SIGN
+0xD8 0x0158 # LATIN CAPITAL LETTER R WITH CARON
+0xD9 0x016E # LATIN CAPITAL LETTER U WITH RING ABOVE
+0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE
+0xDB 0x0170 # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD 0x00DD # LATIN CAPITAL LETTER Y WITH ACUTE
+0xDE 0x0162 # LATIN CAPITAL LETTER T WITH CEDILLA
+0xDF 0x00DF # LATIN SMALL LETTER SHARP S
+0xE0 0x0155 # LATIN SMALL LETTER R WITH ACUTE
+0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE
+0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3 0x0103 # LATIN SMALL LETTER A WITH BREVE
+0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS
+0xE5 0x013A # LATIN SMALL LETTER L WITH ACUTE
+0xE6 0x0107 # LATIN SMALL LETTER C WITH ACUTE
+0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA
+0xE8 0x010D # LATIN SMALL LETTER C WITH CARON
+0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE
+0xEA 0x0119 # LATIN SMALL LETTER E WITH OGONEK
+0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS
+0xEC 0x011B # LATIN SMALL LETTER E WITH CARON
+0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE
+0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF 0x010F # LATIN SMALL LETTER D WITH CARON
+0xF0 0x0111 # LATIN SMALL LETTER D WITH STROKE
+0xF1 0x0144 # LATIN SMALL LETTER N WITH ACUTE
+0xF2 0x0148 # LATIN SMALL LETTER N WITH CARON
+0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE
+0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5 0x0151 # LATIN SMALL LETTER O WITH DOUBLE ACUTE
+0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS
+0xF7 0x00F7 # DIVISION SIGN
+0xF8 0x0159 # LATIN SMALL LETTER R WITH CARON
+0xF9 0x016F # LATIN SMALL LETTER U WITH RING ABOVE
+0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE
+0xFB 0x0171 # LATIN SMALL LETTER U WITH DOUBLE ACUTE
+0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS
+0xFD 0x00FD # LATIN SMALL LETTER Y WITH ACUTE
+0xFE 0x0163 # LATIN SMALL LETTER T WITH CEDILLA
+0xFF 0x02D9 # DOT ABOVE
diff --git a/ext/mbstring/tests/data/8859-3.txt b/ext/mbstring/tests/data/8859-3.txt
new file mode 100644
index 0000000000..5a6c5de547
--- /dev/null
+++ b/ext/mbstring/tests/data/8859-3.txt
@@ -0,0 +1,285 @@
+# 8859-3.TXT
+# Date: 2015-12-02 21:39:00 GMT [KW]
+# © 2015 Unicode®, Inc.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
+#
+# Name: ISO/IEC 8859-3:1999 to Unicode
+# Unicode version: 3.0
+# Table version: 2.0
+# Table format: Format A
+# Date: 1999 July 27 (header updated: 2015 December 02)
+# Authors: Ken Whistler <ken@unicode.org>
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO/IEC 8859-3:1999 characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO/IEC 8859-3 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO/IEC 8859-3 order.
+#
+# Version history
+# 1.0 version: updates 0.1 version by adding mappings for all
+# control characters.
+# 2.0 version: updates to copyright notice and terms of use; no
+# changes to character mappings
+#
+# Updated versions of this file may be found in:
+# http://www.unicode.org/Public/MAPPINGS/
+#
+# Any comments or problems, contact us at:
+# http://www.unicode.org/reporting.html
+#
+0x00 0x0000 # NULL
+0x01 0x0001 # START OF HEADING
+0x02 0x0002 # START OF TEXT
+0x03 0x0003 # END OF TEXT
+0x04 0x0004 # END OF TRANSMISSION
+0x05 0x0005 # ENQUIRY
+0x06 0x0006 # ACKNOWLEDGE
+0x07 0x0007 # BELL
+0x08 0x0008 # BACKSPACE
+0x09 0x0009 # HORIZONTAL TABULATION
+0x0A 0x000A # LINE FEED
+0x0B 0x000B # VERTICAL TABULATION
+0x0C 0x000C # FORM FEED
+0x0D 0x000D # CARRIAGE RETURN
+0x0E 0x000E # SHIFT OUT
+0x0F 0x000F # SHIFT IN
+0x10 0x0010 # DATA LINK ESCAPE
+0x11 0x0011 # DEVICE CONTROL ONE
+0x12 0x0012 # DEVICE CONTROL TWO
+0x13 0x0013 # DEVICE CONTROL THREE
+0x14 0x0014 # DEVICE CONTROL FOUR
+0x15 0x0015 # NEGATIVE ACKNOWLEDGE
+0x16 0x0016 # SYNCHRONOUS IDLE
+0x17 0x0017 # END OF TRANSMISSION BLOCK
+0x18 0x0018 # CANCEL
+0x19 0x0019 # END OF MEDIUM
+0x1A 0x001A # SUBSTITUTE
+0x1B 0x001B # ESCAPE
+0x1C 0x001C # FILE SEPARATOR
+0x1D 0x001D # GROUP SEPARATOR
+0x1E 0x001E # RECORD SEPARATOR
+0x1F 0x001F # UNIT SEPARATOR
+0x20 0x0020 # SPACE
+0x21 0x0021 # EXCLAMATION MARK
+0x22 0x0022 # QUOTATION MARK
+0x23 0x0023 # NUMBER SIGN
+0x24 0x0024 # DOLLAR SIGN
+0x25 0x0025 # PERCENT SIGN
+0x26 0x0026 # AMPERSAND
+0x27 0x0027 # APOSTROPHE
+0x28 0x0028 # LEFT PARENTHESIS
+0x29 0x0029 # RIGHT PARENTHESIS
+0x2A 0x002A # ASTERISK
+0x2B 0x002B # PLUS SIGN
+0x2C 0x002C # COMMA
+0x2D 0x002D # HYPHEN-MINUS
+0x2E 0x002E # FULL STOP
+0x2F 0x002F # SOLIDUS
+0x30 0x0030 # DIGIT ZERO
+0x31 0x0031 # DIGIT ONE
+0x32 0x0032 # DIGIT TWO
+0x33 0x0033 # DIGIT THREE
+0x34 0x0034 # DIGIT FOUR
+0x35 0x0035 # DIGIT FIVE
+0x36 0x0036 # DIGIT SIX
+0x37 0x0037 # DIGIT SEVEN
+0x38 0x0038 # DIGIT EIGHT
+0x39 0x0039 # DIGIT NINE
+0x3A 0x003A # COLON
+0x3B 0x003B # SEMICOLON
+0x3C 0x003C # LESS-THAN SIGN
+0x3D 0x003D # EQUALS SIGN
+0x3E 0x003E # GREATER-THAN SIGN
+0x3F 0x003F # QUESTION MARK
+0x40 0x0040 # COMMERCIAL AT
+0x41 0x0041 # LATIN CAPITAL LETTER A
+0x42 0x0042 # LATIN CAPITAL LETTER B
+0x43 0x0043 # LATIN CAPITAL LETTER C
+0x44 0x0044 # LATIN CAPITAL LETTER D
+0x45 0x0045 # LATIN CAPITAL LETTER E
+0x46 0x0046 # LATIN CAPITAL LETTER F
+0x47 0x0047 # LATIN CAPITAL LETTER G
+0x48 0x0048 # LATIN CAPITAL LETTER H
+0x49 0x0049 # LATIN CAPITAL LETTER I
+0x4A 0x004A # LATIN CAPITAL LETTER J
+0x4B 0x004B # LATIN CAPITAL LETTER K
+0x4C 0x004C # LATIN CAPITAL LETTER L
+0x4D 0x004D # LATIN CAPITAL LETTER M
+0x4E 0x004E # LATIN CAPITAL LETTER N
+0x4F 0x004F # LATIN CAPITAL LETTER O
+0x50 0x0050 # LATIN CAPITAL LETTER P
+0x51 0x0051 # LATIN CAPITAL LETTER Q
+0x52 0x0052 # LATIN CAPITAL LETTER R
+0x53 0x0053 # LATIN CAPITAL LETTER S
+0x54 0x0054 # LATIN CAPITAL LETTER T
+0x55 0x0055 # LATIN CAPITAL LETTER U
+0x56 0x0056 # LATIN CAPITAL LETTER V
+0x57 0x0057 # LATIN CAPITAL LETTER W
+0x58 0x0058 # LATIN CAPITAL LETTER X
+0x59 0x0059 # LATIN CAPITAL LETTER Y
+0x5A 0x005A # LATIN CAPITAL LETTER Z
+0x5B 0x005B # LEFT SQUARE BRACKET
+0x5C 0x005C # REVERSE SOLIDUS
+0x5D 0x005D # RIGHT SQUARE BRACKET
+0x5E 0x005E # CIRCUMFLEX ACCENT
+0x5F 0x005F # LOW LINE
+0x60 0x0060 # GRAVE ACCENT
+0x61 0x0061 # LATIN SMALL LETTER A
+0x62 0x0062 # LATIN SMALL LETTER B
+0x63 0x0063 # LATIN SMALL LETTER C
+0x64 0x0064 # LATIN SMALL LETTER D
+0x65 0x0065 # LATIN SMALL LETTER E
+0x66 0x0066 # LATIN SMALL LETTER F
+0x67 0x0067 # LATIN SMALL LETTER G
+0x68 0x0068 # LATIN SMALL LETTER H
+0x69 0x0069 # LATIN SMALL LETTER I
+0x6A 0x006A # LATIN SMALL LETTER J
+0x6B 0x006B # LATIN SMALL LETTER K
+0x6C 0x006C # LATIN SMALL LETTER L
+0x6D 0x006D # LATIN SMALL LETTER M
+0x6E 0x006E # LATIN SMALL LETTER N
+0x6F 0x006F # LATIN SMALL LETTER O
+0x70 0x0070 # LATIN SMALL LETTER P
+0x71 0x0071 # LATIN SMALL LETTER Q
+0x72 0x0072 # LATIN SMALL LETTER R
+0x73 0x0073 # LATIN SMALL LETTER S
+0x74 0x0074 # LATIN SMALL LETTER T
+0x75 0x0075 # LATIN SMALL LETTER U
+0x76 0x0076 # LATIN SMALL LETTER V
+0x77 0x0077 # LATIN SMALL LETTER W
+0x78 0x0078 # LATIN SMALL LETTER X
+0x79 0x0079 # LATIN SMALL LETTER Y
+0x7A 0x007A # LATIN SMALL LETTER Z
+0x7B 0x007B # LEFT CURLY BRACKET
+0x7C 0x007C # VERTICAL LINE
+0x7D 0x007D # RIGHT CURLY BRACKET
+0x7E 0x007E # TILDE
+0x7F 0x007F # DELETE
+0x80 0x0080 # <control>
+0x81 0x0081 # <control>
+0x82 0x0082 # <control>
+0x83 0x0083 # <control>
+0x84 0x0084 # <control>
+0x85 0x0085 # <control>
+0x86 0x0086 # <control>
+0x87 0x0087 # <control>
+0x88 0x0088 # <control>
+0x89 0x0089 # <control>
+0x8A 0x008A # <control>
+0x8B 0x008B # <control>
+0x8C 0x008C # <control>
+0x8D 0x008D # <control>
+0x8E 0x008E # <control>
+0x8F 0x008F # <control>
+0x90 0x0090 # <control>
+0x91 0x0091 # <control>
+0x92 0x0092 # <control>
+0x93 0x0093 # <control>
+0x94 0x0094 # <control>
+0x95 0x0095 # <control>
+0x96 0x0096 # <control>
+0x97 0x0097 # <control>
+0x98 0x0098 # <control>
+0x99 0x0099 # <control>
+0x9A 0x009A # <control>
+0x9B 0x009B # <control>
+0x9C 0x009C # <control>
+0x9D 0x009D # <control>
+0x9E 0x009E # <control>
+0x9F 0x009F # <control>
+0xA0 0x00A0 # NO-BREAK SPACE
+0xA1 0x0126 # LATIN CAPITAL LETTER H WITH STROKE
+0xA2 0x02D8 # BREVE
+0xA3 0x00A3 # POUND SIGN
+0xA4 0x00A4 # CURRENCY SIGN
+0xA6 0x0124 # LATIN CAPITAL LETTER H WITH CIRCUMFLEX
+0xA7 0x00A7 # SECTION SIGN
+0xA8 0x00A8 # DIAERESIS
+0xA9 0x0130 # LATIN CAPITAL LETTER I WITH DOT ABOVE
+0xAA 0x015E # LATIN CAPITAL LETTER S WITH CEDILLA
+0xAB 0x011E # LATIN CAPITAL LETTER G WITH BREVE
+0xAC 0x0134 # LATIN CAPITAL LETTER J WITH CIRCUMFLEX
+0xAD 0x00AD # SOFT HYPHEN
+0xAF 0x017B # LATIN CAPITAL LETTER Z WITH DOT ABOVE
+0xB0 0x00B0 # DEGREE SIGN
+0xB1 0x0127 # LATIN SMALL LETTER H WITH STROKE
+0xB2 0x00B2 # SUPERSCRIPT TWO
+0xB3 0x00B3 # SUPERSCRIPT THREE
+0xB4 0x00B4 # ACUTE ACCENT
+0xB5 0x00B5 # MICRO SIGN
+0xB6 0x0125 # LATIN SMALL LETTER H WITH CIRCUMFLEX
+0xB7 0x00B7 # MIDDLE DOT
+0xB8 0x00B8 # CEDILLA
+0xB9 0x0131 # LATIN SMALL LETTER DOTLESS I
+0xBA 0x015F # LATIN SMALL LETTER S WITH CEDILLA
+0xBB 0x011F # LATIN SMALL LETTER G WITH BREVE
+0xBC 0x0135 # LATIN SMALL LETTER J WITH CIRCUMFLEX
+0xBD 0x00BD # VULGAR FRACTION ONE HALF
+0xBF 0x017C # LATIN SMALL LETTER Z WITH DOT ABOVE
+0xC0 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE
+0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE
+0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5 0x010A # LATIN CAPITAL LETTER C WITH DOT ABOVE
+0xC6 0x0108 # LATIN CAPITAL LETTER C WITH CIRCUMFLEX
+0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE
+0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE
+0xCA 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE
+0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE
+0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD1 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE
+0xD2 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE
+0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE
+0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5 0x0120 # LATIN CAPITAL LETTER G WITH DOT ABOVE
+0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7 0x00D7 # MULTIPLICATION SIGN
+0xD8 0x011C # LATIN CAPITAL LETTER G WITH CIRCUMFLEX
+0xD9 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE
+0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE
+0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD 0x016C # LATIN CAPITAL LETTER U WITH BREVE
+0xDE 0x015C # LATIN CAPITAL LETTER S WITH CIRCUMFLEX
+0xDF 0x00DF # LATIN SMALL LETTER SHARP S
+0xE0 0x00E0 # LATIN SMALL LETTER A WITH GRAVE
+0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE
+0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS
+0xE5 0x010B # LATIN SMALL LETTER C WITH DOT ABOVE
+0xE6 0x0109 # LATIN SMALL LETTER C WITH CIRCUMFLEX
+0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA
+0xE8 0x00E8 # LATIN SMALL LETTER E WITH GRAVE
+0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE
+0xEA 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS
+0xEC 0x00EC # LATIN SMALL LETTER I WITH GRAVE
+0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE
+0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS
+0xF1 0x00F1 # LATIN SMALL LETTER N WITH TILDE
+0xF2 0x00F2 # LATIN SMALL LETTER O WITH GRAVE
+0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE
+0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5 0x0121 # LATIN SMALL LETTER G WITH DOT ABOVE
+0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS
+0xF7 0x00F7 # DIVISION SIGN
+0xF8 0x011D # LATIN SMALL LETTER G WITH CIRCUMFLEX
+0xF9 0x00F9 # LATIN SMALL LETTER U WITH GRAVE
+0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE
+0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS
+0xFD 0x016D # LATIN SMALL LETTER U WITH BREVE
+0xFE 0x015D # LATIN SMALL LETTER S WITH CIRCUMFLEX
+0xFF 0x02D9 # DOT ABOVE
diff --git a/ext/mbstring/tests/data/8859-4.txt b/ext/mbstring/tests/data/8859-4.txt
new file mode 100644
index 0000000000..e2f5e725fd
--- /dev/null
+++ b/ext/mbstring/tests/data/8859-4.txt
@@ -0,0 +1,292 @@
+# 8859-4.TXT
+# Date: 2015-12-02 21:41:00 GMT [KW]
+# © 2015 Unicode®, Inc.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
+#
+# Name: ISO/IEC 8859-4:1998 to Unicode
+# Unicode version: 3.0
+# Table version: 2.0
+# Table format: Format A
+# Date: 1999 July 27 (header updated: 2015 December 02)
+# Authors: Ken Whistler <ken@unicode.org>
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO/IEC 8859-4:1998 characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO/IEC 8859-4 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO/IEC 8859-4 order.
+#
+# Version history
+# 1.0 version: updates 0.1 version by adding mappings for all
+# control characters.
+# 2.0 version: updates to copyright notice and terms of use; no
+# changes to character mappings
+#
+# Updated versions of this file may be found in:
+# http://www.unicode.org/Public/MAPPINGS/
+#
+# Any comments or problems, contact us at:
+# http://www.unicode.org/reporting.html
+#
+0x00 0x0000 # NULL
+0x01 0x0001 # START OF HEADING
+0x02 0x0002 # START OF TEXT
+0x03 0x0003 # END OF TEXT
+0x04 0x0004 # END OF TRANSMISSION
+0x05 0x0005 # ENQUIRY
+0x06 0x0006 # ACKNOWLEDGE
+0x07 0x0007 # BELL
+0x08 0x0008 # BACKSPACE
+0x09 0x0009 # HORIZONTAL TABULATION
+0x0A 0x000A # LINE FEED
+0x0B 0x000B # VERTICAL TABULATION
+0x0C 0x000C # FORM FEED
+0x0D 0x000D # CARRIAGE RETURN
+0x0E 0x000E # SHIFT OUT
+0x0F 0x000F # SHIFT IN
+0x10 0x0010 # DATA LINK ESCAPE
+0x11 0x0011 # DEVICE CONTROL ONE
+0x12 0x0012 # DEVICE CONTROL TWO
+0x13 0x0013 # DEVICE CONTROL THREE
+0x14 0x0014 # DEVICE CONTROL FOUR
+0x15 0x0015 # NEGATIVE ACKNOWLEDGE
+0x16 0x0016 # SYNCHRONOUS IDLE
+0x17 0x0017 # END OF TRANSMISSION BLOCK
+0x18 0x0018 # CANCEL
+0x19 0x0019 # END OF MEDIUM
+0x1A 0x001A # SUBSTITUTE
+0x1B 0x001B # ESCAPE
+0x1C 0x001C # FILE SEPARATOR
+0x1D 0x001D # GROUP SEPARATOR
+0x1E 0x001E # RECORD SEPARATOR
+0x1F 0x001F # UNIT SEPARATOR
+0x20 0x0020 # SPACE
+0x21 0x0021 # EXCLAMATION MARK
+0x22 0x0022 # QUOTATION MARK
+0x23 0x0023 # NUMBER SIGN
+0x24 0x0024 # DOLLAR SIGN
+0x25 0x0025 # PERCENT SIGN
+0x26 0x0026 # AMPERSAND
+0x27 0x0027 # APOSTROPHE
+0x28 0x0028 # LEFT PARENTHESIS
+0x29 0x0029 # RIGHT PARENTHESIS
+0x2A 0x002A # ASTERISK
+0x2B 0x002B # PLUS SIGN
+0x2C 0x002C # COMMA
+0x2D 0x002D # HYPHEN-MINUS
+0x2E 0x002E # FULL STOP
+0x2F 0x002F # SOLIDUS
+0x30 0x0030 # DIGIT ZERO
+0x31 0x0031 # DIGIT ONE
+0x32 0x0032 # DIGIT TWO
+0x33 0x0033 # DIGIT THREE
+0x34 0x0034 # DIGIT FOUR
+0x35 0x0035 # DIGIT FIVE
+0x36 0x0036 # DIGIT SIX
+0x37 0x0037 # DIGIT SEVEN
+0x38 0x0038 # DIGIT EIGHT
+0x39 0x0039 # DIGIT NINE
+0x3A 0x003A # COLON
+0x3B 0x003B # SEMICOLON
+0x3C 0x003C # LESS-THAN SIGN
+0x3D 0x003D # EQUALS SIGN
+0x3E 0x003E # GREATER-THAN SIGN
+0x3F 0x003F # QUESTION MARK
+0x40 0x0040 # COMMERCIAL AT
+0x41 0x0041 # LATIN CAPITAL LETTER A
+0x42 0x0042 # LATIN CAPITAL LETTER B
+0x43 0x0043 # LATIN CAPITAL LETTER C
+0x44 0x0044 # LATIN CAPITAL LETTER D
+0x45 0x0045 # LATIN CAPITAL LETTER E
+0x46 0x0046 # LATIN CAPITAL LETTER F
+0x47 0x0047 # LATIN CAPITAL LETTER G
+0x48 0x0048 # LATIN CAPITAL LETTER H
+0x49 0x0049 # LATIN CAPITAL LETTER I
+0x4A 0x004A # LATIN CAPITAL LETTER J
+0x4B 0x004B # LATIN CAPITAL LETTER K
+0x4C 0x004C # LATIN CAPITAL LETTER L
+0x4D 0x004D # LATIN CAPITAL LETTER M
+0x4E 0x004E # LATIN CAPITAL LETTER N
+0x4F 0x004F # LATIN CAPITAL LETTER O
+0x50 0x0050 # LATIN CAPITAL LETTER P
+0x51 0x0051 # LATIN CAPITAL LETTER Q
+0x52 0x0052 # LATIN CAPITAL LETTER R
+0x53 0x0053 # LATIN CAPITAL LETTER S
+0x54 0x0054 # LATIN CAPITAL LETTER T
+0x55 0x0055 # LATIN CAPITAL LETTER U
+0x56 0x0056 # LATIN CAPITAL LETTER V
+0x57 0x0057 # LATIN CAPITAL LETTER W
+0x58 0x0058 # LATIN CAPITAL LETTER X
+0x59 0x0059 # LATIN CAPITAL LETTER Y
+0x5A 0x005A # LATIN CAPITAL LETTER Z
+0x5B 0x005B # LEFT SQUARE BRACKET
+0x5C 0x005C # REVERSE SOLIDUS
+0x5D 0x005D # RIGHT SQUARE BRACKET
+0x5E 0x005E # CIRCUMFLEX ACCENT
+0x5F 0x005F # LOW LINE
+0x60 0x0060 # GRAVE ACCENT
+0x61 0x0061 # LATIN SMALL LETTER A
+0x62 0x0062 # LATIN SMALL LETTER B
+0x63 0x0063 # LATIN SMALL LETTER C
+0x64 0x0064 # LATIN SMALL LETTER D
+0x65 0x0065 # LATIN SMALL LETTER E
+0x66 0x0066 # LATIN SMALL LETTER F
+0x67 0x0067 # LATIN SMALL LETTER G
+0x68 0x0068 # LATIN SMALL LETTER H
+0x69 0x0069 # LATIN SMALL LETTER I
+0x6A 0x006A # LATIN SMALL LETTER J
+0x6B 0x006B # LATIN SMALL LETTER K
+0x6C 0x006C # LATIN SMALL LETTER L
+0x6D 0x006D # LATIN SMALL LETTER M
+0x6E 0x006E # LATIN SMALL LETTER N
+0x6F 0x006F # LATIN SMALL LETTER O
+0x70 0x0070 # LATIN SMALL LETTER P
+0x71 0x0071 # LATIN SMALL LETTER Q
+0x72 0x0072 # LATIN SMALL LETTER R
+0x73 0x0073 # LATIN SMALL LETTER S
+0x74 0x0074 # LATIN SMALL LETTER T
+0x75 0x0075 # LATIN SMALL LETTER U
+0x76 0x0076 # LATIN SMALL LETTER V
+0x77 0x0077 # LATIN SMALL LETTER W
+0x78 0x0078 # LATIN SMALL LETTER X
+0x79 0x0079 # LATIN SMALL LETTER Y
+0x7A 0x007A # LATIN SMALL LETTER Z
+0x7B 0x007B # LEFT CURLY BRACKET
+0x7C 0x007C # VERTICAL LINE
+0x7D 0x007D # RIGHT CURLY BRACKET
+0x7E 0x007E # TILDE
+0x7F 0x007F # DELETE
+0x80 0x0080 # <control>
+0x81 0x0081 # <control>
+0x82 0x0082 # <control>
+0x83 0x0083 # <control>
+0x84 0x0084 # <control>
+0x85 0x0085 # <control>
+0x86 0x0086 # <control>
+0x87 0x0087 # <control>
+0x88 0x0088 # <control>
+0x89 0x0089 # <control>
+0x8A 0x008A # <control>
+0x8B 0x008B # <control>
+0x8C 0x008C # <control>
+0x8D 0x008D # <control>
+0x8E 0x008E # <control>
+0x8F 0x008F # <control>
+0x90 0x0090 # <control>
+0x91 0x0091 # <control>
+0x92 0x0092 # <control>
+0x93 0x0093 # <control>
+0x94 0x0094 # <control>
+0x95 0x0095 # <control>
+0x96 0x0096 # <control>
+0x97 0x0097 # <control>
+0x98 0x0098 # <control>
+0x99 0x0099 # <control>
+0x9A 0x009A # <control>
+0x9B 0x009B # <control>
+0x9C 0x009C # <control>
+0x9D 0x009D # <control>
+0x9E 0x009E # <control>
+0x9F 0x009F # <control>
+0xA0 0x00A0 # NO-BREAK SPACE
+0xA1 0x0104 # LATIN CAPITAL LETTER A WITH OGONEK
+0xA2 0x0138 # LATIN SMALL LETTER KRA
+0xA3 0x0156 # LATIN CAPITAL LETTER R WITH CEDILLA
+0xA4 0x00A4 # CURRENCY SIGN
+0xA5 0x0128 # LATIN CAPITAL LETTER I WITH TILDE
+0xA6 0x013B # LATIN CAPITAL LETTER L WITH CEDILLA
+0xA7 0x00A7 # SECTION SIGN
+0xA8 0x00A8 # DIAERESIS
+0xA9 0x0160 # LATIN CAPITAL LETTER S WITH CARON
+0xAA 0x0112 # LATIN CAPITAL LETTER E WITH MACRON
+0xAB 0x0122 # LATIN CAPITAL LETTER G WITH CEDILLA
+0xAC 0x0166 # LATIN CAPITAL LETTER T WITH STROKE
+0xAD 0x00AD # SOFT HYPHEN
+0xAE 0x017D # LATIN CAPITAL LETTER Z WITH CARON
+0xAF 0x00AF # MACRON
+0xB0 0x00B0 # DEGREE SIGN
+0xB1 0x0105 # LATIN SMALL LETTER A WITH OGONEK
+0xB2 0x02DB # OGONEK
+0xB3 0x0157 # LATIN SMALL LETTER R WITH CEDILLA
+0xB4 0x00B4 # ACUTE ACCENT
+0xB5 0x0129 # LATIN SMALL LETTER I WITH TILDE
+0xB6 0x013C # LATIN SMALL LETTER L WITH CEDILLA
+0xB7 0x02C7 # CARON
+0xB8 0x00B8 # CEDILLA
+0xB9 0x0161 # LATIN SMALL LETTER S WITH CARON
+0xBA 0x0113 # LATIN SMALL LETTER E WITH MACRON
+0xBB 0x0123 # LATIN SMALL LETTER G WITH CEDILLA
+0xBC 0x0167 # LATIN SMALL LETTER T WITH STROKE
+0xBD 0x014A # LATIN CAPITAL LETTER ENG
+0xBE 0x017E # LATIN SMALL LETTER Z WITH CARON
+0xBF 0x014B # LATIN SMALL LETTER ENG
+0xC0 0x0100 # LATIN CAPITAL LETTER A WITH MACRON
+0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE
+0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE
+0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6 0x00C6 # LATIN CAPITAL LETTER AE
+0xC7 0x012E # LATIN CAPITAL LETTER I WITH OGONEK
+0xC8 0x010C # LATIN CAPITAL LETTER C WITH CARON
+0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE
+0xCA 0x0118 # LATIN CAPITAL LETTER E WITH OGONEK
+0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC 0x0116 # LATIN CAPITAL LETTER E WITH DOT ABOVE
+0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE
+0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF 0x012A # LATIN CAPITAL LETTER I WITH MACRON
+0xD0 0x0110 # LATIN CAPITAL LETTER D WITH STROKE
+0xD1 0x0145 # LATIN CAPITAL LETTER N WITH CEDILLA
+0xD2 0x014C # LATIN CAPITAL LETTER O WITH MACRON
+0xD3 0x0136 # LATIN CAPITAL LETTER K WITH CEDILLA
+0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE
+0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7 0x00D7 # MULTIPLICATION SIGN
+0xD8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE
+0xD9 0x0172 # LATIN CAPITAL LETTER U WITH OGONEK
+0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE
+0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD 0x0168 # LATIN CAPITAL LETTER U WITH TILDE
+0xDE 0x016A # LATIN CAPITAL LETTER U WITH MACRON
+0xDF 0x00DF # LATIN SMALL LETTER SHARP S
+0xE0 0x0101 # LATIN SMALL LETTER A WITH MACRON
+0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE
+0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3 0x00E3 # LATIN SMALL LETTER A WITH TILDE
+0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS
+0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE
+0xE6 0x00E6 # LATIN SMALL LETTER AE
+0xE7 0x012F # LATIN SMALL LETTER I WITH OGONEK
+0xE8 0x010D # LATIN SMALL LETTER C WITH CARON
+0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE
+0xEA 0x0119 # LATIN SMALL LETTER E WITH OGONEK
+0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS
+0xEC 0x0117 # LATIN SMALL LETTER E WITH DOT ABOVE
+0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE
+0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF 0x012B # LATIN SMALL LETTER I WITH MACRON
+0xF0 0x0111 # LATIN SMALL LETTER D WITH STROKE
+0xF1 0x0146 # LATIN SMALL LETTER N WITH CEDILLA
+0xF2 0x014D # LATIN SMALL LETTER O WITH MACRON
+0xF3 0x0137 # LATIN SMALL LETTER K WITH CEDILLA
+0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE
+0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS
+0xF7 0x00F7 # DIVISION SIGN
+0xF8 0x00F8 # LATIN SMALL LETTER O WITH STROKE
+0xF9 0x0173 # LATIN SMALL LETTER U WITH OGONEK
+0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE
+0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS
+0xFD 0x0169 # LATIN SMALL LETTER U WITH TILDE
+0xFE 0x016B # LATIN SMALL LETTER U WITH MACRON
+0xFF 0x02D9 # DOT ABOVE
diff --git a/ext/mbstring/tests/data/8859-5.txt b/ext/mbstring/tests/data/8859-5.txt
new file mode 100644
index 0000000000..a574c3feaf
--- /dev/null
+++ b/ext/mbstring/tests/data/8859-5.txt
@@ -0,0 +1,292 @@
+# 8859-5.TXT
+# Date: 2015-12-02 21:43:00 GMT [KW]
+# © 2015 Unicode®, Inc.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
+#
+# Name: ISO 8859-5:1999 to Unicode
+# Unicode version: 3.0
+# Table version: 2.0
+# Table format: Format A
+# Date: 1999 July 27 (header updated: 2015 December 02)
+# Authors: Ken Whistler <ken@unicode.org>
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO/IEC 8859-5:1999 characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO/IEC 8859-5 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO/IEC 8859-5 order.
+#
+# Version history
+# 1.0 version: updates 0.1 version by adding mappings for all
+# control characters.
+# 2.0 version: updates to copyright notice and terms of use; no
+# changes to character mappings
+#
+# Updated versions of this file may be found in:
+# http://www.unicode.org/Public/MAPPINGS/
+#
+# Any comments or problems, contact us at:
+# http://www.unicode.org/reporting.html
+#
+0x00 0x0000 # NULL
+0x01 0x0001 # START OF HEADING
+0x02 0x0002 # START OF TEXT
+0x03 0x0003 # END OF TEXT
+0x04 0x0004 # END OF TRANSMISSION
+0x05 0x0005 # ENQUIRY
+0x06 0x0006 # ACKNOWLEDGE
+0x07 0x0007 # BELL
+0x08 0x0008 # BACKSPACE
+0x09 0x0009 # HORIZONTAL TABULATION
+0x0A 0x000A # LINE FEED
+0x0B 0x000B # VERTICAL TABULATION
+0x0C 0x000C # FORM FEED
+0x0D 0x000D # CARRIAGE RETURN
+0x0E 0x000E # SHIFT OUT
+0x0F 0x000F # SHIFT IN
+0x10 0x0010 # DATA LINK ESCAPE
+0x11 0x0011 # DEVICE CONTROL ONE
+0x12 0x0012 # DEVICE CONTROL TWO
+0x13 0x0013 # DEVICE CONTROL THREE
+0x14 0x0014 # DEVICE CONTROL FOUR
+0x15 0x0015 # NEGATIVE ACKNOWLEDGE
+0x16 0x0016 # SYNCHRONOUS IDLE
+0x17 0x0017 # END OF TRANSMISSION BLOCK
+0x18 0x0018 # CANCEL
+0x19 0x0019 # END OF MEDIUM
+0x1A 0x001A # SUBSTITUTE
+0x1B 0x001B # ESCAPE
+0x1C 0x001C # FILE SEPARATOR
+0x1D 0x001D # GROUP SEPARATOR
+0x1E 0x001E # RECORD SEPARATOR
+0x1F 0x001F # UNIT SEPARATOR
+0x20 0x0020 # SPACE
+0x21 0x0021 # EXCLAMATION MARK
+0x22 0x0022 # QUOTATION MARK
+0x23 0x0023 # NUMBER SIGN
+0x24 0x0024 # DOLLAR SIGN
+0x25 0x0025 # PERCENT SIGN
+0x26 0x0026 # AMPERSAND
+0x27 0x0027 # APOSTROPHE
+0x28 0x0028 # LEFT PARENTHESIS
+0x29 0x0029 # RIGHT PARENTHESIS
+0x2A 0x002A # ASTERISK
+0x2B 0x002B # PLUS SIGN
+0x2C 0x002C # COMMA
+0x2D 0x002D # HYPHEN-MINUS
+0x2E 0x002E # FULL STOP
+0x2F 0x002F # SOLIDUS
+0x30 0x0030 # DIGIT ZERO
+0x31 0x0031 # DIGIT ONE
+0x32 0x0032 # DIGIT TWO
+0x33 0x0033 # DIGIT THREE
+0x34 0x0034 # DIGIT FOUR
+0x35 0x0035 # DIGIT FIVE
+0x36 0x0036 # DIGIT SIX
+0x37 0x0037 # DIGIT SEVEN
+0x38 0x0038 # DIGIT EIGHT
+0x39 0x0039 # DIGIT NINE
+0x3A 0x003A # COLON
+0x3B 0x003B # SEMICOLON
+0x3C 0x003C # LESS-THAN SIGN
+0x3D 0x003D # EQUALS SIGN
+0x3E 0x003E # GREATER-THAN SIGN
+0x3F 0x003F # QUESTION MARK
+0x40 0x0040 # COMMERCIAL AT
+0x41 0x0041 # LATIN CAPITAL LETTER A
+0x42 0x0042 # LATIN CAPITAL LETTER B
+0x43 0x0043 # LATIN CAPITAL LETTER C
+0x44 0x0044 # LATIN CAPITAL LETTER D
+0x45 0x0045 # LATIN CAPITAL LETTER E
+0x46 0x0046 # LATIN CAPITAL LETTER F
+0x47 0x0047 # LATIN CAPITAL LETTER G
+0x48 0x0048 # LATIN CAPITAL LETTER H
+0x49 0x0049 # LATIN CAPITAL LETTER I
+0x4A 0x004A # LATIN CAPITAL LETTER J
+0x4B 0x004B # LATIN CAPITAL LETTER K
+0x4C 0x004C # LATIN CAPITAL LETTER L
+0x4D 0x004D # LATIN CAPITAL LETTER M
+0x4E 0x004E # LATIN CAPITAL LETTER N
+0x4F 0x004F # LATIN CAPITAL LETTER O
+0x50 0x0050 # LATIN CAPITAL LETTER P
+0x51 0x0051 # LATIN CAPITAL LETTER Q
+0x52 0x0052 # LATIN CAPITAL LETTER R
+0x53 0x0053 # LATIN CAPITAL LETTER S
+0x54 0x0054 # LATIN CAPITAL LETTER T
+0x55 0x0055 # LATIN CAPITAL LETTER U
+0x56 0x0056 # LATIN CAPITAL LETTER V
+0x57 0x0057 # LATIN CAPITAL LETTER W
+0x58 0x0058 # LATIN CAPITAL LETTER X
+0x59 0x0059 # LATIN CAPITAL LETTER Y
+0x5A 0x005A # LATIN CAPITAL LETTER Z
+0x5B 0x005B # LEFT SQUARE BRACKET
+0x5C 0x005C # REVERSE SOLIDUS
+0x5D 0x005D # RIGHT SQUARE BRACKET
+0x5E 0x005E # CIRCUMFLEX ACCENT
+0x5F 0x005F # LOW LINE
+0x60 0x0060 # GRAVE ACCENT
+0x61 0x0061 # LATIN SMALL LETTER A
+0x62 0x0062 # LATIN SMALL LETTER B
+0x63 0x0063 # LATIN SMALL LETTER C
+0x64 0x0064 # LATIN SMALL LETTER D
+0x65 0x0065 # LATIN SMALL LETTER E
+0x66 0x0066 # LATIN SMALL LETTER F
+0x67 0x0067 # LATIN SMALL LETTER G
+0x68 0x0068 # LATIN SMALL LETTER H
+0x69 0x0069 # LATIN SMALL LETTER I
+0x6A 0x006A # LATIN SMALL LETTER J
+0x6B 0x006B # LATIN SMALL LETTER K
+0x6C 0x006C # LATIN SMALL LETTER L
+0x6D 0x006D # LATIN SMALL LETTER M
+0x6E 0x006E # LATIN SMALL LETTER N
+0x6F 0x006F # LATIN SMALL LETTER O
+0x70 0x0070 # LATIN SMALL LETTER P
+0x71 0x0071 # LATIN SMALL LETTER Q
+0x72 0x0072 # LATIN SMALL LETTER R
+0x73 0x0073 # LATIN SMALL LETTER S
+0x74 0x0074 # LATIN SMALL LETTER T
+0x75 0x0075 # LATIN SMALL LETTER U
+0x76 0x0076 # LATIN SMALL LETTER V
+0x77 0x0077 # LATIN SMALL LETTER W
+0x78 0x0078 # LATIN SMALL LETTER X
+0x79 0x0079 # LATIN SMALL LETTER Y
+0x7A 0x007A # LATIN SMALL LETTER Z
+0x7B 0x007B # LEFT CURLY BRACKET
+0x7C 0x007C # VERTICAL LINE
+0x7D 0x007D # RIGHT CURLY BRACKET
+0x7E 0x007E # TILDE
+0x7F 0x007F # DELETE
+0x80 0x0080 # <control>
+0x81 0x0081 # <control>
+0x82 0x0082 # <control>
+0x83 0x0083 # <control>
+0x84 0x0084 # <control>
+0x85 0x0085 # <control>
+0x86 0x0086 # <control>
+0x87 0x0087 # <control>
+0x88 0x0088 # <control>
+0x89 0x0089 # <control>
+0x8A 0x008A # <control>
+0x8B 0x008B # <control>
+0x8C 0x008C # <control>
+0x8D 0x008D # <control>
+0x8E 0x008E # <control>
+0x8F 0x008F # <control>
+0x90 0x0090 # <control>
+0x91 0x0091 # <control>
+0x92 0x0092 # <control>
+0x93 0x0093 # <control>
+0x94 0x0094 # <control>
+0x95 0x0095 # <control>
+0x96 0x0096 # <control>
+0x97 0x0097 # <control>
+0x98 0x0098 # <control>
+0x99 0x0099 # <control>
+0x9A 0x009A # <control>
+0x9B 0x009B # <control>
+0x9C 0x009C # <control>
+0x9D 0x009D # <control>
+0x9E 0x009E # <control>
+0x9F 0x009F # <control>
+0xA0 0x00A0 # NO-BREAK SPACE
+0xA1 0x0401 # CYRILLIC CAPITAL LETTER IO
+0xA2 0x0402 # CYRILLIC CAPITAL LETTER DJE
+0xA3 0x0403 # CYRILLIC CAPITAL LETTER GJE
+0xA4 0x0404 # CYRILLIC CAPITAL LETTER UKRAINIAN IE
+0xA5 0x0405 # CYRILLIC CAPITAL LETTER DZE
+0xA6 0x0406 # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+0xA7 0x0407 # CYRILLIC CAPITAL LETTER YI
+0xA8 0x0408 # CYRILLIC CAPITAL LETTER JE
+0xA9 0x0409 # CYRILLIC CAPITAL LETTER LJE
+0xAA 0x040A # CYRILLIC CAPITAL LETTER NJE
+0xAB 0x040B # CYRILLIC CAPITAL LETTER TSHE
+0xAC 0x040C # CYRILLIC CAPITAL LETTER KJE
+0xAD 0x00AD # SOFT HYPHEN
+0xAE 0x040E # CYRILLIC CAPITAL LETTER SHORT U
+0xAF 0x040F # CYRILLIC CAPITAL LETTER DZHE
+0xB0 0x0410 # CYRILLIC CAPITAL LETTER A
+0xB1 0x0411 # CYRILLIC CAPITAL LETTER BE
+0xB2 0x0412 # CYRILLIC CAPITAL LETTER VE
+0xB3 0x0413 # CYRILLIC CAPITAL LETTER GHE
+0xB4 0x0414 # CYRILLIC CAPITAL LETTER DE
+0xB5 0x0415 # CYRILLIC CAPITAL LETTER IE
+0xB6 0x0416 # CYRILLIC CAPITAL LETTER ZHE
+0xB7 0x0417 # CYRILLIC CAPITAL LETTER ZE
+0xB8 0x0418 # CYRILLIC CAPITAL LETTER I
+0xB9 0x0419 # CYRILLIC CAPITAL LETTER SHORT I
+0xBA 0x041A # CYRILLIC CAPITAL LETTER KA
+0xBB 0x041B # CYRILLIC CAPITAL LETTER EL
+0xBC 0x041C # CYRILLIC CAPITAL LETTER EM
+0xBD 0x041D # CYRILLIC CAPITAL LETTER EN
+0xBE 0x041E # CYRILLIC CAPITAL LETTER O
+0xBF 0x041F # CYRILLIC CAPITAL LETTER PE
+0xC0 0x0420 # CYRILLIC CAPITAL LETTER ER
+0xC1 0x0421 # CYRILLIC CAPITAL LETTER ES
+0xC2 0x0422 # CYRILLIC CAPITAL LETTER TE
+0xC3 0x0423 # CYRILLIC CAPITAL LETTER U
+0xC4 0x0424 # CYRILLIC CAPITAL LETTER EF
+0xC5 0x0425 # CYRILLIC CAPITAL LETTER HA
+0xC6 0x0426 # CYRILLIC CAPITAL LETTER TSE
+0xC7 0x0427 # CYRILLIC CAPITAL LETTER CHE
+0xC8 0x0428 # CYRILLIC CAPITAL LETTER SHA
+0xC9 0x0429 # CYRILLIC CAPITAL LETTER SHCHA
+0xCA 0x042A # CYRILLIC CAPITAL LETTER HARD SIGN
+0xCB 0x042B # CYRILLIC CAPITAL LETTER YERU
+0xCC 0x042C # CYRILLIC CAPITAL LETTER SOFT SIGN
+0xCD 0x042D # CYRILLIC CAPITAL LETTER E
+0xCE 0x042E # CYRILLIC CAPITAL LETTER YU
+0xCF 0x042F # CYRILLIC CAPITAL LETTER YA
+0xD0 0x0430 # CYRILLIC SMALL LETTER A
+0xD1 0x0431 # CYRILLIC SMALL LETTER BE
+0xD2 0x0432 # CYRILLIC SMALL LETTER VE
+0xD3 0x0433 # CYRILLIC SMALL LETTER GHE
+0xD4 0x0434 # CYRILLIC SMALL LETTER DE
+0xD5 0x0435 # CYRILLIC SMALL LETTER IE
+0xD6 0x0436 # CYRILLIC SMALL LETTER ZHE
+0xD7 0x0437 # CYRILLIC SMALL LETTER ZE
+0xD8 0x0438 # CYRILLIC SMALL LETTER I
+0xD9 0x0439 # CYRILLIC SMALL LETTER SHORT I
+0xDA 0x043A # CYRILLIC SMALL LETTER KA
+0xDB 0x043B # CYRILLIC SMALL LETTER EL
+0xDC 0x043C # CYRILLIC SMALL LETTER EM
+0xDD 0x043D # CYRILLIC SMALL LETTER EN
+0xDE 0x043E # CYRILLIC SMALL LETTER O
+0xDF 0x043F # CYRILLIC SMALL LETTER PE
+0xE0 0x0440 # CYRILLIC SMALL LETTER ER
+0xE1 0x0441 # CYRILLIC SMALL LETTER ES
+0xE2 0x0442 # CYRILLIC SMALL LETTER TE
+0xE3 0x0443 # CYRILLIC SMALL LETTER U
+0xE4 0x0444 # CYRILLIC SMALL LETTER EF
+0xE5 0x0445 # CYRILLIC SMALL LETTER HA
+0xE6 0x0446 # CYRILLIC SMALL LETTER TSE
+0xE7 0x0447 # CYRILLIC SMALL LETTER CHE
+0xE8 0x0448 # CYRILLIC SMALL LETTER SHA
+0xE9 0x0449 # CYRILLIC SMALL LETTER SHCHA
+0xEA 0x044A # CYRILLIC SMALL LETTER HARD SIGN
+0xEB 0x044B # CYRILLIC SMALL LETTER YERU
+0xEC 0x044C # CYRILLIC SMALL LETTER SOFT SIGN
+0xED 0x044D # CYRILLIC SMALL LETTER E
+0xEE 0x044E # CYRILLIC SMALL LETTER YU
+0xEF 0x044F # CYRILLIC SMALL LETTER YA
+0xF0 0x2116 # NUMERO SIGN
+0xF1 0x0451 # CYRILLIC SMALL LETTER IO
+0xF2 0x0452 # CYRILLIC SMALL LETTER DJE
+0xF3 0x0453 # CYRILLIC SMALL LETTER GJE
+0xF4 0x0454 # CYRILLIC SMALL LETTER UKRAINIAN IE
+0xF5 0x0455 # CYRILLIC SMALL LETTER DZE
+0xF6 0x0456 # CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+0xF7 0x0457 # CYRILLIC SMALL LETTER YI
+0xF8 0x0458 # CYRILLIC SMALL LETTER JE
+0xF9 0x0459 # CYRILLIC SMALL LETTER LJE
+0xFA 0x045A # CYRILLIC SMALL LETTER NJE
+0xFB 0x045B # CYRILLIC SMALL LETTER TSHE
+0xFC 0x045C # CYRILLIC SMALL LETTER KJE
+0xFD 0x00A7 # SECTION SIGN
+0xFE 0x045E # CYRILLIC SMALL LETTER SHORT U
+0xFF 0x045F # CYRILLIC SMALL LETTER DZHE
diff --git a/ext/mbstring/tests/data/8859-6.txt b/ext/mbstring/tests/data/8859-6.txt
new file mode 100644
index 0000000000..fed0af3631
--- /dev/null
+++ b/ext/mbstring/tests/data/8859-6.txt
@@ -0,0 +1,249 @@
+# 8859-6.TXT
+# Date: 2015-12-02 21:44:00 GMT [KW]
+# © 2015 Unicode®, Inc.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
+#
+# Name: ISO 8859-6:1999 to Unicode
+# Unicode version: 3.0
+# Table version: 2.0
+# Table format: Format A
+# Date: 1999 July 27 (header updated: 2015 December 02)
+# Authors: Ken Whistler <ken@unicode.org>
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO/IEC 8859-6:1999 characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO/IEC 8859-6 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO/IEC 8859-6 order.
+#
+# Version history
+# 1.0 version: updates 0.1 version by adding mappings for all
+# control characters.
+# 0x30..0x39 remapped to the ASCII digits (U+0030..U+0039) instead
+# of the Arabic digits (U+0660..U+0669).
+# 2.0 version: updates to copyright notice and terms of use; no
+# changes to character mappings
+#
+# Updated versions of this file may be found in:
+# http://www.unicode.org/Public/MAPPINGS/
+#
+# Any comments or problems, contact us at:
+# http://www.unicode.org/reporting.html
+#
+0x00 0x0000 # NULL
+0x01 0x0001 # START OF HEADING
+0x02 0x0002 # START OF TEXT
+0x03 0x0003 # END OF TEXT
+0x04 0x0004 # END OF TRANSMISSION
+0x05 0x0005 # ENQUIRY
+0x06 0x0006 # ACKNOWLEDGE
+0x07 0x0007 # BELL
+0x08 0x0008 # BACKSPACE
+0x09 0x0009 # HORIZONTAL TABULATION
+0x0A 0x000A # LINE FEED
+0x0B 0x000B # VERTICAL TABULATION
+0x0C 0x000C # FORM FEED
+0x0D 0x000D # CARRIAGE RETURN
+0x0E 0x000E # SHIFT OUT
+0x0F 0x000F # SHIFT IN
+0x10 0x0010 # DATA LINK ESCAPE
+0x11 0x0011 # DEVICE CONTROL ONE
+0x12 0x0012 # DEVICE CONTROL TWO
+0x13 0x0013 # DEVICE CONTROL THREE
+0x14 0x0014 # DEVICE CONTROL FOUR
+0x15 0x0015 # NEGATIVE ACKNOWLEDGE
+0x16 0x0016 # SYNCHRONOUS IDLE
+0x17 0x0017 # END OF TRANSMISSION BLOCK
+0x18 0x0018 # CANCEL
+0x19 0x0019 # END OF MEDIUM
+0x1A 0x001A # SUBSTITUTE
+0x1B 0x001B # ESCAPE
+0x1C 0x001C # FILE SEPARATOR
+0x1D 0x001D # GROUP SEPARATOR
+0x1E 0x001E # RECORD SEPARATOR
+0x1F 0x001F # UNIT SEPARATOR
+0x20 0x0020 # SPACE
+0x21 0x0021 # EXCLAMATION MARK
+0x22 0x0022 # QUOTATION MARK
+0x23 0x0023 # NUMBER SIGN
+0x24 0x0024 # DOLLAR SIGN
+0x25 0x0025 # PERCENT SIGN
+0x26 0x0026 # AMPERSAND
+0x27 0x0027 # APOSTROPHE
+0x28 0x0028 # LEFT PARENTHESIS
+0x29 0x0029 # RIGHT PARENTHESIS
+0x2A 0x002A # ASTERISK
+0x2B 0x002B # PLUS SIGN
+0x2C 0x002C # COMMA
+0x2D 0x002D # HYPHEN-MINUS
+0x2E 0x002E # FULL STOP
+0x2F 0x002F # SOLIDUS
+0x30 0x0030 # DIGIT ZERO
+0x31 0x0031 # DIGIT ONE
+0x32 0x0032 # DIGIT TWO
+0x33 0x0033 # DIGIT THREE
+0x34 0x0034 # DIGIT FOUR
+0x35 0x0035 # DIGIT FIVE
+0x36 0x0036 # DIGIT SIX
+0x37 0x0037 # DIGIT SEVEN
+0x38 0x0038 # DIGIT EIGHT
+0x39 0x0039 # DIGIT NINE
+0x3A 0x003A # COLON
+0x3B 0x003B # SEMICOLON
+0x3C 0x003C # LESS-THAN SIGN
+0x3D 0x003D # EQUALS SIGN
+0x3E 0x003E # GREATER-THAN SIGN
+0x3F 0x003F # QUESTION MARK
+0x40 0x0040 # COMMERCIAL AT
+0x41 0x0041 # LATIN CAPITAL LETTER A
+0x42 0x0042 # LATIN CAPITAL LETTER B
+0x43 0x0043 # LATIN CAPITAL LETTER C
+0x44 0x0044 # LATIN CAPITAL LETTER D
+0x45 0x0045 # LATIN CAPITAL LETTER E
+0x46 0x0046 # LATIN CAPITAL LETTER F
+0x47 0x0047 # LATIN CAPITAL LETTER G
+0x48 0x0048 # LATIN CAPITAL LETTER H
+0x49 0x0049 # LATIN CAPITAL LETTER I
+0x4A 0x004A # LATIN CAPITAL LETTER J
+0x4B 0x004B # LATIN CAPITAL LETTER K
+0x4C 0x004C # LATIN CAPITAL LETTER L
+0x4D 0x004D # LATIN CAPITAL LETTER M
+0x4E 0x004E # LATIN CAPITAL LETTER N
+0x4F 0x004F # LATIN CAPITAL LETTER O
+0x50 0x0050 # LATIN CAPITAL LETTER P
+0x51 0x0051 # LATIN CAPITAL LETTER Q
+0x52 0x0052 # LATIN CAPITAL LETTER R
+0x53 0x0053 # LATIN CAPITAL LETTER S
+0x54 0x0054 # LATIN CAPITAL LETTER T
+0x55 0x0055 # LATIN CAPITAL LETTER U
+0x56 0x0056 # LATIN CAPITAL LETTER V
+0x57 0x0057 # LATIN CAPITAL LETTER W
+0x58 0x0058 # LATIN CAPITAL LETTER X
+0x59 0x0059 # LATIN CAPITAL LETTER Y
+0x5A 0x005A # LATIN CAPITAL LETTER Z
+0x5B 0x005B # LEFT SQUARE BRACKET
+0x5C 0x005C # REVERSE SOLIDUS
+0x5D 0x005D # RIGHT SQUARE BRACKET
+0x5E 0x005E # CIRCUMFLEX ACCENT
+0x5F 0x005F # LOW LINE
+0x60 0x0060 # GRAVE ACCENT
+0x61 0x0061 # LATIN SMALL LETTER A
+0x62 0x0062 # LATIN SMALL LETTER B
+0x63 0x0063 # LATIN SMALL LETTER C
+0x64 0x0064 # LATIN SMALL LETTER D
+0x65 0x0065 # LATIN SMALL LETTER E
+0x66 0x0066 # LATIN SMALL LETTER F
+0x67 0x0067 # LATIN SMALL LETTER G
+0x68 0x0068 # LATIN SMALL LETTER H
+0x69 0x0069 # LATIN SMALL LETTER I
+0x6A 0x006A # LATIN SMALL LETTER J
+0x6B 0x006B # LATIN SMALL LETTER K
+0x6C 0x006C # LATIN SMALL LETTER L
+0x6D 0x006D # LATIN SMALL LETTER M
+0x6E 0x006E # LATIN SMALL LETTER N
+0x6F 0x006F # LATIN SMALL LETTER O
+0x70 0x0070 # LATIN SMALL LETTER P
+0x71 0x0071 # LATIN SMALL LETTER Q
+0x72 0x0072 # LATIN SMALL LETTER R
+0x73 0x0073 # LATIN SMALL LETTER S
+0x74 0x0074 # LATIN SMALL LETTER T
+0x75 0x0075 # LATIN SMALL LETTER U
+0x76 0x0076 # LATIN SMALL LETTER V
+0x77 0x0077 # LATIN SMALL LETTER W
+0x78 0x0078 # LATIN SMALL LETTER X
+0x79 0x0079 # LATIN SMALL LETTER Y
+0x7A 0x007A # LATIN SMALL LETTER Z
+0x7B 0x007B # LEFT CURLY BRACKET
+0x7C 0x007C # VERTICAL LINE
+0x7D 0x007D # RIGHT CURLY BRACKET
+0x7E 0x007E # TILDE
+0x7F 0x007F # DELETE
+0x80 0x0080 # <control>
+0x81 0x0081 # <control>
+0x82 0x0082 # <control>
+0x83 0x0083 # <control>
+0x84 0x0084 # <control>
+0x85 0x0085 # <control>
+0x86 0x0086 # <control>
+0x87 0x0087 # <control>
+0x88 0x0088 # <control>
+0x89 0x0089 # <control>
+0x8A 0x008A # <control>
+0x8B 0x008B # <control>
+0x8C 0x008C # <control>
+0x8D 0x008D # <control>
+0x8E 0x008E # <control>
+0x8F 0x008F # <control>
+0x90 0x0090 # <control>
+0x91 0x0091 # <control>
+0x92 0x0092 # <control>
+0x93 0x0093 # <control>
+0x94 0x0094 # <control>
+0x95 0x0095 # <control>
+0x96 0x0096 # <control>
+0x97 0x0097 # <control>
+0x98 0x0098 # <control>
+0x99 0x0099 # <control>
+0x9A 0x009A # <control>
+0x9B 0x009B # <control>
+0x9C 0x009C # <control>
+0x9D 0x009D # <control>
+0x9E 0x009E # <control>
+0x9F 0x009F # <control>
+0xA0 0x00A0 # NO-BREAK SPACE
+0xA4 0x00A4 # CURRENCY SIGN
+0xAC 0x060C # ARABIC COMMA
+0xAD 0x00AD # SOFT HYPHEN
+0xBB 0x061B # ARABIC SEMICOLON
+0xBF 0x061F # ARABIC QUESTION MARK
+0xC1 0x0621 # ARABIC LETTER HAMZA
+0xC2 0x0622 # ARABIC LETTER ALEF WITH MADDA ABOVE
+0xC3 0x0623 # ARABIC LETTER ALEF WITH HAMZA ABOVE
+0xC4 0x0624 # ARABIC LETTER WAW WITH HAMZA ABOVE
+0xC5 0x0625 # ARABIC LETTER ALEF WITH HAMZA BELOW
+0xC6 0x0626 # ARABIC LETTER YEH WITH HAMZA ABOVE
+0xC7 0x0627 # ARABIC LETTER ALEF
+0xC8 0x0628 # ARABIC LETTER BEH
+0xC9 0x0629 # ARABIC LETTER TEH MARBUTA
+0xCA 0x062A # ARABIC LETTER TEH
+0xCB 0x062B # ARABIC LETTER THEH
+0xCC 0x062C # ARABIC LETTER JEEM
+0xCD 0x062D # ARABIC LETTER HAH
+0xCE 0x062E # ARABIC LETTER KHAH
+0xCF 0x062F # ARABIC LETTER DAL
+0xD0 0x0630 # ARABIC LETTER THAL
+0xD1 0x0631 # ARABIC LETTER REH
+0xD2 0x0632 # ARABIC LETTER ZAIN
+0xD3 0x0633 # ARABIC LETTER SEEN
+0xD4 0x0634 # ARABIC LETTER SHEEN
+0xD5 0x0635 # ARABIC LETTER SAD
+0xD6 0x0636 # ARABIC LETTER DAD
+0xD7 0x0637 # ARABIC LETTER TAH
+0xD8 0x0638 # ARABIC LETTER ZAH
+0xD9 0x0639 # ARABIC LETTER AIN
+0xDA 0x063A # ARABIC LETTER GHAIN
+0xE0 0x0640 # ARABIC TATWEEL
+0xE1 0x0641 # ARABIC LETTER FEH
+0xE2 0x0642 # ARABIC LETTER QAF
+0xE3 0x0643 # ARABIC LETTER KAF
+0xE4 0x0644 # ARABIC LETTER LAM
+0xE5 0x0645 # ARABIC LETTER MEEM
+0xE6 0x0646 # ARABIC LETTER NOON
+0xE7 0x0647 # ARABIC LETTER HEH
+0xE8 0x0648 # ARABIC LETTER WAW
+0xE9 0x0649 # ARABIC LETTER ALEF MAKSURA
+0xEA 0x064A # ARABIC LETTER YEH
+0xEB 0x064B # ARABIC FATHATAN
+0xEC 0x064C # ARABIC DAMMATAN
+0xED 0x064D # ARABIC KASRATAN
+0xEE 0x064E # ARABIC FATHA
+0xEF 0x064F # ARABIC DAMMA
+0xF0 0x0650 # ARABIC KASRA
+0xF1 0x0651 # ARABIC SHADDA
+0xF2 0x0652 # ARABIC SUKUN
diff --git a/ext/mbstring/tests/data/8859-7.txt b/ext/mbstring/tests/data/8859-7.txt
new file mode 100644
index 0000000000..49131a4d94
--- /dev/null
+++ b/ext/mbstring/tests/data/8859-7.txt
@@ -0,0 +1,299 @@
+# 8859-7.TXT
+# Date: 2015-12-02 21:47:00 GMT [KW]
+# © 2015 Unicode®, Inc.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
+#
+# Name: ISO 8859-7:2003 to Unicode
+# Unicode version: 4.0
+# Table version: 3.0
+# Table format: Format A
+# Date: 2003-Nov-12 (header updated: 2015 December 02)
+# Authors: Ken Whistler <ken@unicode.org>
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO 8859-7:2003 characters map into Unicode.
+#
+# ISO 8859-7:1987 is equivalent to ISO-IR-126, ELOT 928,
+# and ECMA 118. ISO 8859-7:2003 adds two currency signs
+# and one other character not in the earlier standard.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO 8859-7 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO 8859-7 order.
+#
+# Version history
+# 1.0 version updates 0.1 version by adding mappings for all
+# control characters.
+# Remap 0xA1 to U+2018 (instead of 0x02BD) to match text of 8859-7
+# Remap 0xA2 to U+2019 (instead of 0x02BC) to match text of 8859-7
+#
+# 2.0 version updates 1.0 version by adding mappings for the
+# three newly added characters 0xA4, 0xA5, 0xAA.
+#
+# 3.0 version: updates to copyright notice and terms of use; no
+# changes to character mappings
+#
+# Updated versions of this file may be found in:
+# http://www.unicode.org/Public/MAPPINGS/
+#
+# Any comments or problems, contact us at:
+# http://www.unicode.org/reporting.html
+#
+0x00 0x0000 # NULL
+0x01 0x0001 # START OF HEADING
+0x02 0x0002 # START OF TEXT
+0x03 0x0003 # END OF TEXT
+0x04 0x0004 # END OF TRANSMISSION
+0x05 0x0005 # ENQUIRY
+0x06 0x0006 # ACKNOWLEDGE
+0x07 0x0007 # BELL
+0x08 0x0008 # BACKSPACE
+0x09 0x0009 # HORIZONTAL TABULATION
+0x0A 0x000A # LINE FEED
+0x0B 0x000B # VERTICAL TABULATION
+0x0C 0x000C # FORM FEED
+0x0D 0x000D # CARRIAGE RETURN
+0x0E 0x000E # SHIFT OUT
+0x0F 0x000F # SHIFT IN
+0x10 0x0010 # DATA LINK ESCAPE
+0x11 0x0011 # DEVICE CONTROL ONE
+0x12 0x0012 # DEVICE CONTROL TWO
+0x13 0x0013 # DEVICE CONTROL THREE
+0x14 0x0014 # DEVICE CONTROL FOUR
+0x15 0x0015 # NEGATIVE ACKNOWLEDGE
+0x16 0x0016 # SYNCHRONOUS IDLE
+0x17 0x0017 # END OF TRANSMISSION BLOCK
+0x18 0x0018 # CANCEL
+0x19 0x0019 # END OF MEDIUM
+0x1A 0x001A # SUBSTITUTE
+0x1B 0x001B # ESCAPE
+0x1C 0x001C # FILE SEPARATOR
+0x1D 0x001D # GROUP SEPARATOR
+0x1E 0x001E # RECORD SEPARATOR
+0x1F 0x001F # UNIT SEPARATOR
+0x20 0x0020 # SPACE
+0x21 0x0021 # EXCLAMATION MARK
+0x22 0x0022 # QUOTATION MARK
+0x23 0x0023 # NUMBER SIGN
+0x24 0x0024 # DOLLAR SIGN
+0x25 0x0025 # PERCENT SIGN
+0x26 0x0026 # AMPERSAND
+0x27 0x0027 # APOSTROPHE
+0x28 0x0028 # LEFT PARENTHESIS
+0x29 0x0029 # RIGHT PARENTHESIS
+0x2A 0x002A # ASTERISK
+0x2B 0x002B # PLUS SIGN
+0x2C 0x002C # COMMA
+0x2D 0x002D # HYPHEN-MINUS
+0x2E 0x002E # FULL STOP
+0x2F 0x002F # SOLIDUS
+0x30 0x0030 # DIGIT ZERO
+0x31 0x0031 # DIGIT ONE
+0x32 0x0032 # DIGIT TWO
+0x33 0x0033 # DIGIT THREE
+0x34 0x0034 # DIGIT FOUR
+0x35 0x0035 # DIGIT FIVE
+0x36 0x0036 # DIGIT SIX
+0x37 0x0037 # DIGIT SEVEN
+0x38 0x0038 # DIGIT EIGHT
+0x39 0x0039 # DIGIT NINE
+0x3A 0x003A # COLON
+0x3B 0x003B # SEMICOLON
+0x3C 0x003C # LESS-THAN SIGN
+0x3D 0x003D # EQUALS SIGN
+0x3E 0x003E # GREATER-THAN SIGN
+0x3F 0x003F # QUESTION MARK
+0x40 0x0040 # COMMERCIAL AT
+0x41 0x0041 # LATIN CAPITAL LETTER A
+0x42 0x0042 # LATIN CAPITAL LETTER B
+0x43 0x0043 # LATIN CAPITAL LETTER C
+0x44 0x0044 # LATIN CAPITAL LETTER D
+0x45 0x0045 # LATIN CAPITAL LETTER E
+0x46 0x0046 # LATIN CAPITAL LETTER F
+0x47 0x0047 # LATIN CAPITAL LETTER G
+0x48 0x0048 # LATIN CAPITAL LETTER H
+0x49 0x0049 # LATIN CAPITAL LETTER I
+0x4A 0x004A # LATIN CAPITAL LETTER J
+0x4B 0x004B # LATIN CAPITAL LETTER K
+0x4C 0x004C # LATIN CAPITAL LETTER L
+0x4D 0x004D # LATIN CAPITAL LETTER M
+0x4E 0x004E # LATIN CAPITAL LETTER N
+0x4F 0x004F # LATIN CAPITAL LETTER O
+0x50 0x0050 # LATIN CAPITAL LETTER P
+0x51 0x0051 # LATIN CAPITAL LETTER Q
+0x52 0x0052 # LATIN CAPITAL LETTER R
+0x53 0x0053 # LATIN CAPITAL LETTER S
+0x54 0x0054 # LATIN CAPITAL LETTER T
+0x55 0x0055 # LATIN CAPITAL LETTER U
+0x56 0x0056 # LATIN CAPITAL LETTER V
+0x57 0x0057 # LATIN CAPITAL LETTER W
+0x58 0x0058 # LATIN CAPITAL LETTER X
+0x59 0x0059 # LATIN CAPITAL LETTER Y
+0x5A 0x005A # LATIN CAPITAL LETTER Z
+0x5B 0x005B # LEFT SQUARE BRACKET
+0x5C 0x005C # REVERSE SOLIDUS
+0x5D 0x005D # RIGHT SQUARE BRACKET
+0x5E 0x005E # CIRCUMFLEX ACCENT
+0x5F 0x005F # LOW LINE
+0x60 0x0060 # GRAVE ACCENT
+0x61 0x0061 # LATIN SMALL LETTER A
+0x62 0x0062 # LATIN SMALL LETTER B
+0x63 0x0063 # LATIN SMALL LETTER C
+0x64 0x0064 # LATIN SMALL LETTER D
+0x65 0x0065 # LATIN SMALL LETTER E
+0x66 0x0066 # LATIN SMALL LETTER F
+0x67 0x0067 # LATIN SMALL LETTER G
+0x68 0x0068 # LATIN SMALL LETTER H
+0x69 0x0069 # LATIN SMALL LETTER I
+0x6A 0x006A # LATIN SMALL LETTER J
+0x6B 0x006B # LATIN SMALL LETTER K
+0x6C 0x006C # LATIN SMALL LETTER L
+0x6D 0x006D # LATIN SMALL LETTER M
+0x6E 0x006E # LATIN SMALL LETTER N
+0x6F 0x006F # LATIN SMALL LETTER O
+0x70 0x0070 # LATIN SMALL LETTER P
+0x71 0x0071 # LATIN SMALL LETTER Q
+0x72 0x0072 # LATIN SMALL LETTER R
+0x73 0x0073 # LATIN SMALL LETTER S
+0x74 0x0074 # LATIN SMALL LETTER T
+0x75 0x0075 # LATIN SMALL LETTER U
+0x76 0x0076 # LATIN SMALL LETTER V
+0x77 0x0077 # LATIN SMALL LETTER W
+0x78 0x0078 # LATIN SMALL LETTER X
+0x79 0x0079 # LATIN SMALL LETTER Y
+0x7A 0x007A # LATIN SMALL LETTER Z
+0x7B 0x007B # LEFT CURLY BRACKET
+0x7C 0x007C # VERTICAL LINE
+0x7D 0x007D # RIGHT CURLY BRACKET
+0x7E 0x007E # TILDE
+0x7F 0x007F # DELETE
+0x80 0x0080 # <control>
+0x81 0x0081 # <control>
+0x82 0x0082 # <control>
+0x83 0x0083 # <control>
+0x84 0x0084 # <control>
+0x85 0x0085 # <control>
+0x86 0x0086 # <control>
+0x87 0x0087 # <control>
+0x88 0x0088 # <control>
+0x89 0x0089 # <control>
+0x8A 0x008A # <control>
+0x8B 0x008B # <control>
+0x8C 0x008C # <control>
+0x8D 0x008D # <control>
+0x8E 0x008E # <control>
+0x8F 0x008F # <control>
+0x90 0x0090 # <control>
+0x91 0x0091 # <control>
+0x92 0x0092 # <control>
+0x93 0x0093 # <control>
+0x94 0x0094 # <control>
+0x95 0x0095 # <control>
+0x96 0x0096 # <control>
+0x97 0x0097 # <control>
+0x98 0x0098 # <control>
+0x99 0x0099 # <control>
+0x9A 0x009A # <control>
+0x9B 0x009B # <control>
+0x9C 0x009C # <control>
+0x9D 0x009D # <control>
+0x9E 0x009E # <control>
+0x9F 0x009F # <control>
+0xA0 0x00A0 # NO-BREAK SPACE
+0xA1 0x2018 # LEFT SINGLE QUOTATION MARK
+0xA2 0x2019 # RIGHT SINGLE QUOTATION MARK
+0xA3 0x00A3 # POUND SIGN
+0xA4 0x20AC # EURO SIGN
+0xA5 0x20AF # DRACHMA SIGN
+0xA6 0x00A6 # BROKEN BAR
+0xA7 0x00A7 # SECTION SIGN
+0xA8 0x00A8 # DIAERESIS
+0xA9 0x00A9 # COPYRIGHT SIGN
+0xAA 0x037A # GREEK YPOGEGRAMMENI
+0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC 0x00AC # NOT SIGN
+0xAD 0x00AD # SOFT HYPHEN
+0xAF 0x2015 # HORIZONTAL BAR
+0xB0 0x00B0 # DEGREE SIGN
+0xB1 0x00B1 # PLUS-MINUS SIGN
+0xB2 0x00B2 # SUPERSCRIPT TWO
+0xB3 0x00B3 # SUPERSCRIPT THREE
+0xB4 0x0384 # GREEK TONOS
+0xB5 0x0385 # GREEK DIALYTIKA TONOS
+0xB6 0x0386 # GREEK CAPITAL LETTER ALPHA WITH TONOS
+0xB7 0x00B7 # MIDDLE DOT
+0xB8 0x0388 # GREEK CAPITAL LETTER EPSILON WITH TONOS
+0xB9 0x0389 # GREEK CAPITAL LETTER ETA WITH TONOS
+0xBA 0x038A # GREEK CAPITAL LETTER IOTA WITH TONOS
+0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC 0x038C # GREEK CAPITAL LETTER OMICRON WITH TONOS
+0xBD 0x00BD # VULGAR FRACTION ONE HALF
+0xBE 0x038E # GREEK CAPITAL LETTER UPSILON WITH TONOS
+0xBF 0x038F # GREEK CAPITAL LETTER OMEGA WITH TONOS
+0xC0 0x0390 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+0xC1 0x0391 # GREEK CAPITAL LETTER ALPHA
+0xC2 0x0392 # GREEK CAPITAL LETTER BETA
+0xC3 0x0393 # GREEK CAPITAL LETTER GAMMA
+0xC4 0x0394 # GREEK CAPITAL LETTER DELTA
+0xC5 0x0395 # GREEK CAPITAL LETTER EPSILON
+0xC6 0x0396 # GREEK CAPITAL LETTER ZETA
+0xC7 0x0397 # GREEK CAPITAL LETTER ETA
+0xC8 0x0398 # GREEK CAPITAL LETTER THETA
+0xC9 0x0399 # GREEK CAPITAL LETTER IOTA
+0xCA 0x039A # GREEK CAPITAL LETTER KAPPA
+0xCB 0x039B # GREEK CAPITAL LETTER LAMDA
+0xCC 0x039C # GREEK CAPITAL LETTER MU
+0xCD 0x039D # GREEK CAPITAL LETTER NU
+0xCE 0x039E # GREEK CAPITAL LETTER XI
+0xCF 0x039F # GREEK CAPITAL LETTER OMICRON
+0xD0 0x03A0 # GREEK CAPITAL LETTER PI
+0xD1 0x03A1 # GREEK CAPITAL LETTER RHO
+0xD3 0x03A3 # GREEK CAPITAL LETTER SIGMA
+0xD4 0x03A4 # GREEK CAPITAL LETTER TAU
+0xD5 0x03A5 # GREEK CAPITAL LETTER UPSILON
+0xD6 0x03A6 # GREEK CAPITAL LETTER PHI
+0xD7 0x03A7 # GREEK CAPITAL LETTER CHI
+0xD8 0x03A8 # GREEK CAPITAL LETTER PSI
+0xD9 0x03A9 # GREEK CAPITAL LETTER OMEGA
+0xDA 0x03AA # GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+0xDB 0x03AB # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+0xDC 0x03AC # GREEK SMALL LETTER ALPHA WITH TONOS
+0xDD 0x03AD # GREEK SMALL LETTER EPSILON WITH TONOS
+0xDE 0x03AE # GREEK SMALL LETTER ETA WITH TONOS
+0xDF 0x03AF # GREEK SMALL LETTER IOTA WITH TONOS
+0xE0 0x03B0 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+0xE1 0x03B1 # GREEK SMALL LETTER ALPHA
+0xE2 0x03B2 # GREEK SMALL LETTER BETA
+0xE3 0x03B3 # GREEK SMALL LETTER GAMMA
+0xE4 0x03B4 # GREEK SMALL LETTER DELTA
+0xE5 0x03B5 # GREEK SMALL LETTER EPSILON
+0xE6 0x03B6 # GREEK SMALL LETTER ZETA
+0xE7 0x03B7 # GREEK SMALL LETTER ETA
+0xE8 0x03B8 # GREEK SMALL LETTER THETA
+0xE9 0x03B9 # GREEK SMALL LETTER IOTA
+0xEA 0x03BA # GREEK SMALL LETTER KAPPA
+0xEB 0x03BB # GREEK SMALL LETTER LAMDA
+0xEC 0x03BC # GREEK SMALL LETTER MU
+0xED 0x03BD # GREEK SMALL LETTER NU
+0xEE 0x03BE # GREEK SMALL LETTER XI
+0xEF 0x03BF # GREEK SMALL LETTER OMICRON
+0xF0 0x03C0 # GREEK SMALL LETTER PI
+0xF1 0x03C1 # GREEK SMALL LETTER RHO
+0xF2 0x03C2 # GREEK SMALL LETTER FINAL SIGMA
+0xF3 0x03C3 # GREEK SMALL LETTER SIGMA
+0xF4 0x03C4 # GREEK SMALL LETTER TAU
+0xF5 0x03C5 # GREEK SMALL LETTER UPSILON
+0xF6 0x03C6 # GREEK SMALL LETTER PHI
+0xF7 0x03C7 # GREEK SMALL LETTER CHI
+0xF8 0x03C8 # GREEK SMALL LETTER PSI
+0xF9 0x03C9 # GREEK SMALL LETTER OMEGA
+0xFA 0x03CA # GREEK SMALL LETTER IOTA WITH DIALYTIKA
+0xFB 0x03CB # GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+0xFC 0x03CC # GREEK SMALL LETTER OMICRON WITH TONOS
+0xFD 0x03CD # GREEK SMALL LETTER UPSILON WITH TONOS
+0xFE 0x03CE # GREEK SMALL LETTER OMEGA WITH TONOS
diff --git a/ext/mbstring/tests/data/8859-8.txt b/ext/mbstring/tests/data/8859-8.txt
new file mode 100644
index 0000000000..ff068f7083
--- /dev/null
+++ b/ext/mbstring/tests/data/8859-8.txt
@@ -0,0 +1,258 @@
+# 8859-8.TXT
+# Date: 2015-12-02 21:50:00 GMT [KW]
+# © 2015 Unicode®, Inc.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
+#
+# Name: ISO/IEC 8859-8:1999 to Unicode
+# Unicode version: 3.0
+# Table version: 2.0
+# Table format: Format A
+# Date: 2000-Jan-03 (header updated: 2015 December 02)
+# Authors: Ken Whistler <ken@unicode.org>
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO/IEC 8859-8:1999 characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO/IEC 8859-8 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO/IEC 8859-8 order.
+#
+# Version history
+# 1.0 version updates 0.1 version by adding mappings for all
+# control characters.
+# 1.1 version updates to the published 8859-8:1999, correcting
+# the mapping of 0xAF and adding mappings for LRM and RLM.
+# 2.0 version: updates to copyright notice and terms of use; no
+# changes to character mappings
+#
+# Updated versions of this file may be found in:
+# http://www.unicode.org/Public/MAPPINGS/
+#
+# Any comments or problems, contact us at:
+# http://www.unicode.org/reporting.html
+#
+0x00 0x0000 # NULL
+0x01 0x0001 # START OF HEADING
+0x02 0x0002 # START OF TEXT
+0x03 0x0003 # END OF TEXT
+0x04 0x0004 # END OF TRANSMISSION
+0x05 0x0005 # ENQUIRY
+0x06 0x0006 # ACKNOWLEDGE
+0x07 0x0007 # BELL
+0x08 0x0008 # BACKSPACE
+0x09 0x0009 # HORIZONTAL TABULATION
+0x0A 0x000A # LINE FEED
+0x0B 0x000B # VERTICAL TABULATION
+0x0C 0x000C # FORM FEED
+0x0D 0x000D # CARRIAGE RETURN
+0x0E 0x000E # SHIFT OUT
+0x0F 0x000F # SHIFT IN
+0x10 0x0010 # DATA LINK ESCAPE
+0x11 0x0011 # DEVICE CONTROL ONE
+0x12 0x0012 # DEVICE CONTROL TWO
+0x13 0x0013 # DEVICE CONTROL THREE
+0x14 0x0014 # DEVICE CONTROL FOUR
+0x15 0x0015 # NEGATIVE ACKNOWLEDGE
+0x16 0x0016 # SYNCHRONOUS IDLE
+0x17 0x0017 # END OF TRANSMISSION BLOCK
+0x18 0x0018 # CANCEL
+0x19 0x0019 # END OF MEDIUM
+0x1A 0x001A # SUBSTITUTE
+0x1B 0x001B # ESCAPE
+0x1C 0x001C # FILE SEPARATOR
+0x1D 0x001D # GROUP SEPARATOR
+0x1E 0x001E # RECORD SEPARATOR
+0x1F 0x001F # UNIT SEPARATOR
+0x20 0x0020 # SPACE
+0x21 0x0021 # EXCLAMATION MARK
+0x22 0x0022 # QUOTATION MARK
+0x23 0x0023 # NUMBER SIGN
+0x24 0x0024 # DOLLAR SIGN
+0x25 0x0025 # PERCENT SIGN
+0x26 0x0026 # AMPERSAND
+0x27 0x0027 # APOSTROPHE
+0x28 0x0028 # LEFT PARENTHESIS
+0x29 0x0029 # RIGHT PARENTHESIS
+0x2A 0x002A # ASTERISK
+0x2B 0x002B # PLUS SIGN
+0x2C 0x002C # COMMA
+0x2D 0x002D # HYPHEN-MINUS
+0x2E 0x002E # FULL STOP
+0x2F 0x002F # SOLIDUS
+0x30 0x0030 # DIGIT ZERO
+0x31 0x0031 # DIGIT ONE
+0x32 0x0032 # DIGIT TWO
+0x33 0x0033 # DIGIT THREE
+0x34 0x0034 # DIGIT FOUR
+0x35 0x0035 # DIGIT FIVE
+0x36 0x0036 # DIGIT SIX
+0x37 0x0037 # DIGIT SEVEN
+0x38 0x0038 # DIGIT EIGHT
+0x39 0x0039 # DIGIT NINE
+0x3A 0x003A # COLON
+0x3B 0x003B # SEMICOLON
+0x3C 0x003C # LESS-THAN SIGN
+0x3D 0x003D # EQUALS SIGN
+0x3E 0x003E # GREATER-THAN SIGN
+0x3F 0x003F # QUESTION MARK
+0x40 0x0040 # COMMERCIAL AT
+0x41 0x0041 # LATIN CAPITAL LETTER A
+0x42 0x0042 # LATIN CAPITAL LETTER B
+0x43 0x0043 # LATIN CAPITAL LETTER C
+0x44 0x0044 # LATIN CAPITAL LETTER D
+0x45 0x0045 # LATIN CAPITAL LETTER E
+0x46 0x0046 # LATIN CAPITAL LETTER F
+0x47 0x0047 # LATIN CAPITAL LETTER G
+0x48 0x0048 # LATIN CAPITAL LETTER H
+0x49 0x0049 # LATIN CAPITAL LETTER I
+0x4A 0x004A # LATIN CAPITAL LETTER J
+0x4B 0x004B # LATIN CAPITAL LETTER K
+0x4C 0x004C # LATIN CAPITAL LETTER L
+0x4D 0x004D # LATIN CAPITAL LETTER M
+0x4E 0x004E # LATIN CAPITAL LETTER N
+0x4F 0x004F # LATIN CAPITAL LETTER O
+0x50 0x0050 # LATIN CAPITAL LETTER P
+0x51 0x0051 # LATIN CAPITAL LETTER Q
+0x52 0x0052 # LATIN CAPITAL LETTER R
+0x53 0x0053 # LATIN CAPITAL LETTER S
+0x54 0x0054 # LATIN CAPITAL LETTER T
+0x55 0x0055 # LATIN CAPITAL LETTER U
+0x56 0x0056 # LATIN CAPITAL LETTER V
+0x57 0x0057 # LATIN CAPITAL LETTER W
+0x58 0x0058 # LATIN CAPITAL LETTER X
+0x59 0x0059 # LATIN CAPITAL LETTER Y
+0x5A 0x005A # LATIN CAPITAL LETTER Z
+0x5B 0x005B # LEFT SQUARE BRACKET
+0x5C 0x005C # REVERSE SOLIDUS
+0x5D 0x005D # RIGHT SQUARE BRACKET
+0x5E 0x005E # CIRCUMFLEX ACCENT
+0x5F 0x005F # LOW LINE
+0x60 0x0060 # GRAVE ACCENT
+0x61 0x0061 # LATIN SMALL LETTER A
+0x62 0x0062 # LATIN SMALL LETTER B
+0x63 0x0063 # LATIN SMALL LETTER C
+0x64 0x0064 # LATIN SMALL LETTER D
+0x65 0x0065 # LATIN SMALL LETTER E
+0x66 0x0066 # LATIN SMALL LETTER F
+0x67 0x0067 # LATIN SMALL LETTER G
+0x68 0x0068 # LATIN SMALL LETTER H
+0x69 0x0069 # LATIN SMALL LETTER I
+0x6A 0x006A # LATIN SMALL LETTER J
+0x6B 0x006B # LATIN SMALL LETTER K
+0x6C 0x006C # LATIN SMALL LETTER L
+0x6D 0x006D # LATIN SMALL LETTER M
+0x6E 0x006E # LATIN SMALL LETTER N
+0x6F 0x006F # LATIN SMALL LETTER O
+0x70 0x0070 # LATIN SMALL LETTER P
+0x71 0x0071 # LATIN SMALL LETTER Q
+0x72 0x0072 # LATIN SMALL LETTER R
+0x73 0x0073 # LATIN SMALL LETTER S
+0x74 0x0074 # LATIN SMALL LETTER T
+0x75 0x0075 # LATIN SMALL LETTER U
+0x76 0x0076 # LATIN SMALL LETTER V
+0x77 0x0077 # LATIN SMALL LETTER W
+0x78 0x0078 # LATIN SMALL LETTER X
+0x79 0x0079 # LATIN SMALL LETTER Y
+0x7A 0x007A # LATIN SMALL LETTER Z
+0x7B 0x007B # LEFT CURLY BRACKET
+0x7C 0x007C # VERTICAL LINE
+0x7D 0x007D # RIGHT CURLY BRACKET
+0x7E 0x007E # TILDE
+0x7F 0x007F # DELETE
+0x80 0x0080 # <control>
+0x81 0x0081 # <control>
+0x82 0x0082 # <control>
+0x83 0x0083 # <control>
+0x84 0x0084 # <control>
+0x85 0x0085 # <control>
+0x86 0x0086 # <control>
+0x87 0x0087 # <control>
+0x88 0x0088 # <control>
+0x89 0x0089 # <control>
+0x8A 0x008A # <control>
+0x8B 0x008B # <control>
+0x8C 0x008C # <control>
+0x8D 0x008D # <control>
+0x8E 0x008E # <control>
+0x8F 0x008F # <control>
+0x90 0x0090 # <control>
+0x91 0x0091 # <control>
+0x92 0x0092 # <control>
+0x93 0x0093 # <control>
+0x94 0x0094 # <control>
+0x95 0x0095 # <control>
+0x96 0x0096 # <control>
+0x97 0x0097 # <control>
+0x98 0x0098 # <control>
+0x99 0x0099 # <control>
+0x9A 0x009A # <control>
+0x9B 0x009B # <control>
+0x9C 0x009C # <control>
+0x9D 0x009D # <control>
+0x9E 0x009E # <control>
+0x9F 0x009F # <control>
+0xA0 0x00A0 # NO-BREAK SPACE
+0xA2 0x00A2 # CENT SIGN
+0xA3 0x00A3 # POUND SIGN
+0xA4 0x00A4 # CURRENCY SIGN
+0xA5 0x00A5 # YEN SIGN
+0xA6 0x00A6 # BROKEN BAR
+0xA7 0x00A7 # SECTION SIGN
+0xA8 0x00A8 # DIAERESIS
+0xA9 0x00A9 # COPYRIGHT SIGN
+0xAA 0x00D7 # MULTIPLICATION SIGN
+0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC 0x00AC # NOT SIGN
+0xAD 0x00AD # SOFT HYPHEN
+0xAE 0x00AE # REGISTERED SIGN
+0xAF 0x00AF # MACRON
+0xB0 0x00B0 # DEGREE SIGN
+0xB1 0x00B1 # PLUS-MINUS SIGN
+0xB2 0x00B2 # SUPERSCRIPT TWO
+0xB3 0x00B3 # SUPERSCRIPT THREE
+0xB4 0x00B4 # ACUTE ACCENT
+0xB5 0x00B5 # MICRO SIGN
+0xB6 0x00B6 # PILCROW SIGN
+0xB7 0x00B7 # MIDDLE DOT
+0xB8 0x00B8 # CEDILLA
+0xB9 0x00B9 # SUPERSCRIPT ONE
+0xBA 0x00F7 # DIVISION SIGN
+0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC 0x00BC # VULGAR FRACTION ONE QUARTER
+0xBD 0x00BD # VULGAR FRACTION ONE HALF
+0xBE 0x00BE # VULGAR FRACTION THREE QUARTERS
+0xDF 0x2017 # DOUBLE LOW LINE
+0xE0 0x05D0 # HEBREW LETTER ALEF
+0xE1 0x05D1 # HEBREW LETTER BET
+0xE2 0x05D2 # HEBREW LETTER GIMEL
+0xE3 0x05D3 # HEBREW LETTER DALET
+0xE4 0x05D4 # HEBREW LETTER HE
+0xE5 0x05D5 # HEBREW LETTER VAV
+0xE6 0x05D6 # HEBREW LETTER ZAYIN
+0xE7 0x05D7 # HEBREW LETTER HET
+0xE8 0x05D8 # HEBREW LETTER TET
+0xE9 0x05D9 # HEBREW LETTER YOD
+0xEA 0x05DA # HEBREW LETTER FINAL KAF
+0xEB 0x05DB # HEBREW LETTER KAF
+0xEC 0x05DC # HEBREW LETTER LAMED
+0xED 0x05DD # HEBREW LETTER FINAL MEM
+0xEE 0x05DE # HEBREW LETTER MEM
+0xEF 0x05DF # HEBREW LETTER FINAL NUN
+0xF0 0x05E0 # HEBREW LETTER NUN
+0xF1 0x05E1 # HEBREW LETTER SAMEKH
+0xF2 0x05E2 # HEBREW LETTER AYIN
+0xF3 0x05E3 # HEBREW LETTER FINAL PE
+0xF4 0x05E4 # HEBREW LETTER PE
+0xF5 0x05E5 # HEBREW LETTER FINAL TSADI
+0xF6 0x05E6 # HEBREW LETTER TSADI
+0xF7 0x05E7 # HEBREW LETTER QOF
+0xF8 0x05E8 # HEBREW LETTER RESH
+0xF9 0x05E9 # HEBREW LETTER SHIN
+0xFA 0x05EA # HEBREW LETTER TAV
+0xFD 0x200E # LEFT-TO-RIGHT MARK
+0xFE 0x200F # RIGHT-TO-LEFT MARK
diff --git a/ext/mbstring/tests/data/8859-9.txt b/ext/mbstring/tests/data/8859-9.txt
new file mode 100644
index 0000000000..d0c9ff94e4
--- /dev/null
+++ b/ext/mbstring/tests/data/8859-9.txt
@@ -0,0 +1,294 @@
+# 8859-9.TXT
+# Date: 2015-12-02 21:51:00 GMT [KW]
+# © 2015 Unicode®, Inc.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
+#
+# Name: ISO/IEC 8859-9:1999 to Unicode
+# Unicode version: 3.0
+# Table version: 2.0
+# Table format: Format A
+# Date: 1999 July 27 (header updated: 2015 December 02)
+# Authors: Ken Whistler <ken@unicode.org>
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO/IEC 8859-9:1999 characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO/IEC 8859-9 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO/IEC 8859-9 order.
+#
+# ISO/IEC 8859-9 is also equivalent to ISO-IR-148.
+#
+# Version history
+# 1.0 version: updates 0.1 version by adding mappings for all
+# control characters.
+# 2.0 version: updates to copyright notice and terms of use; no
+# changes to character mappings
+#
+# Updated versions of this file may be found in:
+# http://www.unicode.org/Public/MAPPINGS/
+#
+# Any comments or problems, contact us at:
+# http://www.unicode.org/reporting.html
+#
+0x00 0x0000 # NULL
+0x01 0x0001 # START OF HEADING
+0x02 0x0002 # START OF TEXT
+0x03 0x0003 # END OF TEXT
+0x04 0x0004 # END OF TRANSMISSION
+0x05 0x0005 # ENQUIRY
+0x06 0x0006 # ACKNOWLEDGE
+0x07 0x0007 # BELL
+0x08 0x0008 # BACKSPACE
+0x09 0x0009 # HORIZONTAL TABULATION
+0x0A 0x000A # LINE FEED
+0x0B 0x000B # VERTICAL TABULATION
+0x0C 0x000C # FORM FEED
+0x0D 0x000D # CARRIAGE RETURN
+0x0E 0x000E # SHIFT OUT
+0x0F 0x000F # SHIFT IN
+0x10 0x0010 # DATA LINK ESCAPE
+0x11 0x0011 # DEVICE CONTROL ONE
+0x12 0x0012 # DEVICE CONTROL TWO
+0x13 0x0013 # DEVICE CONTROL THREE
+0x14 0x0014 # DEVICE CONTROL FOUR
+0x15 0x0015 # NEGATIVE ACKNOWLEDGE
+0x16 0x0016 # SYNCHRONOUS IDLE
+0x17 0x0017 # END OF TRANSMISSION BLOCK
+0x18 0x0018 # CANCEL
+0x19 0x0019 # END OF MEDIUM
+0x1A 0x001A # SUBSTITUTE
+0x1B 0x001B # ESCAPE
+0x1C 0x001C # FILE SEPARATOR
+0x1D 0x001D # GROUP SEPARATOR
+0x1E 0x001E # RECORD SEPARATOR
+0x1F 0x001F # UNIT SEPARATOR
+0x20 0x0020 # SPACE
+0x21 0x0021 # EXCLAMATION MARK
+0x22 0x0022 # QUOTATION MARK
+0x23 0x0023 # NUMBER SIGN
+0x24 0x0024 # DOLLAR SIGN
+0x25 0x0025 # PERCENT SIGN
+0x26 0x0026 # AMPERSAND
+0x27 0x0027 # APOSTROPHE
+0x28 0x0028 # LEFT PARENTHESIS
+0x29 0x0029 # RIGHT PARENTHESIS
+0x2A 0x002A # ASTERISK
+0x2B 0x002B # PLUS SIGN
+0x2C 0x002C # COMMA
+0x2D 0x002D # HYPHEN-MINUS
+0x2E 0x002E # FULL STOP
+0x2F 0x002F # SOLIDUS
+0x30 0x0030 # DIGIT ZERO
+0x31 0x0031 # DIGIT ONE
+0x32 0x0032 # DIGIT TWO
+0x33 0x0033 # DIGIT THREE
+0x34 0x0034 # DIGIT FOUR
+0x35 0x0035 # DIGIT FIVE
+0x36 0x0036 # DIGIT SIX
+0x37 0x0037 # DIGIT SEVEN
+0x38 0x0038 # DIGIT EIGHT
+0x39 0x0039 # DIGIT NINE
+0x3A 0x003A # COLON
+0x3B 0x003B # SEMICOLON
+0x3C 0x003C # LESS-THAN SIGN
+0x3D 0x003D # EQUALS SIGN
+0x3E 0x003E # GREATER-THAN SIGN
+0x3F 0x003F # QUESTION MARK
+0x40 0x0040 # COMMERCIAL AT
+0x41 0x0041 # LATIN CAPITAL LETTER A
+0x42 0x0042 # LATIN CAPITAL LETTER B
+0x43 0x0043 # LATIN CAPITAL LETTER C
+0x44 0x0044 # LATIN CAPITAL LETTER D
+0x45 0x0045 # LATIN CAPITAL LETTER E
+0x46 0x0046 # LATIN CAPITAL LETTER F
+0x47 0x0047 # LATIN CAPITAL LETTER G
+0x48 0x0048 # LATIN CAPITAL LETTER H
+0x49 0x0049 # LATIN CAPITAL LETTER I
+0x4A 0x004A # LATIN CAPITAL LETTER J
+0x4B 0x004B # LATIN CAPITAL LETTER K
+0x4C 0x004C # LATIN CAPITAL LETTER L
+0x4D 0x004D # LATIN CAPITAL LETTER M
+0x4E 0x004E # LATIN CAPITAL LETTER N
+0x4F 0x004F # LATIN CAPITAL LETTER O
+0x50 0x0050 # LATIN CAPITAL LETTER P
+0x51 0x0051 # LATIN CAPITAL LETTER Q
+0x52 0x0052 # LATIN CAPITAL LETTER R
+0x53 0x0053 # LATIN CAPITAL LETTER S
+0x54 0x0054 # LATIN CAPITAL LETTER T
+0x55 0x0055 # LATIN CAPITAL LETTER U
+0x56 0x0056 # LATIN CAPITAL LETTER V
+0x57 0x0057 # LATIN CAPITAL LETTER W
+0x58 0x0058 # LATIN CAPITAL LETTER X
+0x59 0x0059 # LATIN CAPITAL LETTER Y
+0x5A 0x005A # LATIN CAPITAL LETTER Z
+0x5B 0x005B # LEFT SQUARE BRACKET
+0x5C 0x005C # REVERSE SOLIDUS
+0x5D 0x005D # RIGHT SQUARE BRACKET
+0x5E 0x005E # CIRCUMFLEX ACCENT
+0x5F 0x005F # LOW LINE
+0x60 0x0060 # GRAVE ACCENT
+0x61 0x0061 # LATIN SMALL LETTER A
+0x62 0x0062 # LATIN SMALL LETTER B
+0x63 0x0063 # LATIN SMALL LETTER C
+0x64 0x0064 # LATIN SMALL LETTER D
+0x65 0x0065 # LATIN SMALL LETTER E
+0x66 0x0066 # LATIN SMALL LETTER F
+0x67 0x0067 # LATIN SMALL LETTER G
+0x68 0x0068 # LATIN SMALL LETTER H
+0x69 0x0069 # LATIN SMALL LETTER I
+0x6A 0x006A # LATIN SMALL LETTER J
+0x6B 0x006B # LATIN SMALL LETTER K
+0x6C 0x006C # LATIN SMALL LETTER L
+0x6D 0x006D # LATIN SMALL LETTER M
+0x6E 0x006E # LATIN SMALL LETTER N
+0x6F 0x006F # LATIN SMALL LETTER O
+0x70 0x0070 # LATIN SMALL LETTER P
+0x71 0x0071 # LATIN SMALL LETTER Q
+0x72 0x0072 # LATIN SMALL LETTER R
+0x73 0x0073 # LATIN SMALL LETTER S
+0x74 0x0074 # LATIN SMALL LETTER T
+0x75 0x0075 # LATIN SMALL LETTER U
+0x76 0x0076 # LATIN SMALL LETTER V
+0x77 0x0077 # LATIN SMALL LETTER W
+0x78 0x0078 # LATIN SMALL LETTER X
+0x79 0x0079 # LATIN SMALL LETTER Y
+0x7A 0x007A # LATIN SMALL LETTER Z
+0x7B 0x007B # LEFT CURLY BRACKET
+0x7C 0x007C # VERTICAL LINE
+0x7D 0x007D # RIGHT CURLY BRACKET
+0x7E 0x007E # TILDE
+0x7F 0x007F # DELETE
+0x80 0x0080 # <control>
+0x81 0x0081 # <control>
+0x82 0x0082 # <control>
+0x83 0x0083 # <control>
+0x84 0x0084 # <control>
+0x85 0x0085 # <control>
+0x86 0x0086 # <control>
+0x87 0x0087 # <control>
+0x88 0x0088 # <control>
+0x89 0x0089 # <control>
+0x8A 0x008A # <control>
+0x8B 0x008B # <control>
+0x8C 0x008C # <control>
+0x8D 0x008D # <control>
+0x8E 0x008E # <control>
+0x8F 0x008F # <control>
+0x90 0x0090 # <control>
+0x91 0x0091 # <control>
+0x92 0x0092 # <control>
+0x93 0x0093 # <control>
+0x94 0x0094 # <control>
+0x95 0x0095 # <control>
+0x96 0x0096 # <control>
+0x97 0x0097 # <control>
+0x98 0x0098 # <control>
+0x99 0x0099 # <control>
+0x9A 0x009A # <control>
+0x9B 0x009B # <control>
+0x9C 0x009C # <control>
+0x9D 0x009D # <control>
+0x9E 0x009E # <control>
+0x9F 0x009F # <control>
+0xA0 0x00A0 # NO-BREAK SPACE
+0xA1 0x00A1 # INVERTED EXCLAMATION MARK
+0xA2 0x00A2 # CENT SIGN
+0xA3 0x00A3 # POUND SIGN
+0xA4 0x00A4 # CURRENCY SIGN
+0xA5 0x00A5 # YEN SIGN
+0xA6 0x00A6 # BROKEN BAR
+0xA7 0x00A7 # SECTION SIGN
+0xA8 0x00A8 # DIAERESIS
+0xA9 0x00A9 # COPYRIGHT SIGN
+0xAA 0x00AA # FEMININE ORDINAL INDICATOR
+0xAB 0x00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC 0x00AC # NOT SIGN
+0xAD 0x00AD # SOFT HYPHEN
+0xAE 0x00AE # REGISTERED SIGN
+0xAF 0x00AF # MACRON
+0xB0 0x00B0 # DEGREE SIGN
+0xB1 0x00B1 # PLUS-MINUS SIGN
+0xB2 0x00B2 # SUPERSCRIPT TWO
+0xB3 0x00B3 # SUPERSCRIPT THREE
+0xB4 0x00B4 # ACUTE ACCENT
+0xB5 0x00B5 # MICRO SIGN
+0xB6 0x00B6 # PILCROW SIGN
+0xB7 0x00B7 # MIDDLE DOT
+0xB8 0x00B8 # CEDILLA
+0xB9 0x00B9 # SUPERSCRIPT ONE
+0xBA 0x00BA # MASCULINE ORDINAL INDICATOR
+0xBB 0x00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC 0x00BC # VULGAR FRACTION ONE QUARTER
+0xBD 0x00BD # VULGAR FRACTION ONE HALF
+0xBE 0x00BE # VULGAR FRACTION THREE QUARTERS
+0xBF 0x00BF # INVERTED QUESTION MARK
+0xC0 0x00C0 # LATIN CAPITAL LETTER A WITH GRAVE
+0xC1 0x00C1 # LATIN CAPITAL LETTER A WITH ACUTE
+0xC2 0x00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3 0x00C3 # LATIN CAPITAL LETTER A WITH TILDE
+0xC4 0x00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5 0x00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6 0x00C6 # LATIN CAPITAL LETTER AE
+0xC7 0x00C7 # LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8 0x00C8 # LATIN CAPITAL LETTER E WITH GRAVE
+0xC9 0x00C9 # LATIN CAPITAL LETTER E WITH ACUTE
+0xCA 0x00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xCB 0x00CB # LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC 0x00CC # LATIN CAPITAL LETTER I WITH GRAVE
+0xCD 0x00CD # LATIN CAPITAL LETTER I WITH ACUTE
+0xCE 0x00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF 0x00CF # LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD0 0x011E # LATIN CAPITAL LETTER G WITH BREVE
+0xD1 0x00D1 # LATIN CAPITAL LETTER N WITH TILDE
+0xD2 0x00D2 # LATIN CAPITAL LETTER O WITH GRAVE
+0xD3 0x00D3 # LATIN CAPITAL LETTER O WITH ACUTE
+0xD4 0x00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5 0x00D5 # LATIN CAPITAL LETTER O WITH TILDE
+0xD6 0x00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7 0x00D7 # MULTIPLICATION SIGN
+0xD8 0x00D8 # LATIN CAPITAL LETTER O WITH STROKE
+0xD9 0x00D9 # LATIN CAPITAL LETTER U WITH GRAVE
+0xDA 0x00DA # LATIN CAPITAL LETTER U WITH ACUTE
+0xDB 0x00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC 0x00DC # LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD 0x0130 # LATIN CAPITAL LETTER I WITH DOT ABOVE
+0xDE 0x015E # LATIN CAPITAL LETTER S WITH CEDILLA
+0xDF 0x00DF # LATIN SMALL LETTER SHARP S
+0xE0 0x00E0 # LATIN SMALL LETTER A WITH GRAVE
+0xE1 0x00E1 # LATIN SMALL LETTER A WITH ACUTE
+0xE2 0x00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3 0x00E3 # LATIN SMALL LETTER A WITH TILDE
+0xE4 0x00E4 # LATIN SMALL LETTER A WITH DIAERESIS
+0xE5 0x00E5 # LATIN SMALL LETTER A WITH RING ABOVE
+0xE6 0x00E6 # LATIN SMALL LETTER AE
+0xE7 0x00E7 # LATIN SMALL LETTER C WITH CEDILLA
+0xE8 0x00E8 # LATIN SMALL LETTER E WITH GRAVE
+0xE9 0x00E9 # LATIN SMALL LETTER E WITH ACUTE
+0xEA 0x00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xEB 0x00EB # LATIN SMALL LETTER E WITH DIAERESIS
+0xEC 0x00EC # LATIN SMALL LETTER I WITH GRAVE
+0xED 0x00ED # LATIN SMALL LETTER I WITH ACUTE
+0xEE 0x00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF 0x00EF # LATIN SMALL LETTER I WITH DIAERESIS
+0xF0 0x011F # LATIN SMALL LETTER G WITH BREVE
+0xF1 0x00F1 # LATIN SMALL LETTER N WITH TILDE
+0xF2 0x00F2 # LATIN SMALL LETTER O WITH GRAVE
+0xF3 0x00F3 # LATIN SMALL LETTER O WITH ACUTE
+0xF4 0x00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5 0x00F5 # LATIN SMALL LETTER O WITH TILDE
+0xF6 0x00F6 # LATIN SMALL LETTER O WITH DIAERESIS
+0xF7 0x00F7 # DIVISION SIGN
+0xF8 0x00F8 # LATIN SMALL LETTER O WITH STROKE
+0xF9 0x00F9 # LATIN SMALL LETTER U WITH GRAVE
+0xFA 0x00FA # LATIN SMALL LETTER U WITH ACUTE
+0xFB 0x00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC 0x00FC # LATIN SMALL LETTER U WITH DIAERESIS
+0xFD 0x0131 # LATIN SMALL LETTER DOTLESS I
+0xFE 0x015F # LATIN SMALL LETTER S WITH CEDILLA
+0xFF 0x00FF # LATIN SMALL LETTER Y WITH DIAERESIS
diff --git a/ext/mbstring/tests/encoding_tests.inc b/ext/mbstring/tests/encoding_tests.inc
new file mode 100644
index 0000000000..43c6addee6
--- /dev/null
+++ b/ext/mbstring/tests/encoding_tests.inc
@@ -0,0 +1,98 @@
+<?php
+
+// Common code for tests which focus on conversion and verification of text
+// in some specific encoding
+
+function dbgPrint($str) {
+ $result = '';
+ if (mb_check_encoding($str, 'ASCII'))
+ $result .= '"' . $str . '" ';
+ return $result . "(" . bin2hex($str) . ")";
+}
+
+function identifyValidString($goodString, $encoding) {
+ $result = mb_check_encoding($goodString, $encoding);
+ if (!$result)
+ die("mb_check_encoding failed on good $encoding string: " . dbgPrint($goodString));
+}
+
+function identifyInvalidString($badString, $encoding) {
+ $result = mb_check_encoding($badString, $encoding);
+ if ($result)
+ die("mb_check_encoding passed on bad $encoding string: " . dbgPrint($badString));
+}
+
+function testConversion($fromString, $toString, $fromEncoding, $toEncoding) {
+ $result = mb_convert_encoding($fromString, $toEncoding, $fromEncoding);
+ if ($result !== $toString)
+ die("mb_convert_encoding not working on $fromEncoding input: " . dbgPrint($fromString) . "\nExpected $toEncoding: " . dbgPrint($toString) . "\nActually got: " . dbgPrint($result));
+}
+
+function testValidConversion($fromString, $toString, $fromEncoding, $toEncoding) {
+ $illegalChars = mb_get_info('illegal_chars');
+ testConversion($fromString, $toString, $fromEncoding, $toEncoding);
+ if (mb_get_info('illegal_chars') !== $illegalChars)
+ die("mb_convert_encoding incremented illegal_chars on valid $fromEncoding string: " . dbgPrint($fromString) . " when converting to $toEncoding");
+}
+
+function convertValidString($fromString, $toString, $fromEncoding, $toEncoding, $bothWays = true) {
+ testValidConversion($fromString, $toString, $fromEncoding, $toEncoding);
+ if ($bothWays)
+ testValidConversion($toString, $fromString, $toEncoding, $fromEncoding);
+}
+
+function convertInvalidString($fromString, $toString, $fromEncoding, $toEncoding) {
+ $illegalChars = mb_get_info('illegal_chars');
+ testConversion($fromString, $toString, $fromEncoding, $toEncoding);
+ if (mb_get_info('illegal_chars') <= $illegalChars)
+ die("mb_convert_encoding did not increment illegal_chars on invalid $fromEncoding string: " . dbgPrint($fromString) . " when converting to $toEncoding");
+}
+
+function testValidString($fromString, $toString, $fromEncoding, $toEncoding, $bothWays = true) {
+ identifyValidString($fromString, $fromEncoding);
+ convertValidString($fromString, $toString, $fromEncoding, $toEncoding, $bothWays);
+}
+
+function testInvalidString($fromString, $toString, $fromEncoding, $toEncoding) {
+ identifyInvalidString($fromString, $fromEncoding);
+ convertInvalidString($fromString, $toString, $fromEncoding, $toEncoding);
+}
+
+// Only for encodings where valid characters can be concatenated together in any
+// way, without any escape sequences
+// Also only for encodings which can be converted losslessly to and from $toEncoding
+function testAllValidChars($charMap, $fromEncoding, $toEncoding) {
+ $goodChars = array_keys($charMap);
+ shuffle($goodChars);
+ while (!empty($goodChars)) {
+ $length = min(rand(5,10), count($goodChars));
+ $fromString = $toString = '';
+ while ($length--) {
+ $goodChar = array_pop($goodChars);
+ $fromString .= $goodChar;
+ $toString .= $charMap[$goodChar];
+ }
+
+ testValidString($fromString, $toString, $fromEncoding, $toEncoding);
+ }
+}
+
+function testAllInvalidChars($badChars, $charMap, $fromEncoding, $toEncoding, $replacement) {
+ $badChars = array_keys($badChars);
+ shuffle($badChars);
+ $goodChars = array_keys($charMap);
+ shuffle($goodChars);
+ while (!empty($badChars)) {
+ if (empty($goodChars)) {
+ $goodChars = array_keys($charMap);
+ shuffle($goodChars);
+ }
+ $goodChar = array_pop($goodChars);
+ $fromString = array_pop($badChars) . $goodChar;
+ $toString = $replacement . $charMap[$goodChar];
+
+ testInvalidString($fromString, $toString, $fromEncoding, $toEncoding);
+ }
+}
+
+?>
diff --git a/ext/mbstring/tests/iso8859_encodings.phpt b/ext/mbstring/tests/iso8859_encodings.phpt
new file mode 100644
index 0000000000..2ad647a589
--- /dev/null
+++ b/ext/mbstring/tests/iso8859_encodings.phpt
@@ -0,0 +1,75 @@
+--TEST--
+Exhaustive test of verification and conversion of ISO-8859-X text
+--SKIPIF--
+<?php
+extension_loaded('mbstring') or die('skip mbstring not available');
+if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
+?>
+--FILE--
+<?php
+srand(678); // Make results consistent
+include('encoding_tests.inc');
+mb_substitute_character(0x25); // '%'
+
+function testValid($from, $to, $n) {
+ testValidString($from, $to, "ISO-8859-$n", 'UTF-16BE');
+}
+function testInvalid($from, $to, $n) {
+ testInvalidString($from, $to, "ISO-8859-$n", 'UTF-16BE');
+}
+
+for ($n = 1; $n <= 16; $n++) {
+ if ($n == 11 || $n == 12)
+ continue;
+
+ $toUnicode = array();
+ $fromUnicode = array();
+
+ $fp = fopen(realpath(__DIR__ . "/data/8859-$n.txt"), 'r+');
+ while ($line = fgets($fp, 256)) {
+ if ($line[0] == '#')
+ continue;
+
+ if (sscanf($line, "0x%x\t0x%x", $byte, $codepoint) == 2) {
+ $toUnicode[$byte] = pack('n', $codepoint);
+ $fromUnicode[$codepoint] = chr($byte);
+ }
+ }
+
+ // Try all ISO-8859-{$n} bytes (these are single-byte encodings)
+ for ($i = 0; $i < 256; $i++) {
+ if (isset($toUnicode[$i])) {
+ testValid(chr($i), $toUnicode[$i], $n);
+ } else {
+ testInvalid(chr($i), "\x00%", $n);
+ }
+ }
+
+ // Try all Unicode codepoints up to 0xFFFF
+ for ($i = 0; $i <= 0xFFFF; $i++) {
+ if (isset($fromUnicode[$i])) {
+ testValid($fromUnicode[$i], pack('n', $i), $n);
+ } else if (($i & 0xfc00) != 0xd800) {
+ convertInvalidString(pack('n', $i), "%", 'UTF-16BE', "ISO-8859-{$n}");
+ }
+ }
+
+ echo "All is fine and dandy for ISO-8859-$n text\n";
+}
+
+?>
+--EXPECT--
+All is fine and dandy for ISO-8859-1 text
+All is fine and dandy for ISO-8859-2 text
+All is fine and dandy for ISO-8859-3 text
+All is fine and dandy for ISO-8859-4 text
+All is fine and dandy for ISO-8859-5 text
+All is fine and dandy for ISO-8859-6 text
+All is fine and dandy for ISO-8859-7 text
+All is fine and dandy for ISO-8859-8 text
+All is fine and dandy for ISO-8859-9 text
+All is fine and dandy for ISO-8859-10 text
+All is fine and dandy for ISO-8859-13 text
+All is fine and dandy for ISO-8859-14 text
+All is fine and dandy for ISO-8859-15 text
+All is fine and dandy for ISO-8859-16 text
diff --git a/ext/mbstring/tests/mb_convert_encoding_failed_detection.phpt b/ext/mbstring/tests/mb_convert_encoding_failed_detection.phpt
index b3c8ba10bb..45efe28766 100644
--- a/ext/mbstring/tests/mb_convert_encoding_failed_detection.phpt
+++ b/ext/mbstring/tests/mb_convert_encoding_failed_detection.phpt
@@ -1,5 +1,7 @@
--TEST--
mb_convert_encoding() when encoding detection fails
+--INI--
+mbstring.strict_detection=1
--FILE--
<?php
diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c
index 10f20eede8..55da87fdf0 100644
--- a/ext/mysqlnd/mysqlnd_ps.c
+++ b/ext/mysqlnd/mysqlnd_ps.c
@@ -109,7 +109,7 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s)
}
/* Position at the first row */
set->data_cursor = set->data;
- } else if (result->stored_data->type == MYSQLND_BUFFERED_TYPE_ZVAL) {
+ } else if (result->stored_data->type == MYSQLND_BUFFERED_TYPE_C) {
/*TODO*/
}
diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
index 22b484b789..56757895bb 100644
--- a/ext/opcache/ZendAccelerator.c
+++ b/ext/opcache/ZendAccelerator.c
@@ -802,7 +802,7 @@ static inline void kill_all_lockers(struct flock *mem_usage_check)
/* errno is not ESRCH or we ran out of tries to kill the locker */
ZCSG(force_restart_time) = time(NULL); /* restore forced restart request */
/* cannot kill the locker, bail out with error */
- zend_accel_error(ACCEL_LOG_ERROR, "Cannot kill process %d!", mem_usage_check->l_pid);
+ zend_accel_error_noreturn(ACCEL_LOG_ERROR, "Cannot kill process %d!", mem_usage_check->l_pid);
}
mem_usage_check->l_type = F_WRLCK;
@@ -2639,7 +2639,7 @@ static int zend_accel_init_shm(void)
accel_shared_globals = zend_shared_alloc(sizeof(zend_accel_shared_globals) + sizeof(uint32_t));
}
if (!accel_shared_globals) {
- zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Insufficient shared memory!");
zend_shared_alloc_unlock();
return FAILURE;
}
@@ -2981,7 +2981,7 @@ static zend_result accel_post_startup(void)
page_size = getpagesize();
# endif
if (!page_size || (page_size & (page_size - 1))) {
- zend_accel_error(ACCEL_LOG_FATAL, "Failure to initialize shared memory structures - can't get page size.");
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Failure to initialize shared memory structures - can't get page size.");
abort();
}
jit_size = JIT_G(buffer_size);
@@ -3001,7 +3001,7 @@ static zend_result accel_post_startup(void)
break;
case ALLOC_FAILURE:
accel_startup_ok = 0;
- zend_accel_error(ACCEL_LOG_FATAL, "Failure to initialize shared memory structures - probably not enough shared memory.");
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Failure to initialize shared memory structures - probably not enough shared memory.");
return SUCCESS;
case SUCCESSFULLY_REATTACHED:
#if defined(HAVE_JIT) && !defined(ZEND_WIN32)
@@ -3014,7 +3014,7 @@ static zend_result accel_post_startup(void)
break;
case FAILED_REATTACHED:
accel_startup_ok = 0;
- zend_accel_error(ACCEL_LOG_FATAL, "Failure to initialize shared memory structures - can not reattach to exiting shared memory.");
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Failure to initialize shared memory structures - can not reattach to exiting shared memory.");
return SUCCESS;
break;
#if ENABLE_FILE_CACHE_FALLBACK
@@ -3054,7 +3054,7 @@ static zend_result accel_post_startup(void)
SHM_PROTECT();
} else if (!ZCG(accel_directives).file_cache) {
accel_startup_ok = 0;
- zend_accel_error(ACCEL_LOG_FATAL, "opcache.file_cache_only is set without a proper setting of opcache.file_cache");
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "opcache.file_cache_only is set without a proper setting of opcache.file_cache");
return SUCCESS;
} else {
accel_shared_globals = calloc(1, sizeof(zend_accel_shared_globals));
@@ -4217,7 +4217,7 @@ static zend_persistent_script* preload_script_in_shared_memory(zend_persistent_s
uint32_t checkpoint;
if (zend_accel_hash_is_full(&ZCSG(hash))) {
- zend_accel_error(ACCEL_LOG_FATAL, "Not enough entries in hash table for preloading. Consider increasing the value for the opcache.max_accelerated_files directive in php.ini.");
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Not enough entries in hash table for preloading. Consider increasing the value for the opcache.max_accelerated_files directive in php.ini.");
return NULL;
}
@@ -4269,7 +4269,7 @@ static zend_persistent_script* preload_script_in_shared_memory(zend_persistent_s
}
#endif
if (!ZCG(mem)) {
- zend_accel_error(ACCEL_LOG_FATAL, "Not enough shared memory for preloading. Consider increasing the value for the opcache.memory_consumption directive in php.ini.");
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Not enough shared memory for preloading. Consider increasing the value for the opcache.memory_consumption directive in php.ini.");
return NULL;
}
@@ -4587,7 +4587,7 @@ static int accel_preload(const char *config, zend_bool in_child)
CG(map_ptr_last) = orig_map_ptr_last;
if (EG(full_tables_cleanup)) {
- zend_accel_error(ACCEL_LOG_FATAL, "Preloading is not compatible with dl() function.");
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading is not compatible with dl() function.");
ret = FAILURE;
goto finish;
}
@@ -4670,7 +4670,7 @@ static int accel_preload(const char *config, zend_bool in_child)
zend_hash_sort_ex(&script->script.class_table, preload_sort_classes, NULL, 0);
if (preload_optimize(script) != SUCCESS) {
- zend_accel_error(ACCEL_LOG_FATAL, "Optimization error during preloading!");
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Optimization error during preloading!");
return FAILURE;
}
@@ -4769,7 +4769,7 @@ static int accel_finish_startup(void)
if (ZCG(accel_directives).preload && *ZCG(accel_directives).preload) {
#ifdef ZEND_WIN32
- zend_accel_error(ACCEL_LOG_ERROR, "Preloading is not supported on Windows");
+ zend_accel_error_noreturn(ACCEL_LOG_ERROR, "Preloading is not supported on Windows");
return FAILURE;
#else
int in_child = 0;
@@ -4812,21 +4812,21 @@ static int accel_finish_startup(void)
if (!ZCG(accel_directives).preload_user
|| !*ZCG(accel_directives).preload_user) {
zend_shared_alloc_unlock();
- zend_accel_error(ACCEL_LOG_FATAL, "\"opcache.preload_user\" has not been defined");
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "\"opcache.preload_user\" has not been defined");
return FAILURE;
}
pw = getpwnam(ZCG(accel_directives).preload_user);
if (pw == NULL) {
zend_shared_alloc_unlock();
- zend_accel_error(ACCEL_LOG_FATAL, "Preloading failed to getpwnam(\"%s\")", ZCG(accel_directives).preload_user);
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading failed to getpwnam(\"%s\")", ZCG(accel_directives).preload_user);
return FAILURE;
}
pid = fork();
if (pid == -1) {
zend_shared_alloc_unlock();
- zend_accel_error(ACCEL_LOG_FATAL, "Preloading failed to fork()");
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading failed to fork()");
return FAILURE;
} else if (pid == 0) { /* children */
if (setgid(pw->pw_gid) < 0) {
@@ -4847,7 +4847,7 @@ static int accel_finish_startup(void)
if (waitpid(pid, &status, 0) < 0) {
zend_shared_alloc_unlock();
- zend_accel_error(ACCEL_LOG_FATAL, "Preloading failed to waitpid(%d)", pid);
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading failed to waitpid(%d)", pid);
return FAILURE;
}
diff --git a/ext/opcache/zend_accelerator_blacklist.c b/ext/opcache/zend_accelerator_blacklist.c
index 9ae897b521..45ad0b2685 100644
--- a/ext/opcache/zend_accelerator_blacklist.c
+++ b/ext/opcache/zend_accelerator_blacklist.c
@@ -60,7 +60,7 @@ void zend_accel_blacklist_init(zend_blacklist *blacklist)
blacklist->entries = (zend_blacklist_entry *) calloc(sizeof(zend_blacklist_entry), blacklist->size);
if (!blacklist->entries) {
- zend_accel_error(ACCEL_LOG_FATAL, "Blacklist initialization: no memory\n");
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Blacklist initialization: no memory\n");
return;
}
blacklist->regexp_list = NULL;
@@ -68,7 +68,7 @@ void zend_accel_blacklist_init(zend_blacklist *blacklist)
static void blacklist_report_regexp_error(const char *pcre_error, int pcre_error_offset)
{
- zend_accel_error(ACCEL_LOG_ERROR, "Blacklist compilation failed (offset: %d), %s\n", pcre_error_offset, pcre_error);
+ zend_accel_error_noreturn(ACCEL_LOG_ERROR, "Blacklist compilation failed (offset: %d), %s\n", pcre_error_offset, pcre_error);
}
static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist)
@@ -163,7 +163,7 @@ static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist)
if (*c || i == blacklist->pos - 1) {
if (*c) {
if (!backtrack) {
- zend_accel_error(ACCEL_LOG_ERROR, "Too long blacklist entry\n");
+ zend_accel_error_noreturn(ACCEL_LOG_ERROR, "Too long blacklist entry\n");
}
p = backtrack;
} else {
@@ -173,7 +173,7 @@ static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist)
it = (zend_regexp_list*)malloc(sizeof(zend_regexp_list));
if (!it) {
- zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed\n");
+ zend_accel_error_noreturn(ACCEL_LOG_ERROR, "malloc() failed\n");
return;
}
it->next = NULL;
@@ -302,7 +302,7 @@ static void zend_accel_blacklist_loadone(zend_blacklist *blacklist, char *filena
blacklist->entries[blacklist->pos].path_length = path_length;
blacklist->entries[blacklist->pos].path = (char *)malloc(path_length + 1);
if (!blacklist->entries[blacklist->pos].path) {
- zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed\n");
+ zend_accel_error_noreturn(ACCEL_LOG_ERROR, "malloc() failed\n");
fclose(fp);
return;
}
diff --git a/ext/opcache/zend_accelerator_debug.c b/ext/opcache/zend_accelerator_debug.c
index f91c269975..a3db2a7215 100644
--- a/ext/opcache/zend_accelerator_debug.c
+++ b/ext/opcache/zend_accelerator_debug.c
@@ -28,9 +28,8 @@
#endif
#include "ZendAccelerator.h"
-void zend_accel_error(int type, const char *format, ...)
+static void zend_accel_error_va_args(int type, const char *format, va_list args)
{
- va_list args;
time_t timestamp;
char *time_string;
FILE * fLog = NULL;
@@ -77,9 +76,7 @@ void zend_accel_error(int type, const char *format, ...)
break;
}
- va_start(args, format);
vfprintf(fLog, format, args);
- va_end(args);
fprintf(fLog, "\n");
fflush(fLog);
@@ -98,3 +95,22 @@ void zend_accel_error(int type, const char *format, ...)
}
}
+
+void zend_accel_error(int type, const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ zend_accel_error_va_args(type, format, args);
+ va_end(args);
+}
+
+ZEND_NORETURN void zend_accel_error_noreturn(int type, const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ ZEND_ASSERT(type == ACCEL_LOG_FATAL || type == ACCEL_LOG_ERROR);
+ zend_accel_error_va_args(type, format, args);
+ va_end(args);
+ /* Should never reach this. */
+ abort();
+}
diff --git a/ext/opcache/zend_accelerator_debug.h b/ext/opcache/zend_accelerator_debug.h
index 234d0367de..61456096d1 100644
--- a/ext/opcache/zend_accelerator_debug.h
+++ b/ext/opcache/zend_accelerator_debug.h
@@ -29,5 +29,6 @@
#define ACCEL_LOG_DEBUG 4
void zend_accel_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
+ZEND_NORETURN void zend_accel_error_noreturn(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
#endif /* _ZEND_ACCELERATOR_DEBUG_H */
diff --git a/ext/opcache/zend_accelerator_hash.c b/ext/opcache/zend_accelerator_hash.c
index 7cd9ef1ef4..b0293ae8f2 100644
--- a/ext/opcache/zend_accelerator_hash.c
+++ b/ext/opcache/zend_accelerator_hash.c
@@ -54,14 +54,14 @@ void zend_accel_hash_init(zend_accel_hash *accel_hash, uint32_t hash_size)
/* set up hash pointers table */
accel_hash->hash_table = zend_shared_alloc(sizeof(zend_accel_hash_entry *)*accel_hash->max_num_entries);
if (!accel_hash->hash_table) {
- zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Insufficient shared memory!");
return;
}
/* set up hash values table */
accel_hash->hash_entries = zend_shared_alloc(sizeof(zend_accel_hash_entry)*accel_hash->max_num_entries);
if (!accel_hash->hash_entries) {
- zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Insufficient shared memory!");
return;
}
memset(accel_hash->hash_table, 0, sizeof(zend_accel_hash_entry *)*accel_hash->max_num_entries);
diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c
index d32a70b7e8..f4cb4f55af 100644
--- a/ext/opcache/zend_shared_alloc.c
+++ b/ext/opcache/zend_shared_alloc.c
@@ -86,7 +86,7 @@ void zend_shared_alloc_create_lock(char *lockfile_path)
fchmod(lock_file, 0666);
if (lock_file == -1) {
- zend_accel_error(ACCEL_LOG_FATAL, "Unable to create lock file: %s (%d)", strerror(errno), errno);
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Unable to create lock file: %s (%d)", strerror(errno), errno);
}
val = fcntl(lock_file, F_GETFD, 0);
val |= FD_CLOEXEC;
@@ -98,7 +98,7 @@ void zend_shared_alloc_create_lock(char *lockfile_path)
static void no_memory_bailout(size_t allocate_size, char *error)
{
- zend_accel_error(ACCEL_LOG_FATAL, "Unable to allocate shared memory segment of %zu bytes: %s: %s (%d)", allocate_size, error?error:"unknown", strerror(errno), errno );
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Unable to allocate shared memory segment of %zu bytes: %s: %s (%d)", allocate_size, error?error:"unknown", strerror(errno), errno );
}
static void copy_shared_segments(void *to, void *from, int count, int size)
@@ -231,14 +231,14 @@ int zend_shared_alloc_startup(size_t requested_size, size_t reserved_size)
p_tmp_shared_globals = (zend_smm_shared_globals *) zend_shared_alloc(sizeof(zend_smm_shared_globals));
if (!p_tmp_shared_globals) {
- zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Insufficient shared memory!");
return ALLOC_FAILURE;
}
memset(p_tmp_shared_globals, 0, sizeof(zend_smm_shared_globals));
tmp_shared_segments = zend_shared_alloc(shared_segments_array_size + ZSMMG(shared_segments_count) * sizeof(void *));
if (!tmp_shared_segments) {
- zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Insufficient shared memory!");
return ALLOC_FAILURE;
}
@@ -252,7 +252,7 @@ int zend_shared_alloc_startup(size_t requested_size, size_t reserved_size)
ZSMMG(shared_memory_state).positions = (int *)zend_shared_alloc(sizeof(int) * ZSMMG(shared_segments_count));
if (!ZSMMG(shared_memory_state).positions) {
- zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Insufficient shared memory!");
return ALLOC_FAILURE;
}
@@ -263,7 +263,7 @@ int zend_shared_alloc_startup(size_t requested_size, size_t reserved_size)
ZSMMG(reserved) = (char*)ZSMMG(shared_segments)[i]->p + ZSMMG(shared_segments)[i]->end;
ZSMMG(reserved_size) = reserved_size;
} else {
- zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
+ zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Insufficient shared memory!");
return ALLOC_FAILURE;
}
}
@@ -340,7 +340,7 @@ void *zend_shared_alloc(size_t size)
#if 1
if (!ZCG(locked)) {
- zend_accel_error(ACCEL_LOG_ERROR, "Shared memory lock not obtained");
+ zend_accel_error_noreturn(ACCEL_LOG_ERROR, "Shared memory lock not obtained");
}
#endif
if (block_size > ZSMMG(shared_free)) { /* No hope to find a big-enough block */
@@ -482,7 +482,7 @@ void zend_shared_alloc_lock(void)
if (errno == EINTR) {
continue;
}
- zend_accel_error(ACCEL_LOG_ERROR, "Cannot create lock - %s (%d)", strerror(errno), errno);
+ zend_accel_error_noreturn(ACCEL_LOG_ERROR, "Cannot create lock - %s (%d)", strerror(errno), errno);
}
break;
}
@@ -508,7 +508,7 @@ void zend_shared_alloc_unlock(void)
#ifndef ZEND_WIN32
if (fcntl(lock_file, F_SETLK, &mem_write_unlock) == -1) {
- zend_accel_error(ACCEL_LOG_ERROR, "Cannot remove lock - %s (%d)", strerror(errno), errno);
+ zend_accel_error_noreturn(ACCEL_LOG_ERROR, "Cannot remove lock - %s (%d)", strerror(errno), errno);
}
#ifdef ZTS
tsrm_mutex_unlock(zts_lock);
@@ -631,7 +631,7 @@ void zend_accel_shared_protect(int mode)
for (i = 0; i < ZSMMG(shared_segments_count); i++) {
DWORD oldProtect;
if (!VirtualProtect(ZSMMG(shared_segments)[i]->p, ZSMMG(shared_segments)[i]->end, mode, &oldProtect)) {
- zend_accel_error(ACCEL_LOG_ERROR, "Failed to protect memory");
+ zend_accel_error_noreturn(ACCEL_LOG_ERROR, "Failed to protect memory");
}
}
#endif
diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c
index 8917b9b0dc..00d20778e9 100644
--- a/ext/pdo/pdo_dbh.c
+++ b/ext/pdo/pdo_dbh.c
@@ -1293,8 +1293,12 @@ static int dbh_compare(zval *object1, zval *object2)
static HashTable *dbh_get_gc(zend_object *object, zval **gc_data, int *gc_count)
{
pdo_dbh_t *dbh = php_pdo_dbh_fetch_inner(object);
- *gc_data = &dbh->def_stmt_ctor_args;
- *gc_count = 1;
+ zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create();
+ zend_get_gc_buffer_add_zval(gc_buffer, &dbh->def_stmt_ctor_args);
+ if (dbh->methods && dbh->methods->get_gc) {
+ dbh->methods->get_gc(dbh, gc_buffer);
+ }
+ zend_get_gc_buffer_use(gc_buffer, gc_data, gc_count);
return zend_std_get_properties(object);
}
diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h
index 960ddec4ef..974eb0bad0 100644
--- a/ext/pdo/php_pdo_driver.h
+++ b/ext/pdo/php_pdo_driver.h
@@ -286,6 +286,10 @@ typedef int (*pdo_dbh_check_liveness_func)(pdo_dbh_t *dbh);
* scope */
typedef void (*pdo_dbh_request_shutdown)(pdo_dbh_t *dbh);
+/* Called when the PDO handle is scanned for GC. Should populate the get_gc buffer
+ * with any zvals in the driver_data that would be freed if the handle is destroyed. */
+typedef void (*pdo_dbh_get_gc_func)(pdo_dbh_t *dbh, zend_get_gc_buffer *buffer);
+
/* for adding methods to the dbh or stmt objects
pointer to a list of driver specific functions. The convention is
to prefix the function names using the PDO driver name; this will
@@ -316,6 +320,7 @@ struct pdo_dbh_methods {
pdo_dbh_get_driver_methods_func get_driver_methods;
pdo_dbh_request_shutdown persistent_shutdown;
pdo_dbh_txn_func in_transaction;
+ pdo_dbh_get_gc_func get_gc;
};
/* }}} */
diff --git a/ext/pdo_dblib/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c
index 7f160a402f..e581642037 100644
--- a/ext/pdo_dblib/dblib_driver.c
+++ b/ext/pdo_dblib/dblib_driver.c
@@ -417,7 +417,8 @@ static const struct pdo_dbh_methods dblib_methods = {
NULL, /* check liveness */
NULL, /* get driver methods */
NULL, /* request shutdown */
- NULL /* in transaction */
+ NULL, /* in transaction */
+ NULL /* get gc */
};
static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c
index c27a9e2ed5..c299907f0f 100644
--- a/ext/pdo_firebird/firebird_driver.c
+++ b/ext/pdo_firebird/firebird_driver.c
@@ -1005,7 +1005,11 @@ static const struct pdo_dbh_methods firebird_methods = { /* {{{ */
NULL, /* last_id not supported */
pdo_firebird_fetch_error_func,
firebird_handle_get_attribute,
- NULL /* check_liveness */
+ NULL, /* check_liveness */
+ NULL, /* get driver methods */
+ NULL, /* request shutdown */
+ NULL, /* in transaction */
+ NULL /* get gc */
};
/* }}} */
diff --git a/ext/pdo_mysql/mysql_driver.c b/ext/pdo_mysql/mysql_driver.c
index 641a9add1a..a83b12b872 100644
--- a/ext/pdo_mysql/mysql_driver.c
+++ b/ext/pdo_mysql/mysql_driver.c
@@ -577,7 +577,8 @@ static const struct pdo_dbh_methods mysql_methods = {
pdo_mysql_check_liveness,
NULL,
pdo_mysql_request_shutdown,
- pdo_mysql_in_transaction
+ pdo_mysql_in_transaction,
+ NULL /* get_gc */
};
/* }}} */
diff --git a/ext/pdo_oci/oci_driver.c b/ext/pdo_oci/oci_driver.c
index 096a26575e..2c65fc973b 100644
--- a/ext/pdo_oci/oci_driver.c
+++ b/ext/pdo_oci/oci_driver.c
@@ -705,9 +705,10 @@ static const struct pdo_dbh_methods oci_methods = {
pdo_oci_fetch_error_func,
oci_handle_get_attribute,
pdo_oci_check_liveness, /* check_liveness */
- NULL, /* get_driver_methods */
- NULL,
- NULL
+ NULL, /* get_driver_methods */
+ NULL, /* request_shutdown */
+ NULL, /* in_transaction */
+ NULL /* get_gc */
};
static int pdo_oci_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
diff --git a/ext/pdo_odbc/odbc_driver.c b/ext/pdo_odbc/odbc_driver.c
index 9a254553d5..81e4915da5 100644
--- a/ext/pdo_odbc/odbc_driver.c
+++ b/ext/pdo_odbc/odbc_driver.c
@@ -384,7 +384,11 @@ static const struct pdo_dbh_methods odbc_methods = {
NULL, /* last id */
pdo_odbc_fetch_error_func,
odbc_handle_get_attr, /* get attr */
- NULL, /* check_liveness */
+ NULL, /* check_liveness */
+ NULL, /* get_driver_methods */
+ NULL, /* request_shutdown */
+ NULL, /* in_transaction */
+ NULL /* get_gc */
};
static int pdo_odbc_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c
index d800d65a2d..37680b8efa 100644
--- a/ext/pdo_pgsql/pgsql_driver.c
+++ b/ext/pdo_pgsql/pgsql_driver.c
@@ -1179,6 +1179,7 @@ static const struct pdo_dbh_methods pgsql_methods = {
pdo_pgsql_get_driver_methods, /* get_driver_methods */
NULL,
pgsql_handle_in_transaction,
+ NULL /* get_gc */
};
static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c
index 26fa1c00eb..a8a96c7a13 100644
--- a/ext/pdo_sqlite/sqlite_driver.c
+++ b/ext/pdo_sqlite/sqlite_driver.c
@@ -695,6 +695,25 @@ static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh)
}
}
+static void pdo_sqlite_get_gc(pdo_dbh_t *dbh, zend_get_gc_buffer *gc_buffer)
+{
+ pdo_sqlite_db_handle *H = dbh->driver_data;
+
+ struct pdo_sqlite_func *func = H->funcs;
+ while (func) {
+ zend_get_gc_buffer_add_zval(gc_buffer, &func->func);
+ zend_get_gc_buffer_add_zval(gc_buffer, &func->step);
+ zend_get_gc_buffer_add_zval(gc_buffer, &func->fini);
+ func = func->next;
+ }
+
+ struct pdo_sqlite_collation *collation = H->collations;
+ while (collation) {
+ zend_get_gc_buffer_add_zval(gc_buffer, &collation->callback);
+ collation = collation->next;
+ }
+}
+
static const struct pdo_dbh_methods sqlite_methods = {
sqlite_handle_closer,
sqlite_handle_preparer,
@@ -710,7 +729,8 @@ static const struct pdo_dbh_methods sqlite_methods = {
NULL, /* check_liveness: not needed */
get_driver_methods,
pdo_sqlite_request_shutdown,
- NULL
+ NULL, /* in_transaction */
+ pdo_sqlite_get_gc
};
static char *make_filename_safe(const char *filename)
diff --git a/ext/pdo_sqlite/tests/gc.phpt b/ext/pdo_sqlite/tests/gc.phpt
new file mode 100644
index 0000000000..25407697e6
--- /dev/null
+++ b/ext/pdo_sqlite/tests/gc.phpt
@@ -0,0 +1,24 @@
+--TEST--
+GC support for PDO Sqlite driver data
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_sqlite')) print 'skip not loaded';
+?>
+--FILE--
+<?php
+
+class Obj {
+ public $a;
+ public function callback() { }
+}
+
+$obj = new Obj;
+$obj->a = new PDO('sqlite::memory:');
+$obj->a->sqliteCreateFunction('func1', function() use ($obj) {}, 1);
+$obj->a->sqliteCreateAggregate('func2', function() use ($obj) {}, function() use($obj) {});
+$obj->a->sqliteCreateCollation('col', function() use ($obj) {});
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff --git a/ext/pspell/pspell.c b/ext/pspell/pspell.c
index 63732b77b0..4253f5f159 100644
--- a/ext/pspell/pspell.c
+++ b/ext/pspell/pspell.c
@@ -19,6 +19,7 @@
#endif
#include "php.h"
+#include "zend_interfaces.h"
#include <stdlib.h>
#include <ctype.h>
@@ -48,58 +49,139 @@
static PHP_MINIT_FUNCTION(pspell);
static PHP_MINFO_FUNCTION(pspell);
-static int le_pspell, le_pspell_config;
+static zend_class_entry *php_pspell_ce = NULL;
+static zend_object_handlers php_pspell_handlers;
+static zend_class_entry *php_pspell_config_ce = NULL;
+static zend_object_handlers php_pspell_config_handlers;
zend_module_entry pspell_module_entry = {
STANDARD_MODULE_HEADER,
- "pspell", ext_functions, PHP_MINIT(pspell), NULL, NULL, NULL, PHP_MINFO(pspell), PHP_PSPELL_VERSION, STANDARD_MODULE_PROPERTIES
+ "pspell",
+ ext_functions,
+ PHP_MINIT(pspell),
+ NULL,
+ NULL,
+ NULL,
+ PHP_MINFO(pspell),
+ PHP_PSPELL_VERSION,
+ STANDARD_MODULE_PROPERTIES,
};
#ifdef COMPILE_DL_PSPELL
ZEND_GET_MODULE(pspell)
#endif
-static void php_pspell_close(zend_resource *rsrc)
+/* class PSpell */
+
+typedef struct _php_pspell_object {
+ PspellManager *mgr;
+ zend_object std;
+} php_pspell_object;
+
+static php_pspell_object *php_pspell_object_from_zend_object(zend_object *zobj) {
+ return ((php_pspell_object*)(zobj + 1)) - 1;
+}
+
+static zend_object *php_pspell_object_to_zend_object(php_pspell_object *obj) {
+ return ((zend_object*)(obj + 1)) - 1;
+}
+
+static zend_function *php_pspell_object_get_constructor(zend_object *object)
{
- PspellManager *manager = (PspellManager *)rsrc->ptr;
+ zend_throw_error(NULL, "You cannot initialize a PSpell object except through helper functions");
+ return NULL;
+}
+
+static zend_object *php_pspell_object_create(zend_class_entry *ce)
+{
+ php_pspell_object *obj = zend_object_alloc(sizeof(php_pspell_object), ce);
+ zend_object *zobj = php_pspell_object_to_zend_object(obj);
+
+ obj->mgr = NULL;
+ zend_object_std_init(zobj, ce);
+ object_properties_init(zobj, ce);
+ zobj->handlers = &php_pspell_handlers;
+
+ return zobj;
+}
+
+static void php_pspell_object_free(zend_object *zobj) {
+ delete_pspell_manager(php_pspell_object_from_zend_object(zobj)->mgr);
+}
- delete_pspell_manager(manager);
+/* class PSpellConfig */
+
+typedef struct _php_pspell_config_object {
+ PspellConfig *cfg;
+ zend_object std;
+} php_pspell_config_object;
+
+static php_pspell_config_object *php_pspell_config_object_from_zend_object(zend_object *zobj) {
+ return ((php_pspell_config_object*)(zobj + 1)) - 1;
}
-static void php_pspell_close_config(zend_resource *rsrc)
+static zend_object *php_pspell_config_object_to_zend_object(php_pspell_config_object *obj) {
+ return ((zend_object*)(obj + 1)) - 1;
+}
+
+static zend_function *php_pspell_config_object_get_constructor(zend_object *object)
{
- PspellConfig *config = (PspellConfig *)rsrc->ptr;
+ zend_throw_error(NULL, "You cannot initialize a PSpellConfig object except through helper functions");
+ return NULL;
+}
- delete_pspell_config(config);
+static zend_object *php_pspell_config_object_create(zend_class_entry *ce)
+{
+ php_pspell_config_object *obj = zend_object_alloc(sizeof(php_pspell_config_object), ce);
+ zend_object *zobj = php_pspell_config_object_to_zend_object(obj);
+
+ obj->cfg = NULL;
+ zend_object_std_init(zobj, ce);
+ object_properties_init(zobj, ce);
+ zobj->handlers = &php_pspell_config_handlers;
+
+ return zobj;
}
-#define PSPELL_FETCH_CONFIG do { \
- zval *res = zend_hash_index_find(&EG(regular_list), conf); \
- if (res == NULL || Z_RES_P(res)->type != le_pspell_config) { \
- zend_throw_error(NULL, "%s(): " ZEND_LONG_FMT " is not a PSPELL config index", get_active_function_name(), conf); \
- RETURN_THROWS(); \
- } \
- config = (PspellConfig *)Z_RES_P(res)->ptr; \
-} while (0)
-
-#define PSPELL_FETCH_MANAGER do { \
- zval *res = zend_hash_index_find(&EG(regular_list), scin); \
- if (res == NULL || Z_RES_P(res)->type != le_pspell) { \
- zend_throw_error(NULL, "%s(): " ZEND_LONG_FMT " is not a PSPELL result index", get_active_function_name(), scin); \
- RETURN_THROWS(); \
- } \
- manager = (PspellManager *)Z_RES_P(res)->ptr; \
-} while (0);
+static void php_pspell_config_object_free(zend_object *zobj) {
+ delete_pspell_config(php_pspell_config_object_from_zend_object(zobj)->cfg);
+}
/* {{{ PHP_MINIT_FUNCTION */
static PHP_MINIT_FUNCTION(pspell)
{
+ zend_class_entry ce;
+ INIT_CLASS_ENTRY(ce, "PSpell", class_PSpell_methods);
+ php_pspell_ce = zend_register_internal_class(&ce);
+ php_pspell_ce->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NO_DYNAMIC_PROPERTIES;
+ php_pspell_ce->create_object = php_pspell_object_create;
+ php_pspell_ce->serialize = zend_class_serialize_deny;
+ php_pspell_ce->unserialize = zend_class_unserialize_deny;
+
+ memcpy(&php_pspell_handlers, &std_object_handlers, sizeof(zend_object_handlers));
+ php_pspell_handlers.clone_obj = NULL;
+ php_pspell_handlers.free_obj = php_pspell_object_free;
+ php_pspell_handlers.get_constructor = php_pspell_object_get_constructor;
+ php_pspell_handlers.offset = XtOffsetOf(php_pspell_object, std);
+
+ INIT_CLASS_ENTRY(ce, "PSpellConfig", class_PSpellConfig_methods);
+ php_pspell_config_ce = zend_register_internal_class(&ce);
+ php_pspell_config_ce->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NO_DYNAMIC_PROPERTIES;
+ php_pspell_config_ce->create_object = php_pspell_config_object_create;
+ php_pspell_config_ce->serialize = zend_class_serialize_deny;
+ php_pspell_config_ce->unserialize = zend_class_unserialize_deny;
+
+ memcpy(&php_pspell_config_handlers, &std_object_handlers, sizeof(zend_object_handlers));
+ php_pspell_config_handlers.clone_obj = NULL;
+ php_pspell_config_handlers.free_obj = php_pspell_config_object_free;
+ php_pspell_config_handlers.get_constructor = php_pspell_config_object_get_constructor;
+ php_pspell_config_handlers.offset = XtOffsetOf(php_pspell_config_object, std);
+
REGISTER_LONG_CONSTANT("PSPELL_FAST", PSPELL_FAST, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("PSPELL_NORMAL", PSPELL_NORMAL, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("PSPELL_BAD_SPELLERS", PSPELL_BAD_SPELLERS, CONST_PERSISTENT | CONST_CS);
REGISTER_LONG_CONSTANT("PSPELL_RUN_TOGETHER", PSPELL_RUN_TOGETHER, CONST_PERSISTENT | CONST_CS);
- le_pspell = zend_register_list_destructors_ex(php_pspell_close, NULL, "pspell", module_number);
- le_pspell_config = zend_register_list_destructors_ex(php_pspell_close_config, NULL, "pspell config", module_number);
+
return SUCCESS;
}
/* }}} */
@@ -111,7 +193,6 @@ PHP_FUNCTION(pspell_new)
size_t language_len, spelling_len = 0, jargon_len = 0, encoding_len = 0;
zend_long mode = Z_L(0), speed = Z_L(0);
int argc = ZEND_NUM_ARGS();
- zval *ind;
#ifdef PHP_WIN32
TCHAR aspell_dir[200];
@@ -122,7 +203,6 @@ PHP_FUNCTION(pspell_new)
#endif
PspellCanHaveError *ret;
- PspellManager *manager;
PspellConfig *config;
if (zend_parse_parameters(argc, "s|sssl", &language, &language_len, &spelling, &spelling_len,
@@ -194,9 +274,8 @@ PHP_FUNCTION(pspell_new)
RETURN_FALSE;
}
- manager = to_pspell_manager(ret);
- ind = zend_list_insert(manager, le_pspell);
- RETURN_LONG(Z_RES_HANDLE_P(ind));
+ object_init_ex(return_value, php_pspell_ce);
+ php_pspell_object_from_zend_object(Z_OBJ_P(return_value))->mgr = to_pspell_manager(ret);
}
/* }}} */
@@ -207,7 +286,6 @@ PHP_FUNCTION(pspell_new_personal)
size_t personal_len, language_len, spelling_len = 0, jargon_len = 0, encoding_len = 0;
zend_long mode = Z_L(0), speed = Z_L(0);
int argc = ZEND_NUM_ARGS();
- zval *ind;
#ifdef PHP_WIN32
TCHAR aspell_dir[200];
@@ -218,7 +296,6 @@ PHP_FUNCTION(pspell_new_personal)
#endif
PspellCanHaveError *ret;
- PspellManager *manager;
PspellConfig *config;
if (zend_parse_parameters(argc, "ps|sssl", &personal, &personal_len, &language, &language_len,
@@ -298,26 +375,22 @@ PHP_FUNCTION(pspell_new_personal)
RETURN_FALSE;
}
- manager = to_pspell_manager(ret);
- ind = zend_list_insert(manager, le_pspell);
- RETURN_LONG(Z_RES_HANDLE_P(ind));
+ object_init_ex(return_value, php_pspell_ce);
+ php_pspell_object_from_zend_object(Z_OBJ_P(return_value))->mgr = to_pspell_manager(ret);
}
/* }}} */
/* {{{ Load a dictionary based on the given config */
PHP_FUNCTION(pspell_new_config)
{
- zend_long conf;
- zval *ind;
+ zval *zcfg;
PspellCanHaveError *ret;
- PspellManager *manager;
PspellConfig *config;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &conf) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &zcfg, php_pspell_config_ce) == FAILURE) {
RETURN_THROWS();
}
-
- PSPELL_FETCH_CONFIG;
+ config = php_pspell_config_object_from_zend_object(Z_OBJ_P(zcfg))->cfg;
ret = new_pspell_manager(config);
@@ -327,27 +400,24 @@ PHP_FUNCTION(pspell_new_config)
RETURN_FALSE;
}
- manager = to_pspell_manager(ret);
- ind = zend_list_insert(manager, le_pspell);
- RETURN_LONG(Z_RES_HANDLE_P(ind));
+ object_init_ex(return_value, php_pspell_ce);
+ php_pspell_object_from_zend_object(Z_OBJ_P(return_value))->mgr = to_pspell_manager(ret);
}
/* }}} */
/* {{{ Returns true if word is valid */
PHP_FUNCTION(pspell_check)
{
- size_t word_len;
- zend_long scin;
- char *word;
+ zval *zmgr;
+ zend_string *word;
PspellManager *manager;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ls", &scin, &word, &word_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &zmgr, php_pspell_ce, &word) == FAILURE) {
RETURN_THROWS();
}
+ manager = php_pspell_object_from_zend_object(Z_OBJ_P(zmgr))->mgr;
- PSPELL_FETCH_MANAGER;
-
- if (pspell_manager_check(manager, word)) {
+ if (pspell_manager_check(manager, ZSTR_VAL(word))) {
RETURN_TRUE;
} else {
RETURN_FALSE;
@@ -358,22 +428,20 @@ PHP_FUNCTION(pspell_check)
/* {{{ Returns array of suggestions */
PHP_FUNCTION(pspell_suggest)
{
- zend_long scin;
- char *word;
- size_t word_len;
+ zval *zmgr;
+ zend_string *word;
PspellManager *manager;
const PspellWordList *wl;
const char *sug;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ls", &scin, &word, &word_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &zmgr, php_pspell_ce, &word) == FAILURE) {
RETURN_THROWS();
}
-
- PSPELL_FETCH_MANAGER;
+ manager = php_pspell_object_from_zend_object(Z_OBJ_P(zmgr))->mgr;
array_init(return_value);
- wl = pspell_manager_suggest(manager, word);
+ wl = pspell_manager_suggest(manager, ZSTR_VAL(word));
if (wl) {
PspellStringEmulation *els = pspell_word_list_elements(wl);
while ((sug = pspell_string_emulation_next(els)) != 0) {
@@ -390,18 +458,16 @@ PHP_FUNCTION(pspell_suggest)
/* {{{ Notify the dictionary of a user-selected replacement */
PHP_FUNCTION(pspell_store_replacement)
{
- size_t miss_len, corr_len;
- zend_long scin;
- char *miss, *corr;
+ zval *zmgr;
+ zend_string *miss, *corr;
PspellManager *manager;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "lss", &scin, &miss, &miss_len, &corr, &corr_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS", &zmgr, php_pspell_ce, &miss, &corr) == FAILURE) {
RETURN_THROWS();
}
+ manager = php_pspell_object_from_zend_object(Z_OBJ_P(zmgr))->mgr;
- PSPELL_FETCH_MANAGER;
-
- pspell_manager_store_replacement(manager, miss, corr);
+ pspell_manager_store_replacement(manager, ZSTR_VAL(miss), ZSTR_VAL(corr));
if (pspell_manager_error_number(manager) == 0) {
RETURN_TRUE;
} else {
@@ -414,23 +480,21 @@ PHP_FUNCTION(pspell_store_replacement)
/* {{{ Adds a word to a personal list */
PHP_FUNCTION(pspell_add_to_personal)
{
- size_t word_len;
- zend_long scin;
- char *word;
+ zval *zmgr;
+ zend_string *word;
PspellManager *manager;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ls", &scin, &word, &word_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &zmgr, php_pspell_ce, &word) == FAILURE) {
RETURN_THROWS();
}
-
- PSPELL_FETCH_MANAGER;
+ manager = php_pspell_object_from_zend_object(Z_OBJ_P(zmgr))->mgr;
/*If the word is empty, we have to return; otherwise we'll segfault! ouch!*/
- if (word_len == 0) {
+ if (ZSTR_LEN(word) == 0) {
RETURN_FALSE;
}
- pspell_manager_add_to_personal(manager, word);
+ pspell_manager_add_to_personal(manager, ZSTR_VAL(word));
if (pspell_manager_error_number(manager) == 0) {
RETURN_TRUE;
} else {
@@ -443,23 +507,21 @@ PHP_FUNCTION(pspell_add_to_personal)
/* {{{ Adds a word to the current session */
PHP_FUNCTION(pspell_add_to_session)
{
- size_t word_len;
- zend_long scin;
- char *word;
+ zval *zmgr;
+ zend_string *word;
PspellManager *manager;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ls", &scin, &word, &word_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &zmgr, php_pspell_ce, &word) == FAILURE) {
RETURN_THROWS();
}
-
- PSPELL_FETCH_MANAGER;
+ manager = php_pspell_object_from_zend_object(Z_OBJ_P(zmgr))->mgr;
/*If the word is empty, we have to return; otherwise we'll segfault! ouch!*/
- if (word_len == 0) {
+ if (ZSTR_LEN(word) == 0) {
RETURN_FALSE;
}
- pspell_manager_add_to_session(manager, word);
+ pspell_manager_add_to_session(manager, ZSTR_VAL(word));
if (pspell_manager_error_number(manager) == 0) {
RETURN_TRUE;
} else {
@@ -472,14 +534,13 @@ PHP_FUNCTION(pspell_add_to_session)
/* {{{ Clears the current session */
PHP_FUNCTION(pspell_clear_session)
{
- zend_long scin;
+ zval *zmgr;
PspellManager *manager;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &scin) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &zmgr, php_pspell_ce) == FAILURE) {
RETURN_THROWS();
}
-
- PSPELL_FETCH_MANAGER;
+ manager = php_pspell_object_from_zend_object(Z_OBJ_P(zmgr))->mgr;
pspell_manager_clear_session(manager);
if (pspell_manager_error_number(manager) == 0) {
@@ -494,14 +555,13 @@ PHP_FUNCTION(pspell_clear_session)
/* {{{ Saves the current (personal) wordlist */
PHP_FUNCTION(pspell_save_wordlist)
{
- zend_long scin;
+ zval *zmgr;
PspellManager *manager;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &scin) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &zmgr, php_pspell_ce) == FAILURE) {
RETURN_THROWS();
}
-
- PSPELL_FETCH_MANAGER;
+ manager = php_pspell_object_from_zend_object(Z_OBJ_P(zmgr))->mgr;
pspell_manager_save_all_word_lists(manager);
@@ -520,7 +580,6 @@ PHP_FUNCTION(pspell_config_create)
{
char *language, *spelling = NULL, *jargon = NULL, *encoding = NULL;
size_t language_len, spelling_len = 0, jargon_len = 0, encoding_len = 0;
- zval *ind;
PspellConfig *config;
#ifdef PHP_WIN32
@@ -577,23 +636,22 @@ PHP_FUNCTION(pspell_config_create)
which is not what we want */
pspell_config_replace(config, "save-repl", "false");
- ind = zend_list_insert(config, le_pspell_config);
- RETURN_LONG(Z_RES_HANDLE_P(ind));
+ object_init_ex(return_value, php_pspell_config_ce);
+ php_pspell_config_object_from_zend_object(Z_OBJ_P(return_value))->cfg = config;
}
/* }}} */
/* {{{ Consider run-together words as valid components */
PHP_FUNCTION(pspell_config_runtogether)
{
- zend_long conf;
+ zval *zcfg;
zend_bool runtogether;
PspellConfig *config;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "lb", &conf, &runtogether) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ob", &zcfg, php_pspell_config_ce, &runtogether) == FAILURE) {
RETURN_THROWS();
}
-
- PSPELL_FETCH_CONFIG;
+ config = php_pspell_config_object_from_zend_object(Z_OBJ_P(zcfg))->cfg;
pspell_config_replace(config, "run-together", runtogether ? "true" : "false");
@@ -604,14 +662,14 @@ PHP_FUNCTION(pspell_config_runtogether)
/* {{{ Select mode for config (PSPELL_FAST, PSPELL_NORMAL or PSPELL_BAD_SPELLERS) */
PHP_FUNCTION(pspell_config_mode)
{
- zend_long conf, mode;
+ zval *zcfg;
+ zend_long mode;
PspellConfig *config;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll", &conf, &mode) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &zcfg, php_pspell_config_ce, &mode) == FAILURE) {
RETURN_THROWS();
}
-
- PSPELL_FETCH_CONFIG;
+ config = php_pspell_config_object_from_zend_object(Z_OBJ_P(zcfg))->cfg;
/* First check what mode we want (how many suggestions) */
if (mode == PSPELL_FAST) {
@@ -630,14 +688,14 @@ PHP_FUNCTION(pspell_config_mode)
PHP_FUNCTION(pspell_config_ignore)
{
char ignore_str[MAX_LENGTH_OF_LONG + 1];
- zend_long conf, ignore = 0L;
+ zval *zcfg;
+ zend_long ignore = 0L;
PspellConfig *config;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll", &conf, &ignore) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &zcfg, php_pspell_config_ce, &ignore) == FAILURE) {
RETURN_THROWS();
}
-
- PSPELL_FETCH_CONFIG;
+ config = php_pspell_config_object_from_zend_object(Z_OBJ_P(zcfg))->cfg;
snprintf(ignore_str, sizeof(ignore_str), ZEND_LONG_FMT, ignore);
@@ -648,22 +706,20 @@ PHP_FUNCTION(pspell_config_ignore)
static void pspell_config_path(INTERNAL_FUNCTION_PARAMETERS, char *option)
{
- zend_long conf;
- char *value;
- size_t value_len;
+ zval *zcfg;
+ zend_string *value;
PspellConfig *config;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "lp", &conf, &value, &value_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "OP", &zcfg, php_pspell_config_ce, &value) == FAILURE) {
RETURN_THROWS();
}
+ config = php_pspell_config_object_from_zend_object(Z_OBJ_P(zcfg))->cfg;
- PSPELL_FETCH_CONFIG;
-
- if (php_check_open_basedir(value)) {
+ if (php_check_open_basedir(ZSTR_VAL(value))) {
RETURN_FALSE;
}
- pspell_config_replace(config, option, value);
+ pspell_config_replace(config, option, ZSTR_VAL(value));
RETURN_TRUE;
}
@@ -692,24 +748,22 @@ PHP_FUNCTION(pspell_config_data_dir)
/* {{{ Use a personal dictionary with replacement pairs for this config */
PHP_FUNCTION(pspell_config_repl)
{
- zend_long conf;
- char *repl;
- size_t repl_len;
+ zval *zcfg;
+ zend_string *repl;
PspellConfig *config;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "lp", &conf, &repl, &repl_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "OP", &zcfg, php_pspell_config_ce, &repl) == FAILURE) {
RETURN_THROWS();
}
-
- PSPELL_FETCH_CONFIG;
+ config = php_pspell_config_object_from_zend_object(Z_OBJ_P(zcfg))->cfg;
pspell_config_replace(config, "save-repl", "true");
- if (php_check_open_basedir(repl)) {
+ if (php_check_open_basedir(ZSTR_VAL(repl))) {
RETURN_FALSE;
}
- pspell_config_replace(config, "repl", repl);
+ pspell_config_replace(config, "repl", ZSTR_VAL(repl));
RETURN_TRUE;
}
@@ -718,15 +772,14 @@ PHP_FUNCTION(pspell_config_repl)
/* {{{ Save replacement pairs when personal list is saved for this config */
PHP_FUNCTION(pspell_config_save_repl)
{
- zend_long conf;
+ zval *zcfg;
zend_bool save;
PspellConfig *config;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "lb", &conf, &save) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ob", &zcfg, php_pspell_config_ce, &save) == FAILURE) {
RETURN_THROWS();
}
-
- PSPELL_FETCH_CONFIG;
+ config = php_pspell_config_object_from_zend_object(Z_OBJ_P(zcfg))->cfg;
pspell_config_replace(config, "save-repl", save ? "true" : "false");
diff --git a/ext/pspell/pspell.stub.php b/ext/pspell/pspell.stub.php
index cf15fb35eb..a10de4b9f9 100644
--- a/ext/pspell/pspell.stub.php
+++ b/ext/pspell/pspell.stub.php
@@ -2,7 +2,10 @@
/** @generate-function-entries */
-function pspell_new(string $language, string $spelling = "", string $jargon = "", string $encoding = "", int $mode = 0): int|false {}
+final class PSpell {}
+final class PSpellConfig {}
+
+function pspell_new(string $language, string $spelling = "", string $jargon = "", string $encoding = "", int $mode = 0): PSpell|false {}
function pspell_new_personal(
string $filename,
@@ -11,38 +14,24 @@ function pspell_new_personal(
string $jargon = "",
string $encoding = "",
int $mode = 0
-): int|false {}
-
-function pspell_new_config(int $config): int|false {}
-
-function pspell_check(int $dictionary, string $word): bool {}
-
-function pspell_suggest(int $dictionary, string $word): array|false {}
-
-function pspell_store_replacement(int $dictionary, string $misspelled, string $correct): bool {}
-
-function pspell_add_to_personal(int $dictionary, string $word): bool {}
-
-function pspell_add_to_session(int $dictionary, string $word): bool {}
-
-function pspell_clear_session(int $dictionary): bool {}
-
-function pspell_save_wordlist(int $dictionary): bool {}
-
-function pspell_config_create(string $language, string $spelling = "", string $jargon = "", string $encoding = ""): int {}
-
-function pspell_config_runtogether(int $config, bool $allow): bool {}
-
-function pspell_config_mode(int $config, int $mode): bool {}
-
-function pspell_config_ignore(int $config, int $min_length): bool {}
-
-function pspell_config_personal(int $config, string $filename): bool {}
-
-function pspell_config_dict_dir(int $config, string $directory): bool {}
-
-function pspell_config_data_dir(int $config, string $directory): bool {}
-
-function pspell_config_repl(int $config, string $filename): bool {}
-
-function pspell_config_save_repl(int $config, bool $save): bool {}
+): PSpell|false {}
+
+function pspell_new_config(PSpellConfig $config): PSpell|false {}
+
+function pspell_check(PSpell $dictionary, string $word): bool {}
+function pspell_suggest(PSpell $dictionary, string $word): array|false {}
+function pspell_store_replacement(PSpell $dictionary, string $misspelled, string $correct): bool {}
+function pspell_add_to_personal(PSpell $dictionary, string $word): bool {}
+function pspell_add_to_session(PSpell $dictionary, string $word): bool {}
+function pspell_clear_session(PSpell $dictionary): bool {}
+function pspell_save_wordlist(PSpell $dictionary): bool {}
+
+function pspell_config_create(string $language, string $spelling = "", string $jargon = "", string $encoding = ""): PSpellConfig {}
+function pspell_config_runtogether(PSpellConfig $config, bool $allow): bool {}
+function pspell_config_mode(PSpellConfig $config, int $mode): bool {}
+function pspell_config_ignore(PSpellConfig $config, int $min_length): bool {}
+function pspell_config_personal(PSpellConfig $config, string $filename): bool {}
+function pspell_config_dict_dir(PSpellConfig $config, string $directory): bool {}
+function pspell_config_data_dir(PSpellConfig $config, string $directory): bool {}
+function pspell_config_repl(PSpellConfig $config, string $filename): bool {}
+function pspell_config_save_repl(PSpellConfig $config, bool $save): bool {}
diff --git a/ext/pspell/pspell_arginfo.h b/ext/pspell/pspell_arginfo.h
index 102907461c..f3b7b55310 100644
--- a/ext/pspell/pspell_arginfo.h
+++ b/ext/pspell/pspell_arginfo.h
@@ -1,7 +1,7 @@
/* This is a generated file, edit the .stub.php file instead.
- * Stub hash: 1d201126072be285aa2dd3c0136cb7cc261f5841 */
+ * Stub hash: efc4c20a1507cfba58ec265a2fe6f61b1e0f8a61 */
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_pspell_new, 0, 1, MAY_BE_LONG|MAY_BE_FALSE)
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_pspell_new, 0, 1, PSpell, MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, language, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, spelling, IS_STRING, 0, "\"\"")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, jargon, IS_STRING, 0, "\"\"")
@@ -9,7 +9,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_pspell_new, 0, 1, MAY_BE_LONG|MA
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "0")
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_pspell_new_personal, 0, 2, MAY_BE_LONG|MAY_BE_FALSE)
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_pspell_new_personal, 0, 2, PSpell, MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, language, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, spelling, IS_STRING, 0, "\"\"")
@@ -18,22 +18,22 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_pspell_new_personal, 0, 2, MAY_B
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mode, IS_LONG, 0, "0")
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_pspell_new_config, 0, 1, MAY_BE_LONG|MAY_BE_FALSE)
- ZEND_ARG_TYPE_INFO(0, config, IS_LONG, 0)
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_pspell_new_config, 0, 1, PSpell, MAY_BE_FALSE)
+ ZEND_ARG_OBJ_INFO(0, config, PSpellConfig, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pspell_check, 0, 2, _IS_BOOL, 0)
- ZEND_ARG_TYPE_INFO(0, dictionary, IS_LONG, 0)
+ ZEND_ARG_OBJ_INFO(0, dictionary, PSpell, 0)
ZEND_ARG_TYPE_INFO(0, word, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_pspell_suggest, 0, 2, MAY_BE_ARRAY|MAY_BE_FALSE)
- ZEND_ARG_TYPE_INFO(0, dictionary, IS_LONG, 0)
+ ZEND_ARG_OBJ_INFO(0, dictionary, PSpell, 0)
ZEND_ARG_TYPE_INFO(0, word, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pspell_store_replacement, 0, 3, _IS_BOOL, 0)
- ZEND_ARG_TYPE_INFO(0, dictionary, IS_LONG, 0)
+ ZEND_ARG_OBJ_INFO(0, dictionary, PSpell, 0)
ZEND_ARG_TYPE_INFO(0, misspelled, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, correct, IS_STRING, 0)
ZEND_END_ARG_INFO()
@@ -43,12 +43,12 @@ ZEND_END_ARG_INFO()
#define arginfo_pspell_add_to_session arginfo_pspell_check
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pspell_clear_session, 0, 1, _IS_BOOL, 0)
- ZEND_ARG_TYPE_INFO(0, dictionary, IS_LONG, 0)
+ ZEND_ARG_OBJ_INFO(0, dictionary, PSpell, 0)
ZEND_END_ARG_INFO()
#define arginfo_pspell_save_wordlist arginfo_pspell_clear_session
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pspell_config_create, 0, 1, IS_LONG, 0)
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_pspell_config_create, 0, 1, PSpellConfig, 0)
ZEND_ARG_TYPE_INFO(0, language, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, spelling, IS_STRING, 0, "\"\"")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, jargon, IS_STRING, 0, "\"\"")
@@ -56,27 +56,27 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pspell_config_create, 0, 1, IS_L
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pspell_config_runtogether, 0, 2, _IS_BOOL, 0)
- ZEND_ARG_TYPE_INFO(0, config, IS_LONG, 0)
+ ZEND_ARG_OBJ_INFO(0, config, PSpellConfig, 0)
ZEND_ARG_TYPE_INFO(0, allow, _IS_BOOL, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pspell_config_mode, 0, 2, _IS_BOOL, 0)
- ZEND_ARG_TYPE_INFO(0, config, IS_LONG, 0)
+ ZEND_ARG_OBJ_INFO(0, config, PSpellConfig, 0)
ZEND_ARG_TYPE_INFO(0, mode, IS_LONG, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pspell_config_ignore, 0, 2, _IS_BOOL, 0)
- ZEND_ARG_TYPE_INFO(0, config, IS_LONG, 0)
+ ZEND_ARG_OBJ_INFO(0, config, PSpellConfig, 0)
ZEND_ARG_TYPE_INFO(0, min_length, IS_LONG, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pspell_config_personal, 0, 2, _IS_BOOL, 0)
- ZEND_ARG_TYPE_INFO(0, config, IS_LONG, 0)
+ ZEND_ARG_OBJ_INFO(0, config, PSpellConfig, 0)
ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pspell_config_dict_dir, 0, 2, _IS_BOOL, 0)
- ZEND_ARG_TYPE_INFO(0, config, IS_LONG, 0)
+ ZEND_ARG_OBJ_INFO(0, config, PSpellConfig, 0)
ZEND_ARG_TYPE_INFO(0, directory, IS_STRING, 0)
ZEND_END_ARG_INFO()
@@ -85,7 +85,7 @@ ZEND_END_ARG_INFO()
#define arginfo_pspell_config_repl arginfo_pspell_config_personal
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pspell_config_save_repl, 0, 2, _IS_BOOL, 0)
- ZEND_ARG_TYPE_INFO(0, config, IS_LONG, 0)
+ ZEND_ARG_OBJ_INFO(0, config, PSpellConfig, 0)
ZEND_ARG_TYPE_INFO(0, save, _IS_BOOL, 0)
ZEND_END_ARG_INFO()
@@ -133,3 +133,13 @@ static const zend_function_entry ext_functions[] = {
ZEND_FE(pspell_config_save_repl, arginfo_pspell_config_save_repl)
ZEND_FE_END
};
+
+
+static const zend_function_entry class_PSpell_methods[] = {
+ ZEND_FE_END
+};
+
+
+static const zend_function_entry class_PSpellConfig_methods[] = {
+ ZEND_FE_END
+};
diff --git a/ext/pspell/tests/003.phpt b/ext/pspell/tests/003.phpt
index e8677ae826..63291a8d42 100644
--- a/ext/pspell/tests/003.phpt
+++ b/ext/pspell/tests/003.phpt
@@ -34,7 +34,7 @@ var_dump(pspell_config_ignore($cfg, PHP_INT_MAX));
bool(false)
Warning: pspell_new_config(): PSPELL couldn't open the dictionary. reason: The encoding "b0rked" is not known. This could also mean that the file "%sb0rked.%s" could not be opened for reading or does not exist. in %s003.php on line 9
-pspell_check(): 0 is not a PSPELL result index
+pspell_check(): Argument #1 ($dictionary) must be of type PSpell, bool given
---
bool(true)
bool(true)
diff --git a/ext/session/tests/003.phpt b/ext/session/tests/003.phpt
index e7e4294375..4f9b37b75d 100644
--- a/ext/session/tests/003.phpt
+++ b/ext/session/tests/003.phpt
@@ -17,7 +17,7 @@ class foo {
function method() { $this->yes++; }
}
-session_id("abtest");
+session_id("test003");
session_start();
session_decode('baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}}');
diff --git a/ext/session/tests/004.phpt b/ext/session/tests/004.phpt
index 4b81a088b2..c3ed0c5616 100644
--- a/ext/session/tests/004.phpt
+++ b/ext/session/tests/004.phpt
@@ -55,7 +55,7 @@ class foo {
session_set_save_handler(array($hnd, "open"), array($hnd, "close"), array($hnd, "read"), array($hnd, "write"), array($hnd, "destroy"), array($hnd, "gc"));
-session_id("abtest");
+session_id("test004");
session_start();
$_SESSION["baz"]->method();
$_SESSION["arr"][3]->method();
@@ -75,7 +75,7 @@ session_destroy();
?>
--EXPECT--
OPEN: PHPSESSID
-READ: abtest
+READ: test004
object(foo)#2 (2) {
["bar"]=>
string(2) "ok"
@@ -91,9 +91,9 @@ array(1) {
int(2)
}
}
-WRITE: abtest, baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:2;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:2;}}
+WRITE: test004, baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:2;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:2;}}
OPEN: PHPSESSID
-READ: abtest
+READ: test004
object(foo)#3 (2) {
["bar"]=>
string(2) "ok"
@@ -109,4 +109,4 @@ array(1) {
int(2)
}
}
-DESTROY: abtest
+DESTROY: test004
diff --git a/ext/session/tests/005.phpt b/ext/session/tests/005.phpt
index a7b42de7fa..2b51ceed94 100644
--- a/ext/session/tests/005.phpt
+++ b/ext/session/tests/005.phpt
@@ -56,7 +56,7 @@ class foo {
session_set_save_handler(array($hnd, "open"), array($hnd, "close"), array($hnd, "read"), array($hnd, "write"), array($hnd, "destroy"), array($hnd, "gc"));
-session_id("abtest");
+session_id("test005");
session_start();
session_decode($hnd->data);
@@ -91,7 +91,7 @@ session_destroy();
?>
--EXPECT--
OPEN: PHPSESSID
-READ: abtest
+READ: test005
object(foo)#4 (2) {
["bar"]=>
string(2) "ok"
@@ -107,10 +107,10 @@ array(1) {
int(2)
}
}
-WRITE: abtest, baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:2;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:2;}}
+WRITE: test005, baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:2;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:2;}}
CLOSE
OPEN: PHPSESSID
-READ: abtest
+READ: test005
object(foo)#2 (2) {
["bar"]=>
string(2) "ok"
@@ -127,10 +127,10 @@ array(1) {
}
}
int(123)
-WRITE: abtest, baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:3;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:3;}}c|i:123;
+WRITE: test005, baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:3;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:3;}}c|i:123;
CLOSE
OPEN: PHPSESSID
-READ: abtest
+READ: test005
object(foo)#4 (2) {
["bar"]=>
string(2) "ok"
@@ -147,5 +147,5 @@ array(1) {
}
}
int(123)
-DESTROY: abtest
+DESTROY: test005
CLOSE
diff --git a/ext/session/tests/006.phpt b/ext/session/tests/006.phpt
index 68cea7314a..e3c048748f 100644
--- a/ext/session/tests/006.phpt
+++ b/ext/session/tests/006.phpt
@@ -13,7 +13,7 @@ session.save_handler=files
error_reporting(E_ALL);
ob_start();
-session_id("abtest");
+session_id("test006");
session_start();
class a {
diff --git a/ext/session/tests/009.phpt b/ext/session/tests/009.phpt
index 10069c21d0..898cf76a5a 100644
--- a/ext/session/tests/009.phpt
+++ b/ext/session/tests/009.phpt
@@ -13,14 +13,14 @@ session.save_handler=files
error_reporting(E_ALL);
ob_start();
-session_id("abtest");
+session_id("test009");
### Phase 1 cleanup
session_start();
session_destroy();
### Phase 2 $_SESSION["c"] does not contain any value
-session_id("abtest");
+session_id("test009");
session_start();
var_dump($_SESSION);
$_SESSION["name"] = "foo";
diff --git a/ext/session/tests/012.phpt b/ext/session/tests/012.phpt
index c555d2ca1e..ad3f54962e 100644
--- a/ext/session/tests/012.phpt
+++ b/ext/session/tests/012.phpt
@@ -14,7 +14,7 @@ error_reporting(E_ALL);
### Absurd example, value of $_SESSION does not matter
-session_id("abtest");
+session_id("test012");
session_start();
$_SESSION["_SESSION"] = Array();
$_SESSION = "kk";
diff --git a/ext/session/tests/013.phpt b/ext/session/tests/013.phpt
index 32909eb58c..07fcea407b 100644
--- a/ext/session/tests/013.phpt
+++ b/ext/session/tests/013.phpt
@@ -12,10 +12,10 @@ session.save_handler=files
<?php
error_reporting(E_ALL);
-session_id("abtest");
+session_id("test013");
session_start();
session_destroy();
-session_id("abtest2");
+session_id("test013-2");
session_start();
session_destroy();
diff --git a/ext/session/tests/014.phpt b/ext/session/tests/014.phpt
index d8369cfec5..a0c6515243 100644
--- a/ext/session/tests/014.phpt
+++ b/ext/session/tests/014.phpt
@@ -14,7 +14,7 @@ session.save_handler=files
<?php
error_reporting(E_ALL);
-session_id("abtest");
+session_id("test014");
session_start();
?>
diff --git a/ext/session/tests/015.phpt b/ext/session/tests/015.phpt
index 527b86bc1d..788f1eac06 100644
--- a/ext/session/tests/015.phpt
+++ b/ext/session/tests/015.phpt
@@ -16,7 +16,7 @@ session.save_handler=files
<?php
error_reporting(E_ALL);
-session_id("abtest");
+session_id("test015");
session_start();
?>
<a href="/link?<?php echo SID; ?>">
@@ -24,4 +24,4 @@ session_start();
session_destroy();
?>
--EXPECT--
-<a href="/link?PHPSESSID=abtest&PHPSESSID=abtest">
+<a href="/link?PHPSESSID=test015&PHPSESSID=test015">
diff --git a/ext/session/tests/018.phpt b/ext/session/tests/018.phpt
index 5ec132b34f..d132abf717 100644
--- a/ext/session/tests/018.phpt
+++ b/ext/session/tests/018.phpt
@@ -16,7 +16,7 @@ session.save_handler=files
error_reporting(E_ALL);
-session_id("abtest");
+session_id("test018");
session_start();
?>
<form accept-charset="ISO-8859-15, ISO-8859-1" action=url.php>
@@ -24,4 +24,4 @@ session_start();
session_destroy();
?>
--EXPECT--
-<form accept-charset="ISO-8859-15, ISO-8859-1" action=url.php><input type="hidden" name="PHPSESSID" value="abtest" />
+<form accept-charset="ISO-8859-15, ISO-8859-1" action=url.php><input type="hidden" name="PHPSESSID" value="test018" />
diff --git a/ext/session/tests/019.phpt b/ext/session/tests/019.phpt
index d9a478245b..e3793a5522 100644
--- a/ext/session/tests/019.phpt
+++ b/ext/session/tests/019.phpt
@@ -23,7 +23,7 @@ class TFoo {
}
}
-session_id("abtest");
+session_id("test019");
session_start();
$_SESSION["o1"] = new TFoo(42);
diff --git a/ext/session/tests/020.phpt b/ext/session/tests/020.phpt
index 267e52191c..f4ec38c8fb 100644
--- a/ext/session/tests/020.phpt
+++ b/ext/session/tests/020.phpt
@@ -17,7 +17,7 @@ session.save_handler=files
error_reporting(E_ALL);
-session_id("abtest");
+session_id("test020");
session_start();
?>
<a href="link.php?a=b">
@@ -25,4 +25,4 @@ session_start();
session_destroy();
?>
--EXPECT--
-<a href="link.php?a=b&amp;PHPSESSID=abtest">
+<a href="link.php?a=b&amp;PHPSESSID=test020">
diff --git a/ext/session/tests/021.phpt b/ext/session/tests/021.phpt
index 4a97d7d32a..2532324fee 100644
--- a/ext/session/tests/021.phpt
+++ b/ext/session/tests/021.phpt
@@ -19,7 +19,7 @@ error_reporting(E_ALL);
ini_set('session.trans_sid_hosts', 'php.net');
$_SERVER['HTTP_HOST'] = 'php.net';
-session_id("abtest");
+session_id("test021");
session_start();
?>
<form action="//bad.net/do.php">
@@ -60,11 +60,11 @@ session_destroy();
--EXPECT--
<form action="//bad.net/do.php">
<fieldset>
-<form action="//php.net/do.php"><input type="hidden" name="PHPSESSID" value="abtest" />
+<form action="//php.net/do.php"><input type="hidden" name="PHPSESSID" value="test021" />
<fieldset>
-<form action="../do.php"><input type="hidden" name="PHPSESSID" value="abtest" />
+<form action="../do.php"><input type="hidden" name="PHPSESSID" value="test021" />
<fieldset>
-<form action="/do.php"><input type="hidden" name="PHPSESSID" value="abtest" />
+<form action="/do.php"><input type="hidden" name="PHPSESSID" value="test021" />
<fieldset>
-<form action="/foo/do.php"><input type="hidden" name="PHPSESSID" value="abtest" />
+<form action="/foo/do.php"><input type="hidden" name="PHPSESSID" value="test021" />
<fieldset>
diff --git a/ext/session/tests/023.phpt b/ext/session/tests/023.phpt
index 23c7096f23..e9ce084256 100644
--- a/ext/session/tests/023.phpt
+++ b/ext/session/tests/023.phpt
@@ -17,7 +17,7 @@ class foo {
function method() { $this->yes++; }
}
-session_id("abtest");
+session_id("test023");
session_start();
session_decode('baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}}');
$baz = $_SESSION['baz'];
diff --git a/ext/session/tests/024.phpt b/ext/session/tests/024.phpt
index 174f2e2639..913956f5b3 100644
--- a/ext/session/tests/024.phpt
+++ b/ext/session/tests/024.phpt
@@ -56,7 +56,7 @@ class foo {
session_set_save_handler(array($hnd, "open"), array($hnd, "close"), array($hnd, "read"), array($hnd, "write"), array($hnd, "destroy"), array($hnd, "gc"));
-session_id("abtest");
+session_id("test024");
session_start();
$baz = $_SESSION['baz'];
@@ -79,7 +79,7 @@ session_destroy();
?>
--EXPECTF--
OPEN: PHPSESSID
-READ: abtest
+READ: test024
object(foo)#%d (2) {
["bar"]=>
string(2) "ok"
@@ -95,9 +95,9 @@ array(1) {
int(2)
}
}
-WRITE: abtest, baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:2;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:2;}}
+WRITE: test024, baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:2;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:2;}}
OPEN: PHPSESSID
-READ: abtest
+READ: test024
object(foo)#%d (2) {
["bar"]=>
string(2) "ok"
@@ -113,4 +113,4 @@ array(1) {
int(2)
}
}
-DESTROY: abtest
+DESTROY: test024
diff --git a/ext/session/tests/025.phpt b/ext/session/tests/025.phpt
index 172ea579c6..4e91da9796 100644
--- a/ext/session/tests/025.phpt
+++ b/ext/session/tests/025.phpt
@@ -57,7 +57,7 @@ class foo {
session_set_save_handler(array($hnd, "open"), array($hnd, "close"), array($hnd, "read"), array($hnd, "write"), array($hnd, "destroy"), array($hnd, "gc"));
-session_id("abtest");
+session_id("test025");
session_start();
$baz = $_SESSION['baz'];
$arr = $_SESSION['arr'];
@@ -93,7 +93,7 @@ session_destroy();
?>
--EXPECTF--
OPEN: PHPSESSID
-READ: abtest
+READ: test025
object(foo)#%d (2) {
["bar"]=>
string(2) "ok"
@@ -109,10 +109,10 @@ array(1) {
int(2)
}
}
-WRITE: abtest, baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:2;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:2;}}
+WRITE: test025, baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:2;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:2;}}
CLOSE
OPEN: PHPSESSID
-READ: abtest
+READ: test025
object(foo)#%d (2) {
["bar"]=>
string(2) "ok"
@@ -129,10 +129,10 @@ array(1) {
}
}
int(123)
-WRITE: abtest, baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:3;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:3;}}c|i:123;
+WRITE: test025, baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:3;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:3;}}c|i:123;
CLOSE
OPEN: PHPSESSID
-READ: abtest
+READ: test025
object(foo)#%d (2) {
["bar"]=>
string(2) "ok"
@@ -149,5 +149,5 @@ array(1) {
}
}
int(123)
-DESTROY: abtest
+DESTROY: test025
CLOSE
diff --git a/ext/session/tests/026.phpt b/ext/session/tests/026.phpt
index b61039ee0c..f5abdac0a5 100644
--- a/ext/session/tests/026.phpt
+++ b/ext/session/tests/026.phpt
@@ -13,7 +13,7 @@ session.save_handler=files
error_reporting(E_ALL);
ob_start();
-session_id("abtest");
+session_id("test026");
session_start();
class a {
diff --git a/ext/session/tests/027.phpt b/ext/session/tests/027.phpt
index ebaf25467c..969bc5b872 100644
--- a/ext/session/tests/027.phpt
+++ b/ext/session/tests/027.phpt
@@ -13,14 +13,14 @@ session.save_handler=files
error_reporting(E_ALL);
ob_start();
-session_id("abtest");
+session_id("test027");
### Phase 1 cleanup
session_start();
session_destroy();
### Phase 2 $_SESSION["c"] does not contain any value
-session_id("abtest");
+session_id("test027");
session_start();
var_dump($_SESSION);
$_SESSION["name"] = "foo";
diff --git a/ext/session/tests/CONFLICTS b/ext/session/tests/CONFLICTS
deleted file mode 100644
index 30888ae480..0000000000
--- a/ext/session/tests/CONFLICTS
+++ /dev/null
@@ -1 +0,0 @@
-session
diff --git a/ext/session/tests/bug41600.phpt b/ext/session/tests/bug41600.phpt
index 79d5e12841..d4dfce9d88 100644
--- a/ext/session/tests/bug41600.phpt
+++ b/ext/session/tests/bug41600.phpt
@@ -17,7 +17,7 @@ session.save_handler=files
error_reporting(E_ALL);
-session_id("abtest");
+session_id("bug41600");
session_start();
?>
<a href="link.php?a=b">
@@ -25,4 +25,4 @@ session_start();
session_destroy();
?>
--EXPECT--
-<a href="link.php?a=b&amp;PHPSESSID=abtest">
+<a href="link.php?a=b&amp;PHPSESSID=bug41600">
diff --git a/ext/session/tests/bug42596.phpt b/ext/session/tests/bug42596.phpt
index f27e86387e..83567bde5f 100644
--- a/ext/session/tests/bug42596.phpt
+++ b/ext/session/tests/bug42596.phpt
@@ -15,7 +15,7 @@ session.serialize_handler=php
session.save_handler=files
--FILE--
<?php
-$sessdir = __DIR__.'/sessions/';
+$sessdir = __DIR__.'/bug42596/';
@rmdir($sessdir);
mkdir($sessdir);
$save_path = '0;0777;'.$sessdir;
diff --git a/ext/session/tests/rfc1867.phpt b/ext/session/tests/rfc1867.phpt
index 0e189b7aa6..a5ae8b2218 100644
--- a/ext/session/tests/rfc1867.phpt
+++ b/ext/session/tests/rfc1867.phpt
@@ -18,15 +18,15 @@ session.save_handler=files
--SKIPIF--
<?php include('skipif.inc'); ?>
--COOKIE--
-PHPSESSID=rfc1867-tests
+PHPSESSID=rfc1867
--GET--
-PHPSESSID=rfc1867-tests-get
+PHPSESSID=rfc1867-get
--POST_RAW--
Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHPSESSID"
-rfc1867-tests-post
+rfc1867-post
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
@@ -50,7 +50,7 @@ var_dump($_SESSION["upload_progress_" . basename(__FILE__)]);
session_destroy();
?>
--EXPECTF--
-string(%d) "rfc1867-tests"
+string(%d) "rfc1867"
bool(true)
array(2) {
["file1"]=>
diff --git a/ext/session/tests/rfc1867_cleanup.phpt b/ext/session/tests/rfc1867_cleanup.phpt
index ae5dcbe8dc..9baa6144ba 100644
--- a/ext/session/tests/rfc1867_cleanup.phpt
+++ b/ext/session/tests/rfc1867_cleanup.phpt
@@ -18,15 +18,15 @@ session.save_handler=files
--SKIPIF--
<?php include('skipif.inc'); ?>
--COOKIE--
-PHPSESSID=rfc1867-tests
+PHPSESSID=rfc1867-cleanup
--GET--
-PHPSESSID=rfc1867-tests-get
+PHPSESSID=rfc1867-cleanup-get
--POST_RAW--
Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHPSESSID"
-rfc1867-tests-post
+rfc1867-cleanup-post
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
@@ -50,7 +50,7 @@ var_dump(isset($_SESSION["upload_progress_" . basename(__FILE__)]));
session_destroy();
?>
--EXPECTF--
-string(%d) "rfc1867-tests"
+string(%d) "rfc1867-cleanup"
bool(true)
array(2) {
["file1"]=>
diff --git a/ext/session/tests/rfc1867_disabled.phpt b/ext/session/tests/rfc1867_disabled.phpt
index 5bedb1de88..8d8effd1f4 100644
--- a/ext/session/tests/rfc1867_disabled.phpt
+++ b/ext/session/tests/rfc1867_disabled.phpt
@@ -17,15 +17,15 @@ session.save_handler=files
--SKIPIF--
<?php include('skipif.inc'); ?>
--COOKIE--
-PHPSESSID=rfc1867-tests
+PHPSESSID=rfc1867-disabled
--GET--
-PHPSESSID=rfc1867-tests-get
+PHPSESSID=rfc1867-disabled-get
--POST_RAW--
Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHPSESSID"
-rfc1867-tests-post
+rfc1867-disabled-post
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="file1"; filename="file1.txt"
@@ -44,7 +44,7 @@ var_dump(isset($_SESSION["upload_progress_" . basename(__FILE__)]));
session_destroy();
?>
--EXPECTF--
-string(%d) "rfc1867-tests"
+string(%d) "rfc1867-disabled"
array(2) {
["file1"]=>
array(5) {
diff --git a/ext/session/tests/rfc1867_disabled_2.phpt b/ext/session/tests/rfc1867_disabled_2.phpt
index d63748369d..c539c6eaea 100644
--- a/ext/session/tests/rfc1867_disabled_2.phpt
+++ b/ext/session/tests/rfc1867_disabled_2.phpt
@@ -17,15 +17,15 @@ session.save_handler=files
--SKIPIF--
<?php include('skipif.inc'); ?>
--COOKIE--
-PHPSESSID=rfc1867-tests
+PHPSESSID=rfc1867-disabled-2
--GET--
-PHPSESSID=rfc1867-tests-get
+PHPSESSID=rfc1867-disabled-2-get
--POST_RAW--
Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHPSESSID"
-rfc1867-tests-post
+rfc1867-disabled-2-post
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="file1"; filename="file1.txt"
@@ -44,7 +44,7 @@ var_dump(isset($_SESSION["upload_progress_" . basename(__FILE__)]));
session_destroy();
?>
--EXPECTF--
-string(%d) "rfc1867-tests"
+string(%d) "rfc1867-disabled-2"
array(2) {
["file1"]=>
array(5) {
diff --git a/ext/session/tests/rfc1867_inter.phpt b/ext/session/tests/rfc1867_inter.phpt
index b961bbcac3..fd28dfe07a 100644
--- a/ext/session/tests/rfc1867_inter.phpt
+++ b/ext/session/tests/rfc1867_inter.phpt
@@ -18,15 +18,15 @@ session.save_handler=files
--SKIPIF--
<?php include('skipif.inc'); ?>
--COOKIE--
-PHPSESSID=rfc1867-tests
+PHPSESSID=rfc1867-inter
--GET--
-PHPSESSID=rfc1867-tests-get
+PHPSESSID=rfc1867-inter-get
--POST_RAW--
Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHPSESSID"
-rfc1867-tests-post
+rfc1867-inter-post
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
@@ -54,7 +54,7 @@ var_dump(isset($_SESSION["upload_progress_" . basename(__FILE__) . "_2"]));
session_destroy();
?>
--EXPECTF--
-string(%d) "rfc1867-tests"
+string(%d) "rfc1867-inter"
array(2) {
["file1"]=>
array(5) {
diff --git a/ext/session/tests/rfc1867_no_name.phpt b/ext/session/tests/rfc1867_no_name.phpt
index 98e8e7cf09..15877a664e 100644
--- a/ext/session/tests/rfc1867_no_name.phpt
+++ b/ext/session/tests/rfc1867_no_name.phpt
@@ -17,15 +17,15 @@ session.save_handler=files
--SKIPIF--
<?php include('skipif.inc'); ?>
--COOKIE--
-PHPSESSID=rfc1867-tests
+PHPSESSID=rfc1867-no-name
--GET--
-PHPSESSID=rfc1867-tests-get
+PHPSESSID=rfc1867-no-name-get
--POST_RAW--
Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHPSESSID"
-rfc1867-tests-post
+rfc1867-no-name-post
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="file1"; filename="file1.txt"
@@ -44,7 +44,7 @@ var_dump(isset($_SESSION["upload_progress_" . basename(__FILE__)]));
session_destroy();
?>
--EXPECTF--
-string(%d) "rfc1867-tests"
+string(%d) "rfc1867-no-name"
array(2) {
["file1"]=>
array(5) {
diff --git a/ext/session/tests/rfc1867_sid_cookie.phpt b/ext/session/tests/rfc1867_sid_cookie.phpt
index 804a9ba308..85c28934f4 100644
--- a/ext/session/tests/rfc1867_sid_cookie.phpt
+++ b/ext/session/tests/rfc1867_sid_cookie.phpt
@@ -17,15 +17,15 @@ session.save_handler=files
--SKIPIF--
<?php include('skipif.inc'); ?>
--COOKIE--
-PHPSESSID=rfc1867-tests
+PHPSESSID=rfc1867-sid-cookie
--GET--
-PHPSESSID=rfc1867-tests-get
+PHPSESSID=rfc1867-sid-cookie-get
--POST_RAW--
Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHPSESSID"
-rfc1867-tests-post
+rfc1867-sid-cookie-post
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
@@ -49,7 +49,7 @@ var_dump($_SESSION["upload_progress_" . basename(__FILE__)]);
session_destroy();
?>
--EXPECTF--
-string(%d) "rfc1867-tests"
+string(%d) "rfc1867-sid-cookie"
bool(true)
array(2) {
["file1"]=>
diff --git a/ext/session/tests/rfc1867_sid_get.phpt b/ext/session/tests/rfc1867_sid_get.phpt
index 17d1ebce0f..dfb192cb47 100644
--- a/ext/session/tests/rfc1867_sid_get.phpt
+++ b/ext/session/tests/rfc1867_sid_get.phpt
@@ -17,13 +17,13 @@ session.save_handler=files
--SKIPIF--
<?php include('skipif.inc'); ?>
--GET--
-PHPSESSID=rfc1867-tests
+PHPSESSID=rfc1867-sid-get
--POST_RAW--
Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHPSESSID"
-rfc1867-tests-post
+rfc1867-sid-get-post
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
@@ -47,7 +47,7 @@ var_dump($_SESSION["upload_progress_" . basename(__FILE__)]);
session_destroy();
?>
--EXPECTF--
-string(%d) "rfc1867-tests"
+string(%d) "rfc1867-sid-get"
bool(true)
array(2) {
["file1"]=>
diff --git a/ext/session/tests/rfc1867_sid_get_2.phpt b/ext/session/tests/rfc1867_sid_get_2.phpt
index 4b32c6e352..33e4489cc8 100644
--- a/ext/session/tests/rfc1867_sid_get_2.phpt
+++ b/ext/session/tests/rfc1867_sid_get_2.phpt
@@ -17,15 +17,15 @@ session.save_handler=files
--SKIPIF--
<?php include('skipif.inc'); ?>
--COOKIE--
-PHPSESSID=rfc1867-tests-cookie
+PHPSESSID=rfc1867-sid-get-2-cookie
--GET--
-PHPSESSID=rfc1867-tests
+PHPSESSID=rfc1867-sid-get-2
--POST_RAW--
Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHPSESSID"
-rfc1867-tests-post
+rfc1867-sid-get-2-post
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
@@ -49,7 +49,7 @@ var_dump($_SESSION["upload_progress_" . basename(__FILE__)]);
session_destroy();
?>
--EXPECTF--
-string(%d) "rfc1867-tests"
+string(%d) "rfc1867-sid-get-2"
bool(true)
array(2) {
["file1"]=>
diff --git a/ext/session/tests/rfc1867_sid_only_cookie.phpt b/ext/session/tests/rfc1867_sid_only_cookie.phpt
index 0c376bb026..54897b91c8 100644
--- a/ext/session/tests/rfc1867_sid_only_cookie.phpt
+++ b/ext/session/tests/rfc1867_sid_only_cookie.phpt
@@ -17,15 +17,15 @@ session.save_handler=files
--SKIPIF--
<?php include('skipif.inc'); ?>
--COOKIE--
-PHPSESSID=rfc1867-tests
+PHPSESSID=rfc1867-sid-only-cookie
--GET--
-PHPSESSID=rfc1867-tests-get
+PHPSESSID=rfc1867-sid-only-cookie-get
--POST_RAW--
Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHPSESSID"
-rfc1867-tests-post
+rfc1867-sid-only-cookie-post
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
@@ -49,7 +49,7 @@ var_dump($_SESSION["upload_progress_" . basename(__FILE__)]);
session_destroy();
?>
--EXPECTF--
-string(%d) "rfc1867-tests"
+string(%d) "rfc1867-sid-only-cookie"
bool(true)
array(2) {
["file1"]=>
diff --git a/ext/session/tests/rfc1867_sid_only_cookie_2.phpt b/ext/session/tests/rfc1867_sid_only_cookie_2.phpt
index 9b0aae9429..3fd46148d7 100644
--- a/ext/session/tests/rfc1867_sid_only_cookie_2.phpt
+++ b/ext/session/tests/rfc1867_sid_only_cookie_2.phpt
@@ -16,13 +16,13 @@ session.save_handler=files
--SKIPIF--
<?php include('skipif.inc'); ?>
--GET--
-PHPSESSID=rfc1867-tests-get
+PHPSESSID=rfc1867-sid-only-cookie-2-get
--POST_RAW--
Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHPSESSID"
-rfc1867-tests-post
+rfc1867-sid-only-cookie-2-post
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
diff --git a/ext/session/tests/rfc1867_sid_post.phpt b/ext/session/tests/rfc1867_sid_post.phpt
index a126f9ba38..f22f153403 100644
--- a/ext/session/tests/rfc1867_sid_post.phpt
+++ b/ext/session/tests/rfc1867_sid_post.phpt
@@ -21,7 +21,7 @@ Content-Type: multipart/form-data; boundary=---------------------------208960602
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHPSESSID"
-rfc1867-tests
+rfc1867-sid-post
-----------------------------20896060251896012921717172737
Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
@@ -45,7 +45,7 @@ var_dump($_SESSION["upload_progress_" . basename(__FILE__)]);
session_destroy();
?>
--EXPECTF--
-string(%d) "rfc1867-tests"
+string(%d) "rfc1867-sid-post"
bool(true)
array(2) {
["file1"]=>
diff --git a/ext/session/tests/session_basic1.phpt b/ext/session/tests/session_basic1.phpt
index ffdcf6c5ec..13c21d3e85 100644
--- a/ext/session/tests/session_basic1.phpt
+++ b/ext/session/tests/session_basic1.phpt
@@ -17,7 +17,7 @@ ob_start();
echo "*** Testing basic session functionality : variation1 ***\n";
-$session_id = 'testid';
+$session_id = 'session-basic1';
session_id($session_id);
$path = __DIR__;
var_dump(session_save_path($path));
@@ -47,20 +47,20 @@ ob_end_flush();
*** Testing basic session functionality : variation1 ***
string(0) ""
*** Without lazy_write ***
-string(6) "testid"
+string(14) "session-basic1"
bool(true)
array(1) {
["lazy_write"]=>
bool(false)
}
bool(true)
-string(6) "testid"
+string(14) "session-basic1"
*** With lazy_write ***
-string(6) "testid"
+string(14) "session-basic1"
bool(true)
bool(true)
-string(6) "testid"
+string(14) "session-basic1"
*** Cleanup ***
-string(6) "testid"
+string(14) "session-basic1"
bool(true)
bool(true)
diff --git a/ext/session/tests/session_basic2.phpt b/ext/session/tests/session_basic2.phpt
index cb9585303c..68230f89b7 100644
--- a/ext/session/tests/session_basic2.phpt
+++ b/ext/session/tests/session_basic2.phpt
@@ -19,7 +19,7 @@ ob_start();
echo "*** Testing basic session functionality : variation2 ***\n";
-$session_id = 'testid';
+$session_id = 'session-basic2';
session_id($session_id);
$path = __DIR__;
var_dump(session_save_path($path));
@@ -55,7 +55,7 @@ ob_end_flush();
*** Testing basic session functionality : variation2 ***
string(0) ""
*** Without lazy_write ***
-string(6) "testid"
+string(14) "session-basic2"
bool(true)
bool(true)
bool(true)
diff --git a/ext/session/tests/session_basic3.phpt b/ext/session/tests/session_basic3.phpt
index f6ed10e296..5f6bd72b82 100644
--- a/ext/session/tests/session_basic3.phpt
+++ b/ext/session/tests/session_basic3.phpt
@@ -93,7 +93,7 @@ output_reset_rewrite_vars();
echo "*** Test trans sid ***\n";
ob_start();
-$session_id = 'testid';
+$session_id = 'session-basic3';
session_id($session_id);
session_start();
// Should add session ID to relative URL only for SECURITY
@@ -225,39 +225,39 @@ ob_end_flush();
*** Testing basic session functionality : variation3 use_trans_sid ***
*** Test trans sid ***
-<a href="/?PHPSESSID=testid">test</a>
-<a href="/path?PHPSESSID=testid">test</a>
-<a href="/path/?PHPSESSID=testid">test</a>
-<a href="/path/?foo=var&PHPSESSID=testid">test</a>
-<a href="../?PHPSESSID=testid">test</a>
-<a href="../path?PHPSESSID=testid">test</a>
-<a href="../path/?PHPSESSID=testid">test</a>
-<a href="../path/?foo=var&PHPSESSID=testid">test</a>
+<a href="/?PHPSESSID=session-basic3">test</a>
+<a href="/path?PHPSESSID=session-basic3">test</a>
+<a href="/path/?PHPSESSID=session-basic3">test</a>
+<a href="/path/?foo=var&PHPSESSID=session-basic3">test</a>
+<a href="../?PHPSESSID=session-basic3">test</a>
+<a href="../path?PHPSESSID=session-basic3">test</a>
+<a href="../path/?PHPSESSID=session-basic3">test</a>
+<a href="../path/?foo=var&PHPSESSID=session-basic3">test</a>
-<a href="/?PHPSESSID=testid#bar">test</a>
-<a href="/path/?PHPSESSID=testid#bar">test</a>
-<a href="/path/?foo=var&PHPSESSID=testid#bar">test</a>
-<a href="../?PHPSESSID=testid#bar">test</a>
-<a href="../path/?PHPSESSID=testid#bar">test</a>
-<a href="../path/?foo=var&PHPSESSID=testid#bar">test</a>
+<a href="/?PHPSESSID=session-basic3#bar">test</a>
+<a href="/path/?PHPSESSID=session-basic3#bar">test</a>
+<a href="/path/?foo=var&PHPSESSID=session-basic3#bar">test</a>
+<a href="../?PHPSESSID=session-basic3#bar">test</a>
+<a href="../path/?PHPSESSID=session-basic3#bar">test</a>
+<a href="../path/?foo=var&PHPSESSID=session-basic3#bar">test</a>
-<a href="/?foo&PHPSESSID=testid">test</a>
-<a href="/?foo&PHPSESSID=testid#bar">test</a>
-<a href="/?foo=var&PHPSESSID=testid">test</a>
-<a href="/?foo=var&PHPSESSID=testid#bar">test</a>
-<a href="../?foo&PHPSESSID=testid">test</a>
-<a href="../?foo&PHPSESSID=testid#bar">test</a>
-<a href="../?foo=var&PHPSESSID=testid">test</a>
-<a href="../?foo=var&PHPSESSID=testid#bar">test</a>
+<a href="/?foo&PHPSESSID=session-basic3">test</a>
+<a href="/?foo&PHPSESSID=session-basic3#bar">test</a>
+<a href="/?foo=var&PHPSESSID=session-basic3">test</a>
+<a href="/?foo=var&PHPSESSID=session-basic3#bar">test</a>
+<a href="../?foo&PHPSESSID=session-basic3">test</a>
+<a href="../?foo&PHPSESSID=session-basic3#bar">test</a>
+<a href="../?foo=var&PHPSESSID=session-basic3">test</a>
+<a href="../?foo=var&PHPSESSID=session-basic3#bar">test</a>
-<a href="file.php?PHPSESSID=testid">test</a>
-<a href="file.php?foo&PHPSESSID=testid">test</a>
-<a href="file.php?foo=var&PHPSESSID=testid">test</a>
-<a href="file.php?foo=var&PHPSESSID=testid#bar">test</a>
-<a href="../file.php?PHPSESSID=testid">test</a>
-<a href="../file.php?foo&PHPSESSID=testid">test</a>
-<a href="../file.php?foo=var&PHPSESSID=testid">test</a>
-<a href="../file.php?foo=var&PHPSESSID=testid#bar">test</a>
+<a href="file.php?PHPSESSID=session-basic3">test</a>
+<a href="file.php?foo&PHPSESSID=session-basic3">test</a>
+<a href="file.php?foo=var&PHPSESSID=session-basic3">test</a>
+<a href="file.php?foo=var&PHPSESSID=session-basic3#bar">test</a>
+<a href="../file.php?PHPSESSID=session-basic3">test</a>
+<a href="../file.php?foo&PHPSESSID=session-basic3">test</a>
+<a href="../file.php?foo=var&PHPSESSID=session-basic3">test</a>
+<a href="../file.php?foo=var&PHPSESSID=session-basic3#bar">test</a>
<a href="http://php.net">test</a>
<a href="http://php.net/">test</a>
@@ -310,19 +310,19 @@ ob_end_flush();
<a href="//php.net/some/path/file.php?foo=var">test</a>
<a href="//php.net/some/path/file.php?foo=var#bar">test</a>
-<form action="script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" />
+<form action="script.php" method="post"><input type="hidden" name="PHPSESSID" value="session-basic3" />
<input type="text" name="test1"></input>
<input type="text" name="test2" />
</form>
-<form action="../script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" />
+<form action="../script.php" method="post"><input type="hidden" name="PHPSESSID" value="session-basic3" />
<input type="text" name="test1"></input>
<input type="text" name="test2" />
</form>
-<form action="/path/script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" />
+<form action="/path/script.php" method="post"><input type="hidden" name="PHPSESSID" value="session-basic3" />
<input type="text" name="test1"></input>
<input type="text" name="test2" />
</form>
-<form action="../path/script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" />
+<form action="../path/script.php" method="post"><input type="hidden" name="PHPSESSID" value="session-basic3" />
<input type="text" name="test1"></input>
<input type="text" name="test2" />
</form>
@@ -341,5 +341,5 @@ ob_end_flush();
bool(true)
*** Cleanup ***
bool(true)
-string(6) "testid"
+string(14) "session-basic3"
bool(true)
diff --git a/ext/session/tests/session_basic5.phpt b/ext/session/tests/session_basic5.phpt
index 50e6cde920..6a7511c317 100644
--- a/ext/session/tests/session_basic5.phpt
+++ b/ext/session/tests/session_basic5.phpt
@@ -24,7 +24,7 @@ ini_set('session.trans_sid_hosts','php.net,example.com');
echo "*** Testing basic session functionality : variation5 use_trans_sid ***\n";
echo "*** Test trans sid ***\n";
-$session_id = 'testid';
+$session_id = 'session-basic5';
session_id($session_id);
session_start();
// Should add session ID to allowed hosts only for SECURITY
@@ -238,116 +238,116 @@ ob_end_flush();
*** Testing basic session functionality : variation5 use_trans_sid ***
*** Test trans sid ***
-<a href="/?PHPSESSID=testid">test</a>
-<a href="/path?PHPSESSID=testid">test</a>
-<a href="/path/?PHPSESSID=testid">test</a>
-<a href="/path/?foo=var&PHPSESSID=testid">test</a>
-<a href="../?PHPSESSID=testid">test</a>
-<a href="../path?PHPSESSID=testid">test</a>
-<a href="../path/?PHPSESSID=testid">test</a>
-<a href="../path/?foo=var&PHPSESSID=testid">test</a>
-
-<a href="/?PHPSESSID=testid#bar">test</a>
-<a href="/path/?PHPSESSID=testid#bar">test</a>
-<a href="/path/?foo=var&PHPSESSID=testid#bar">test</a>
-<a href="../?PHPSESSID=testid#bar">test</a>
-<a href="../path/?PHPSESSID=testid#bar">test</a>
-<a href="../path/?foo=var&PHPSESSID=testid#bar">test</a>
-
-<a href="/?foo&PHPSESSID=testid">test</a>
-<a href="/?foo&PHPSESSID=testid#bar">test</a>
-<a href="/?foo=var&PHPSESSID=testid">test</a>
-<a href="/?foo=var&PHPSESSID=testid#bar">test</a>
-<a href="../?foo&PHPSESSID=testid">test</a>
-<a href="../?foo&PHPSESSID=testid#bar">test</a>
-<a href="../?foo=var&PHPSESSID=testid">test</a>
-<a href="../?foo=var&PHPSESSID=testid#bar">test</a>
-
-<a href="file.php?PHPSESSID=testid">test</a>
-<a href="file.php?foo&PHPSESSID=testid">test</a>
-<a href="file.php?foo=var&PHPSESSID=testid">test</a>
-<a href="file.php?foo=var&PHPSESSID=testid#bar">test</a>
-<a href="../file.php?PHPSESSID=testid">test</a>
-<a href="../file.php?foo&PHPSESSID=testid">test</a>
-<a href="../file.php?foo=var&PHPSESSID=testid">test</a>
-<a href="../file.php?foo=var&PHPSESSID=testid#bar">test</a>
-
-<a href="http://php.net/?PHPSESSID=testid">test</a>
-<a href="http://php.net/?PHPSESSID=testid">test</a>
-<a href="http://php.net/?PHPSESSID=testid#bar">test</a>
-<a href="http://php.net/?foo&PHPSESSID=testid">test</a>
-<a href="http://php.net/?foo&PHPSESSID=testid#bar">test</a>
-<a href="http://php.net/?foo=var&PHPSESSID=testid">test</a>
-<a href="http://php.net/?foo=var&PHPSESSID=testid#bar">test</a>
-<a href="http://php.net/file.php?PHPSESSID=testid">test</a>
-<a href="http://php.net/file.php?PHPSESSID=testid#bar">test</a>
-<a href="http://php.net/file.php?foo&PHPSESSID=testid">test</a>
-<a href="http://php.net/file.php?foo&PHPSESSID=testid#bar">test</a>
-<a href="http://php.net/file.php?foo=var&PHPSESSID=testid">test</a>
-<a href="http://php.net/file.php?foo=var&PHPSESSID=testid#bar">test</a>
-<a href="http://php.net/some/path/file.php?PHPSESSID=testid">test</a>
-<a href="http://php.net/some/path/file.php?foo&PHPSESSID=testid">test</a>
-<a href="http://php.net/some/path/file.php?foo=var&PHPSESSID=testid">test</a>
-<a href="http://php.net/some/path/file.php?foo=var&PHPSESSID=testid#bar">test</a>
-
-<a href="https://php.net/?PHPSESSID=testid">test</a>
-<a href="https://php.net/?PHPSESSID=testid">test</a>
-<a href="https://php.net/?foo=var&PHPSESSID=testid#bar">test</a>
-<a href="https://php.net/file.php?PHPSESSID=testid">test</a>
-<a href="https://php.net/file.php?foo=var&PHPSESSID=testid#bar">test</a>
-<a href="https://php.net/some/path/file.php?PHPSESSID=testid">test</a>
-<a href="https://php.net/some/path/file.php?foo=var&PHPSESSID=testid#bar">test</a>
-<a href="https://php.net:8443/?PHPSESSID=testid">test</a>
-<a href="https://php.net:8443/?PHPSESSID=testid">test</a>
-<a href="https://php.net:8443/?foo=var&PHPSESSID=testid#bar">test</a>
-<a href="https://php.net:8443/file.php?PHPSESSID=testid">test</a>
-<a href="https://php.net:8443/file.php?foo=var&PHPSESSID=testid#bar">test</a>
-<a href="https://php.net:8443/some/path/file.php?PHPSESSID=testid">test</a>
-<a href="https://php.net:8443/some/path/file.php?foo=var&PHPSESSID=testid#bar">test</a>
-
-<a href="//php.net/?PHPSESSID=testid">test</a>
-<a href="//php.net/?PHPSESSID=testid">test</a>
-<a href="//php.net/?PHPSESSID=testid#bar">test</a>
-<a href="//php.net/?foo&PHPSESSID=testid">test</a>
-<a href="//php.net/?foo&PHPSESSID=testid#bar">test</a>
-<a href="//php.net/?foo=var&PHPSESSID=testid">test</a>
-<a href="//php.net/?foo=var&PHPSESSID=testid#bar">test</a>
-<a href="//php.net/file.php?PHPSESSID=testid">test</a>
-<a href="//php.net/file.php?PHPSESSID=testid#bar">test</a>
-<a href="//php.net/file.php?foo&PHPSESSID=testid">test</a>
-<a href="//php.net/file.php?foo&PHPSESSID=testid#bar">test</a>
-<a href="//php.net/file.php?foo=var&PHPSESSID=testid">test</a>
-<a href="//php.net/file.php?foo=var&PHPSESSID=testid#bar">test</a>
-<a href="//php.net/some/path/file.php?PHPSESSID=testid">test</a>
-<a href="//php.net/some/path/file.php?foo&PHPSESSID=testid">test</a>
-<a href="//php.net/some/path/file.php?foo=var&PHPSESSID=testid">test</a>
-<a href="//php.net/some/path/file.php?foo=var&PHPSESSID=testid#bar">test</a>
-
-<form action="script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" />
+<a href="/?PHPSESSID=session-basic5">test</a>
+<a href="/path?PHPSESSID=session-basic5">test</a>
+<a href="/path/?PHPSESSID=session-basic5">test</a>
+<a href="/path/?foo=var&PHPSESSID=session-basic5">test</a>
+<a href="../?PHPSESSID=session-basic5">test</a>
+<a href="../path?PHPSESSID=session-basic5">test</a>
+<a href="../path/?PHPSESSID=session-basic5">test</a>
+<a href="../path/?foo=var&PHPSESSID=session-basic5">test</a>
+
+<a href="/?PHPSESSID=session-basic5#bar">test</a>
+<a href="/path/?PHPSESSID=session-basic5#bar">test</a>
+<a href="/path/?foo=var&PHPSESSID=session-basic5#bar">test</a>
+<a href="../?PHPSESSID=session-basic5#bar">test</a>
+<a href="../path/?PHPSESSID=session-basic5#bar">test</a>
+<a href="../path/?foo=var&PHPSESSID=session-basic5#bar">test</a>
+
+<a href="/?foo&PHPSESSID=session-basic5">test</a>
+<a href="/?foo&PHPSESSID=session-basic5#bar">test</a>
+<a href="/?foo=var&PHPSESSID=session-basic5">test</a>
+<a href="/?foo=var&PHPSESSID=session-basic5#bar">test</a>
+<a href="../?foo&PHPSESSID=session-basic5">test</a>
+<a href="../?foo&PHPSESSID=session-basic5#bar">test</a>
+<a href="../?foo=var&PHPSESSID=session-basic5">test</a>
+<a href="../?foo=var&PHPSESSID=session-basic5#bar">test</a>
+
+<a href="file.php?PHPSESSID=session-basic5">test</a>
+<a href="file.php?foo&PHPSESSID=session-basic5">test</a>
+<a href="file.php?foo=var&PHPSESSID=session-basic5">test</a>
+<a href="file.php?foo=var&PHPSESSID=session-basic5#bar">test</a>
+<a href="../file.php?PHPSESSID=session-basic5">test</a>
+<a href="../file.php?foo&PHPSESSID=session-basic5">test</a>
+<a href="../file.php?foo=var&PHPSESSID=session-basic5">test</a>
+<a href="../file.php?foo=var&PHPSESSID=session-basic5#bar">test</a>
+
+<a href="http://php.net/?PHPSESSID=session-basic5">test</a>
+<a href="http://php.net/?PHPSESSID=session-basic5">test</a>
+<a href="http://php.net/?PHPSESSID=session-basic5#bar">test</a>
+<a href="http://php.net/?foo&PHPSESSID=session-basic5">test</a>
+<a href="http://php.net/?foo&PHPSESSID=session-basic5#bar">test</a>
+<a href="http://php.net/?foo=var&PHPSESSID=session-basic5">test</a>
+<a href="http://php.net/?foo=var&PHPSESSID=session-basic5#bar">test</a>
+<a href="http://php.net/file.php?PHPSESSID=session-basic5">test</a>
+<a href="http://php.net/file.php?PHPSESSID=session-basic5#bar">test</a>
+<a href="http://php.net/file.php?foo&PHPSESSID=session-basic5">test</a>
+<a href="http://php.net/file.php?foo&PHPSESSID=session-basic5#bar">test</a>
+<a href="http://php.net/file.php?foo=var&PHPSESSID=session-basic5">test</a>
+<a href="http://php.net/file.php?foo=var&PHPSESSID=session-basic5#bar">test</a>
+<a href="http://php.net/some/path/file.php?PHPSESSID=session-basic5">test</a>
+<a href="http://php.net/some/path/file.php?foo&PHPSESSID=session-basic5">test</a>
+<a href="http://php.net/some/path/file.php?foo=var&PHPSESSID=session-basic5">test</a>
+<a href="http://php.net/some/path/file.php?foo=var&PHPSESSID=session-basic5#bar">test</a>
+
+<a href="https://php.net/?PHPSESSID=session-basic5">test</a>
+<a href="https://php.net/?PHPSESSID=session-basic5">test</a>
+<a href="https://php.net/?foo=var&PHPSESSID=session-basic5#bar">test</a>
+<a href="https://php.net/file.php?PHPSESSID=session-basic5">test</a>
+<a href="https://php.net/file.php?foo=var&PHPSESSID=session-basic5#bar">test</a>
+<a href="https://php.net/some/path/file.php?PHPSESSID=session-basic5">test</a>
+<a href="https://php.net/some/path/file.php?foo=var&PHPSESSID=session-basic5#bar">test</a>
+<a href="https://php.net:8443/?PHPSESSID=session-basic5">test</a>
+<a href="https://php.net:8443/?PHPSESSID=session-basic5">test</a>
+<a href="https://php.net:8443/?foo=var&PHPSESSID=session-basic5#bar">test</a>
+<a href="https://php.net:8443/file.php?PHPSESSID=session-basic5">test</a>
+<a href="https://php.net:8443/file.php?foo=var&PHPSESSID=session-basic5#bar">test</a>
+<a href="https://php.net:8443/some/path/file.php?PHPSESSID=session-basic5">test</a>
+<a href="https://php.net:8443/some/path/file.php?foo=var&PHPSESSID=session-basic5#bar">test</a>
+
+<a href="//php.net/?PHPSESSID=session-basic5">test</a>
+<a href="//php.net/?PHPSESSID=session-basic5">test</a>
+<a href="//php.net/?PHPSESSID=session-basic5#bar">test</a>
+<a href="//php.net/?foo&PHPSESSID=session-basic5">test</a>
+<a href="//php.net/?foo&PHPSESSID=session-basic5#bar">test</a>
+<a href="//php.net/?foo=var&PHPSESSID=session-basic5">test</a>
+<a href="//php.net/?foo=var&PHPSESSID=session-basic5#bar">test</a>
+<a href="//php.net/file.php?PHPSESSID=session-basic5">test</a>
+<a href="//php.net/file.php?PHPSESSID=session-basic5#bar">test</a>
+<a href="//php.net/file.php?foo&PHPSESSID=session-basic5">test</a>
+<a href="//php.net/file.php?foo&PHPSESSID=session-basic5#bar">test</a>
+<a href="//php.net/file.php?foo=var&PHPSESSID=session-basic5">test</a>
+<a href="//php.net/file.php?foo=var&PHPSESSID=session-basic5#bar">test</a>
+<a href="//php.net/some/path/file.php?PHPSESSID=session-basic5">test</a>
+<a href="//php.net/some/path/file.php?foo&PHPSESSID=session-basic5">test</a>
+<a href="//php.net/some/path/file.php?foo=var&PHPSESSID=session-basic5">test</a>
+<a href="//php.net/some/path/file.php?foo=var&PHPSESSID=session-basic5#bar">test</a>
+
+<form action="script.php" method="post"><input type="hidden" name="PHPSESSID" value="session-basic5" />
<input type="text" name="test1"></input>
<input type="text" name="test2" />
</form>
-<form action="../script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" />r
+<form action="../script.php" method="post"><input type="hidden" name="PHPSESSID" value="session-basic5" />r
<input type="text" name="test1"></input>
<input type="text" name="test2" />
</form>
-<form action="/path/script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" />
+<form action="/path/script.php" method="post"><input type="hidden" name="PHPSESSID" value="session-basic5" />
<input type="text" name="test1"></input>
<input type="text" name="test2" />
</form>
-<form action="../path/script.php" method="post"><input type="hidden" name="PHPSESSID" value="testid" />
+<form action="../path/script.php" method="post"><input type="hidden" name="PHPSESSID" value="session-basic5" />
<input type="text" name="test1"></input>
<input type="text" name="test2" />
</form>
-<form method="post" action="http://php.net/script.php"><input type="hidden" name="PHPSESSID" value="testid" />
+<form method="post" action="http://php.net/script.php"><input type="hidden" name="PHPSESSID" value="session-basic5" />
<input type="text" name="test1"></input>
<input type="text" name="test2" />
</form>
-<form method="post" action="https://php.net/script.php"><input type="hidden" name="PHPSESSID" value="testid" />
+<form method="post" action="https://php.net/script.php"><input type="hidden" name="PHPSESSID" value="session-basic5" />
<input type="text" name="test1"></input>
<input type="text" name="test2" />
</form>
-<form method="post" action="//php.net/script.php"><input type="hidden" name="PHPSESSID" value="testid" />
+<form method="post" action="//php.net/script.php"><input type="hidden" name="PHPSESSID" value="session-basic5" />
<input type="text" name="test1"></input>
<input type="text" name="test2" />
</form>
@@ -436,5 +436,5 @@ ob_end_flush();
bool(true)
*** Cleanup ***
bool(true)
-string(6) "testid"
+string(14) "session-basic5"
bool(true)
diff --git a/ext/session/tests/session_commit_variation4.phpt b/ext/session/tests/session_commit_variation4.phpt
index 2633f543af..b0c3ad4a94 100644
--- a/ext/session/tests/session_commit_variation4.phpt
+++ b/ext/session/tests/session_commit_variation4.phpt
@@ -12,7 +12,7 @@ ob_start();
echo "*** Testing session_commit() : variation ***\n";
var_dump(ini_get('session.use_strict_mode'));
-var_dump(session_id("test"));
+var_dump(session_id("session-commit-variation4"));
var_dump(session_start());
var_dump(session_id());
var_dump(session_commit());
@@ -38,18 +38,18 @@ ob_end_flush();
string(1) "0"
string(0) ""
bool(true)
-string(4) "test"
+string(25) "session-commit-variation4"
bool(true)
-string(4) "test"
+string(25) "session-commit-variation4"
bool(true)
string(1) "0"
-string(4) "test"
+string(25) "session-commit-variation4"
bool(true)
-string(4) "test"
+string(25) "session-commit-variation4"
bool(true)
-string(4) "test"
+string(25) "session-commit-variation4"
bool(true)
-string(4) "test"
+string(25) "session-commit-variation4"
bool(true)
bool(true)
string(1) "0"
diff --git a/ext/session/tests/session_module_name_variation4.phpt b/ext/session/tests/session_module_name_variation4.phpt
index 9b845151a8..7e58ddc6c4 100644
--- a/ext/session/tests/session_module_name_variation4.phpt
+++ b/ext/session/tests/session_module_name_variation4.phpt
@@ -15,6 +15,8 @@ echo "*** Testing session_module_name() : variation ***\n";
require_once "save_handler.inc";
$path = __DIR__;
+$path = __DIR__ . '/session_module_name_variation4';
+@mkdir($path);
session_save_path($path);
session_module_name("files");
@@ -35,6 +37,7 @@ var_dump($_SESSION);
var_dump(session_destroy());
ob_end_flush();
+rmdir($path);
?>
--EXPECT--
*** Testing session_module_name() : variation ***
diff --git a/ext/session/tests/session_save_path_variation4.phpt b/ext/session/tests/session_save_path_variation4.phpt
index 8b3df52262..ec22e92051 100644
--- a/ext/session/tests/session_save_path_variation4.phpt
+++ b/ext/session/tests/session_save_path_variation4.phpt
@@ -14,7 +14,7 @@ ob_start();
echo "*** Testing session_save_path() : variation ***\n";
$initdir = __DIR__;
-$sessions = ($initdir."/sessions");
+$sessions = ($initdir."/session_save_path_variation4");
chdir($initdir);
@@ -38,7 +38,7 @@ ob_end_flush();
--CLEAN--
<?php
$initdir = __DIR__;
-$sessions = ($initdir."/sessions");
+$sessions = ($initdir."/session_save_path_variation4");
var_dump(rmdir($sessions));
?>
--EXPECTF--
diff --git a/ext/session/tests/session_save_path_variation5.phpt b/ext/session/tests/session_save_path_variation5.phpt
index 446a472ab4..3977d0deab 100644
--- a/ext/session/tests/session_save_path_variation5.phpt
+++ b/ext/session/tests/session_save_path_variation5.phpt
@@ -15,7 +15,7 @@ session.name=PHPSESSID
ob_start();
echo "*** Testing session_save_path() : variation ***\n";
$directory = __DIR__;
-$sessions = ($directory."/sessions");
+$sessions = ($directory."/session_save_path_variation5");
chdir($directory);
ini_set('open_basedir', '.');
@@ -36,7 +36,7 @@ ob_end_flush();
--CLEAN--
<?php
$directory = __DIR__;
-$sessions = ($directory."/sessions");
+$sessions = ($directory."/session_save_path_variation5");
var_dump(rmdir($sessions));
?>
--EXPECTF--
diff --git a/ext/session/tests/session_set_save_handler_basic.phpt b/ext/session/tests/session_set_save_handler_basic.phpt
index 459f03c825..23865aa512 100644
--- a/ext/session/tests/session_set_save_handler_basic.phpt
+++ b/ext/session/tests/session_set_save_handler_basic.phpt
@@ -20,7 +20,8 @@ var_dump(session_module_name(FALSE));
var_dump(session_module_name("blah"));
var_dump(session_module_name("foo"));
-$path = __DIR__;
+$path = __DIR__ . '/session_set_save_handler_basic';
+@mkdir($path);
session_save_path($path);
session_set_save_handler("open", "close", "read", "write", "destroy", "gc");
@@ -55,6 +56,7 @@ session_start();
session_destroy();
ob_end_flush();
+rmdir($path);
?>
--EXPECTF--
*** Testing session_set_save_handler() : basic functionality ***
diff --git a/ext/session/tests/session_set_save_handler_variation2.phpt b/ext/session/tests/session_set_save_handler_variation2.phpt
index 224846466e..a4b7d4df6e 100644
--- a/ext/session/tests/session_set_save_handler_variation2.phpt
+++ b/ext/session/tests/session_set_save_handler_variation2.phpt
@@ -10,13 +10,15 @@ ob_start();
echo "*** Testing session_set_save_handler() : variation ***\n";
require_once "save_handler.inc";
-$path = __DIR__;
+$path = __DIR__ . '/session_set_save_handler_variation2';
+@mkdir($path);
session_save_path($path);
var_dump(session_start());
var_dump(session_set_save_handler("open", "close", "read", "write", "destroy", "gc"));
var_dump(session_destroy());
ob_end_flush();
+rmdir($path);
?>
--EXPECTF--
*** Testing session_set_save_handler() : variation ***
diff --git a/ext/session/tests/session_set_save_handler_variation3.phpt b/ext/session/tests/session_set_save_handler_variation3.phpt
index be825cbe72..cc0ae1fb23 100644
--- a/ext/session/tests/session_set_save_handler_variation3.phpt
+++ b/ext/session/tests/session_set_save_handler_variation3.phpt
@@ -12,13 +12,15 @@ ob_start();
echo "*** Testing session_set_save_handler() : variation ***\n";
require_once "save_handler.inc";
-$path = __DIR__;
+$path = __DIR__ . '/session_set_save_handler_variation3';
+@mkdir($path);
var_dump(session_status());
session_save_path($path);
var_dump(session_set_save_handler("open", "close", "read", "write", "destroy", "gc"));
var_dump(session_destroy());
-
ob_end_flush();
+
+rmdir($path);
?>
--EXPECTF--
*** Testing session_set_save_handler() : variation ***
diff --git a/ext/session/tests/session_set_save_handler_variation4.phpt b/ext/session/tests/session_set_save_handler_variation4.phpt
index e1b61f29a7..9930f7aaf2 100644
--- a/ext/session/tests/session_set_save_handler_variation4.phpt
+++ b/ext/session/tests/session_set_save_handler_variation4.phpt
@@ -23,7 +23,8 @@ function noisy_gc($maxlifetime) {
}
require_once "save_handler.inc";
-$path = __DIR__;
+$path = __DIR__ . '/session_set_save_handler_variation4';
+@mkdir($path);
session_save_path($path);
session_set_save_handler("open", "close", "read", "write", "destroy", "noisy_gc");
@@ -42,13 +43,14 @@ var_dump($_SESSION);
var_dump(session_destroy());
ob_end_flush();
+rmdir($path);
?>
--EXPECTF--
*** Testing session_set_save_handler() : variation ***
Open [%s,PHPSESSID]
Read [%s,%s]
GC [0]
-2 deleted
+1 deleted
array(3) {
["Blah"]=>
string(12) "Hello World!"
diff --git a/ext/session/tests/session_set_save_handler_variation5.phpt b/ext/session/tests/session_set_save_handler_variation5.phpt
index 9860dcc04a..7cf7814259 100644
--- a/ext/session/tests/session_set_save_handler_variation5.phpt
+++ b/ext/session/tests/session_set_save_handler_variation5.phpt
@@ -24,7 +24,8 @@ function noisy_gc($maxlifetime) {
echo "*** Testing session_set_save_handler() : variation ***\n";
require_once "save_handler.inc";
-$path = __DIR__;
+$path = __DIR__ . '/session_set_save_handler_variation5';
+@mkdir($path);
var_dump(session_save_path($path));
echo "*** Without lazy_write ***\n";
@@ -48,6 +49,7 @@ var_dump(session_start());
var_dump(session_destroy());
ob_end_flush();
+rmdir($path);
?>
--EXPECTF--
*** Testing session_set_save_handler() : variation ***
diff --git a/ext/session/tests/session_set_save_handler_variation6.phpt b/ext/session/tests/session_set_save_handler_variation6.phpt
index d65c0dc1c8..11af07f603 100644
--- a/ext/session/tests/session_set_save_handler_variation6.phpt
+++ b/ext/session/tests/session_set_save_handler_variation6.phpt
@@ -17,7 +17,8 @@ ob_start();
echo "*** Testing session_set_save_handler() : test write short circuit ***\n";
require_once "save_handler.inc";
-$path = __DIR__;
+$path = __DIR__ . '/session_set_save_handler_variation6';
+@mkdir($path);
session_save_path($path);
session_set_save_handler("open", "close", "read", "write", "destroy", "gc", "create_sid", "validate_sid", "update");
@@ -53,6 +54,7 @@ session_start();
session_destroy();
ob_end_flush();
+rmdir($path);
?>
--EXPECTF--
*** Testing session_set_save_handler() : test write short circuit ***
diff --git a/ext/soap/tests/bug73037.phpt b/ext/soap/tests/bug73037.phpt
index 4e72932862..8060575bd8 100644
--- a/ext/soap/tests/bug73037.phpt
+++ b/ext/soap/tests/bug73037.phpt
@@ -1,7 +1,5 @@
--TEST--
Bug #73037 SoapServer reports Bad Request when gzipped, var 0
---CONFLICTS--
-server
--SKIPIF--
<?php
require_once('skipif.inc');
diff --git a/ext/soap/tests/custom_content_type.phpt b/ext/soap/tests/custom_content_type.phpt
index 17a074f102..9172d3d6ca 100644
--- a/ext/soap/tests/custom_content_type.phpt
+++ b/ext/soap/tests/custom_content_type.phpt
@@ -8,8 +8,6 @@ SOAP customized Content-Type, eg. SwA use case
echo "skip sapi/cli/tests/php_cli_server.inc required but not found";
}
?>
---CONFLICTS--
-server
--FILE--
<?php
diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c
index 0b21c4f684..c50d8d5d71 100644
--- a/ext/sockets/sockets.c
+++ b/ext/sockets/sockets.c
@@ -1045,11 +1045,7 @@ PHP_FUNCTION(socket_read)
if (retval == -1) {
/* if the socket is in non-blocking mode and there's no data to read,
don't output any error, as this is a normal situation, and not an error */
- if (errno == EAGAIN
-#ifdef EWOULDBLOCK
- || errno == EWOULDBLOCK
-#endif
- ) {
+ if (PHP_IS_TRANSIENT_ERROR(errno)) {
php_sock->error = errno;
SOCKETS_G(last_error) = errno;
} else {
diff --git a/ext/sodium/config.m4 b/ext/sodium/config.m4
index 0676b66910..05d9ebd5a1 100644
--- a/ext/sodium/config.m4
+++ b/ext/sodium/config.m4
@@ -11,8 +11,9 @@ if test "$PHP_SODIUM" != "no"; then
AC_DEFINE(HAVE_LIBSODIUMLIB, 1, [ ])
- dnl Add -Wno-type-limits as this may arise on 32bits platforms
+ dnl Add -Wno-type-limits and -Wno-logical-op as this may arise on 32bits platforms
SODIUM_COMPILER_FLAGS="$LIBSODIUM_CFLAGS -Wno-type-limits"
+ AX_CHECK_COMPILE_FLAG([-Wno-logical-op], SODIUM_COMPILER_FLAGS="$SODIUM_COMPILER_FLAGS -Wno-logical-op", , [-Werror])
PHP_NEW_EXTENSION(sodium, libsodium.c sodium_pwhash.c, $ext_shared, , $SODIUM_COMPILER_FLAGS)
PHP_SUBST(SODIUM_SHARED_LIBADD)
fi
diff --git a/ext/standard/array.c b/ext/standard/array.c
index f99af84611..3a50e77100 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -1321,7 +1321,13 @@ PHP_FUNCTION(max)
}
/* }}} */
-static int php_array_walk(zval *array, zval *userdata, int recursive) /* {{{ */
+typedef struct {
+ zend_fcall_info fci;
+ zend_fcall_info_cache fci_cache;
+} php_array_walk_context;
+
+static int php_array_walk(
+ php_array_walk_context *context, zval *array, zval *userdata, int recursive)
{
zval args[3], /* Arguments to userland function */
retval, /* Return value - unused */
@@ -1331,15 +1337,19 @@ static int php_array_walk(zval *array, zval *userdata, int recursive) /* {{{ */
uint32_t ht_iter;
int result = SUCCESS;
+ /* Create a local copy of fci, as we want to use different arguments at different
+ * levels of recursion. */
+ zend_fcall_info fci = context->fci;
+
/* Set up known arguments */
ZVAL_UNDEF(&args[1]);
if (userdata) {
ZVAL_COPY(&args[2], userdata);
}
- BG(array_walk_fci).retval = &retval;
- BG(array_walk_fci).param_count = userdata ? 3 : 2;
- BG(array_walk_fci).params = args;
+ fci.retval = &retval;
+ fci.param_count = userdata ? 3 : 2;
+ fci.params = args;
zend_hash_internal_pointer_reset_ex(target_hash, &pos);
ht_iter = zend_hash_iterator_add(target_hash, pos);
@@ -1386,8 +1396,6 @@ static int php_array_walk(zval *array, zval *userdata, int recursive) /* {{{ */
if (recursive && Z_TYPE_P(Z_REFVAL_P(zv)) == IS_ARRAY) {
HashTable *thash;
- zend_fcall_info orig_array_walk_fci;
- zend_fcall_info_cache orig_array_walk_fci_cache;
zval ref;
ZVAL_COPY_VALUE(&ref, zv);
@@ -1400,28 +1408,20 @@ static int php_array_walk(zval *array, zval *userdata, int recursive) /* {{{ */
break;
}
- /* backup the fcall info and cache */
- orig_array_walk_fci = BG(array_walk_fci);
- orig_array_walk_fci_cache = BG(array_walk_fci_cache);
-
Z_ADDREF(ref);
GC_PROTECT_RECURSION(thash);
- result = php_array_walk(zv, userdata, recursive);
+ result = php_array_walk(context, zv, userdata, recursive);
if (Z_TYPE_P(Z_REFVAL(ref)) == IS_ARRAY && thash == Z_ARRVAL_P(Z_REFVAL(ref))) {
/* If the hashtable changed in the meantime, we'll "leak" this apply count
* increment -- our reference to thash is no longer valid. */
GC_UNPROTECT_RECURSION(thash);
}
zval_ptr_dtor(&ref);
-
- /* restore the fcall info and cache */
- BG(array_walk_fci) = orig_array_walk_fci;
- BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
} else {
ZVAL_COPY(&args[0], zv);
/* Call the userland function */
- result = zend_call_function(&BG(array_walk_fci), &BG(array_walk_fci_cache));
+ result = zend_call_function(&fci, &context->fci_cache);
if (result == SUCCESS) {
zval_ptr_dtor(&retval);
}
@@ -1458,33 +1458,22 @@ static int php_array_walk(zval *array, zval *userdata, int recursive) /* {{{ */
zend_hash_iterator_del(ht_iter);
return result;
}
-/* }}} */
/* {{{ Apply a user function to every member of an array */
PHP_FUNCTION(array_walk)
{
zval *array;
zval *userdata = NULL;
- zend_fcall_info orig_array_walk_fci;
- zend_fcall_info_cache orig_array_walk_fci_cache;
-
- orig_array_walk_fci = BG(array_walk_fci);
- orig_array_walk_fci_cache = BG(array_walk_fci_cache);
+ php_array_walk_context context;
ZEND_PARSE_PARAMETERS_START(2, 3)
Z_PARAM_ARRAY_OR_OBJECT_EX(array, 0, 1)
- Z_PARAM_FUNC(BG(array_walk_fci), BG(array_walk_fci_cache))
+ Z_PARAM_FUNC(context.fci, context.fci_cache)
Z_PARAM_OPTIONAL
Z_PARAM_ZVAL(userdata)
- ZEND_PARSE_PARAMETERS_END_EX(
- BG(array_walk_fci) = orig_array_walk_fci;
- BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
- return
- );
-
- php_array_walk(array, userdata, 0);
- BG(array_walk_fci) = orig_array_walk_fci;
- BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
+ ZEND_PARSE_PARAMETERS_END();
+
+ php_array_walk(&context, array, userdata, 0);
RETURN_TRUE;
}
/* }}} */
@@ -1494,26 +1483,16 @@ PHP_FUNCTION(array_walk_recursive)
{
zval *array;
zval *userdata = NULL;
- zend_fcall_info orig_array_walk_fci;
- zend_fcall_info_cache orig_array_walk_fci_cache;
-
- orig_array_walk_fci = BG(array_walk_fci);
- orig_array_walk_fci_cache = BG(array_walk_fci_cache);
+ php_array_walk_context context;
ZEND_PARSE_PARAMETERS_START(2, 3)
Z_PARAM_ARRAY_OR_OBJECT_EX(array, 0, 1)
- Z_PARAM_FUNC(BG(array_walk_fci), BG(array_walk_fci_cache))
+ Z_PARAM_FUNC(context.fci, context.fci_cache)
Z_PARAM_OPTIONAL
Z_PARAM_ZVAL(userdata)
- ZEND_PARSE_PARAMETERS_END_EX(
- BG(array_walk_fci) = orig_array_walk_fci;
- BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
- return
- );
-
- php_array_walk(array, userdata, 1);
- BG(array_walk_fci) = orig_array_walk_fci;
- BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
+ ZEND_PARSE_PARAMETERS_END();
+
+ php_array_walk(&context, array, userdata, 1);
RETURN_TRUE;
}
/* }}} */
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index 876ef347eb..33247c4cb3 100755
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -463,8 +463,6 @@ PHP_RINIT_FUNCTION(basic) /* {{{ */
BG(strtok_last) = NULL;
BG(ctype_string) = NULL;
BG(locale_changed) = 0;
- BG(array_walk_fci) = empty_fcall_info;
- BG(array_walk_fci_cache) = empty_fcall_info_cache;
BG(user_compare_fci) = empty_fcall_info;
BG(user_compare_fci_cache) = empty_fcall_info_cache;
BG(page_uid) = -1;
@@ -1472,7 +1470,7 @@ PHPAPI int _php_error_log_ex(int opt_err, const char *message, size_t message_le
return FAILURE;
case 3: /*save to a file */
- stream = php_stream_open_wrapper(opt, "a", IGNORE_URL_WIN | REPORT_ERRORS, NULL);
+ stream = php_stream_open_wrapper(opt, "a", REPORT_ERRORS, NULL);
if (!stream) {
return FAILURE;
}
@@ -1953,12 +1951,8 @@ PHP_FUNCTION(highlight_string)
hicompiled_string_description = zend_make_compiled_string_description("highlighted code");
- // TODO: Accept zend_string in highlight_string API.
- zval str_zv;
- ZVAL_STR_COPY(&str_zv, str);
- highlight_string(&str_zv, &syntax_highlighter_ini, hicompiled_string_description);
+ highlight_string(str, &syntax_highlighter_ini, hicompiled_string_description);
efree(hicompiled_string_description);
- zval_ptr_dtor(&str_zv);
EG(error_reporting) = old_error_reporting;
diff --git a/ext/standard/basic_functions.h b/ext/standard/basic_functions.h
index 97faf50fd9..34b2570175 100644
--- a/ext/standard/basic_functions.h
+++ b/ext/standard/basic_functions.h
@@ -66,8 +66,6 @@ typedef struct _php_basic_globals {
char *strtok_last;
char strtok_table[256];
size_t strtok_len;
- zend_fcall_info array_walk_fci;
- zend_fcall_info_cache array_walk_fci_cache;
zend_fcall_info user_compare_fci;
zend_fcall_info_cache user_compare_fci_cache;
zend_llist *user_tick_functions;
diff --git a/ext/standard/mail.c b/ext/standard/mail.c
index 3080a3957b..4dfbfb03d0 100644
--- a/ext/standard/mail.c
+++ b/ext/standard/mail.c
@@ -371,7 +371,7 @@ void php_mail_log_to_syslog(char *message) {
void php_mail_log_to_file(char *filename, char *message, size_t message_size) {
/* Write 'message' to the given file. */
- uint32_t flags = IGNORE_URL_WIN | REPORT_ERRORS | STREAM_DISABLE_OPEN_BASEDIR;
+ uint32_t flags = REPORT_ERRORS | STREAM_DISABLE_OPEN_BASEDIR;
php_stream *stream = php_stream_open_wrapper(filename, "a", flags, NULL);
if (stream) {
php_stream_write(stream, message, message_size);
diff --git a/ext/standard/php_http.h b/ext/standard/php_http.h
index 1df941ee00..3f764c18a6 100644
--- a/ext/standard/php_http.h
+++ b/ext/standard/php_http.h
@@ -25,6 +25,5 @@ PHPAPI void php_url_encode_hash_ex(HashTable *ht, smart_str *formstr,
const char *key_prefix, size_t key_prefix_len,
const char *key_suffix, size_t key_suffix_len,
zval *type, const char *arg_sep, int enc_type);
-#define php_url_encode_hash(ht, formstr) php_url_encode_hash_ex((ht), (formstr), NULL, 0, NULL, 0, NULL, 0, NULL)
#endif
diff --git a/ext/standard/tests/streams/bug64433.phpt b/ext/standard/tests/streams/bug64433.phpt
index 56af241837..53fecc57f9 100644
--- a/ext/standard/tests/streams/bug64433.phpt
+++ b/ext/standard/tests/streams/bug64433.phpt
@@ -9,8 +9,6 @@ if(!$res) {
die("skip could not open cli server script");
}
?>
---CONFLICTS--
-server
--FILE--
<?php
include __DIR__."/../../../../sapi/cli/tests/php_cli_server.inc";
diff --git a/ext/standard/tests/url/get_headers_error_003.phpt b/ext/standard/tests/url/get_headers_error_003.phpt
index a8edc2cb21..7ee0b9e210 100644
--- a/ext/standard/tests/url/get_headers_error_003.phpt
+++ b/ext/standard/tests/url/get_headers_error_003.phpt
@@ -1,7 +1,5 @@
--TEST--
Test get_headers() function : test with context
---CONFLICTS--
-server
--FILE--
<?php
diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c
index 96baabacd4..58707d6f95 100644
--- a/ext/zip/php_zip.c
+++ b/ext/zip/php_zip.c
@@ -288,11 +288,13 @@ static int php_zip_add_file(ze_zip_object *obj, const char *filename, size_t fil
}
if (!expand_filepath(filename, resolved_path)) {
+ php_error_docref(NULL, E_WARNING, "No such file or directory");
return -1;
}
php_stat(resolved_path, strlen(resolved_path), FS_EXISTS, &exists_flag);
if (Z_TYPE(exists_flag) == IS_FALSE) {
+ php_error_docref(NULL, E_WARNING, "No such file or directory");
return -1;
}
@@ -1163,6 +1165,7 @@ PHP_FUNCTION(zip_open)
}
if(!expand_filepath(ZSTR_VAL(filename), resolved_path)) {
+ php_error_docref(NULL, E_WARNING, "No such file or directory");
RETURN_FALSE;
}
@@ -1444,6 +1447,7 @@ PHP_METHOD(ZipArchive, open)
}
if (!(resolved_path = expand_filepath(ZSTR_VAL(filename), NULL))) {
+ php_error_docref(NULL, E_WARNING, "No such file or directory");
RETURN_FALSE;
}
diff --git a/ext/zip/tests/bug64342_0.phpt b/ext/zip/tests/bug64342_0.phpt
index 43f60f5d7c..751fb9c4ba 100644
--- a/ext/zip/tests/bug64342_0.phpt
+++ b/ext/zip/tests/bug64342_0.phpt
@@ -38,6 +38,8 @@ DONE
?>
--EXPECTF--
%s.txt
+
+Warning: ZipArchive::addFile(): No such file or directory in %s on line %d
add failed
close ok
DONE
diff --git a/ext/zip/tests/bug64342_1-mb.phpt b/ext/zip/tests/bug64342_1-mb.phpt
index 4884c9fe5f..9efd046315 100644
--- a/ext/zip/tests/bug64342_1-mb.phpt
+++ b/ext/zip/tests/bug64342_1-mb.phpt
@@ -37,6 +37,7 @@ if ($zip->status == ZIPARCHIVE::ER_OK) {
}
@unlink($file);
?>
---EXPECT--
+--EXPECTF--
+Warning: ZipArchive::addFile(): No such file or directory in %s on line %d
failed
OK
diff --git a/ext/zip/tests/bug64342_1.phpt b/ext/zip/tests/bug64342_1.phpt
index 6b923d3ef1..1fff3da26d 100644
--- a/ext/zip/tests/bug64342_1.phpt
+++ b/ext/zip/tests/bug64342_1.phpt
@@ -37,6 +37,7 @@ if ($zip->status == ZIPARCHIVE::ER_OK) {
}
@unlink($file);
?>
---EXPECT--
+--EXPECTF--
+Warning: ZipArchive::addFile(): No such file or directory in %s on line %d
failed
OK