diff options
Diffstat (limited to 'ext/mbstring/mbstring.c')
| -rw-r--r-- | ext/mbstring/mbstring.c | 191 |
1 files changed, 157 insertions, 34 deletions
diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 213d38b5e3..5c77a36f7b 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -81,9 +81,17 @@ #include "zend_multibyte.h" #endif /* ZEND_MULTIBYTE */ -#if HAVE_MBSTRING +#if HAVE_ONIG +#include "php_onig_compat.h" +#include <oniguruma.h> +#undef UChar +#elif HAVE_PCRE || HAVE_BUNDLED_PCRE +#include <pcre.h> +#endif /* }}} */ +#if HAVE_MBSTRING + /* {{{ prototypes */ ZEND_DECLARE_MODULE_GLOBALS(mbstring) static PHP_GINIT_FUNCTION(mbstring); @@ -900,6 +908,79 @@ php_mb_parse_encoding_array(zval *array, enum mbfl_no_encoding **return_list, in } /* }}} */ +static void *_php_mb_compile_regex(const char *pattern TSRMLS_DC); +static int _php_mb_match_regex(void *opaque, const char *str, size_t str_len); +static void _php_mb_free_regex(void *opaque); + +#if HAVE_ONIG +/* {{{ _php_mb_compile_regex */ +void *_php_mb_compile_regex(const char *pattern TSRMLS_DC) +{ + php_mb_regex_t *retval; + OnigErrorInfo err_info; + int err_code; + + if ((err_code = onig_new(&retval, + (const OnigUChar *)pattern, + (const OnigUChar *)pattern + strlen(pattern), + ONIG_OPTION_IGNORECASE | ONIG_OPTION_DONT_CAPTURE_GROUP, + ONIG_ENCODING_ASCII, &OnigSyntaxPerl, &err_info))) { + OnigUChar err_str[ONIG_MAX_ERROR_MESSAGE_LEN]; + onig_error_code_to_str(err_str, err_code, err_info); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: %s", pattern, err_str); + retval = NULL; + } + return retval; +} +/* }}} */ + +/* {{{ _php_mb_match_regex */ +int _php_mb_match_regex(void *opaque, const char *str, size_t str_len) +{ + return onig_search((php_mb_regex_t *)opaque, (const OnigUChar *)str, + (const OnigUChar*)str + str_len, (const OnigUChar *)str, + (const OnigUChar*)str + str_len, NULL, ONIG_OPTION_NONE) >= 0; +} +/* }}} */ + +/* {{{ _php_mb_free_regex */ +void _php_mb_free_regex(void *opaque) +{ + onig_free((php_mb_regex_t *)opaque); +} +/* }}} */ +#elif HAVE_PCRE || HAVE_BUNDLED_PCRE +/* {{{ _php_mb_compile_regex */ +void *_php_mb_compile_regex(const char *pattern TSRMLS_DC) +{ + pcre *retval; + const char *err_str; + int err_offset; + + if (!(retval = pcre_compile(pattern, + PCRE_CASELESS, &err_str, &err_offset, NULL))) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (offset=%d): %s", pattern, err_offset, err_str); + } + return retval; +} +/* }}} */ + +/* {{{ _php_mb_match_regex */ +int _php_mb_match_regex(void *opaque, const char *str, size_t str_len) +{ + return pcre_exec((pcre *)opaque, NULL, str, (int)str_len, 0, + 0, NULL, 0) >= 0; +} +/* }}} */ + +/* {{{ _php_mb_free_regex */ +void _php_mb_free_regex(void *opaque) +{ + pcre_free(opaque); +} +/* }}} */ +#endif + /* {{{ php_mb_nls_get_default_detect_order_list */ static int php_mb_nls_get_default_detect_order_list(enum mbfl_no_language lang, enum mbfl_no_encoding **plist, int* plist_size) { @@ -920,6 +1001,7 @@ static int php_mb_nls_get_default_detect_order_list(enum mbfl_no_language lang, /* }}} */ /* {{{ php.ini directive handler */ +/* {{{ static PHP_INI_MH(OnUpdate_mbstring_language) */ static PHP_INI_MH(OnUpdate_mbstring_language) { enum mbfl_no_language no_language; @@ -1105,26 +1187,63 @@ static PHP_INI_MH(OnUpdate_mbstring_encoding_translation) } /* }}} */ +/* {{{ static PHP_INI_MH(OnUpdate_mbstring_http_output_conv_mimetypes */ +static PHP_INI_MH(OnUpdate_mbstring_http_output_conv_mimetypes) +{ + zval tmp; + void *re = NULL; + + if (!new_value) { + return SUCCESS; + } + php_trim(new_value, new_value_length, NULL, 0, &tmp, 3 TSRMLS_CC); + + if (Z_STRLEN(tmp) > 0) { + if (!(re = _php_mb_compile_regex(Z_STRVAL(tmp) TSRMLS_CC))) { + zval_dtor(&tmp); + return FAILURE; + } + } + + if (MBSTRG(http_output_conv_mimetypes)) { + _php_mb_free_regex(MBSTRG(http_output_conv_mimetypes)); + } + + MBSTRG(http_output_conv_mimetypes) = re; + + zval_dtor(&tmp); + return SUCCESS; +} +/* }}} */ +/* }}} */ + /* {{{ php.ini directive registration */ PHP_INI_BEGIN() - PHP_INI_ENTRY("mbstring.language", "neutral", PHP_INI_SYSTEM | PHP_INI_PERDIR, OnUpdate_mbstring_language) - PHP_INI_ENTRY("mbstring.detect_order", NULL, PHP_INI_ALL, OnUpdate_mbstring_detect_order) - PHP_INI_ENTRY("mbstring.http_input", "pass", PHP_INI_ALL, OnUpdate_mbstring_http_input) - PHP_INI_ENTRY("mbstring.http_output", "pass", PHP_INI_ALL, OnUpdate_mbstring_http_output) - PHP_INI_ENTRY("mbstring.internal_encoding", NULL, PHP_INI_ALL, OnUpdate_mbstring_internal_encoding) + PHP_INI_ENTRY("mbstring.language", "neutral", PHP_INI_SYSTEM | PHP_INI_PERDIR, OnUpdate_mbstring_language) + PHP_INI_ENTRY("mbstring.detect_order", NULL, PHP_INI_ALL, OnUpdate_mbstring_detect_order) + PHP_INI_ENTRY("mbstring.http_input", "pass", PHP_INI_ALL, OnUpdate_mbstring_http_input) + PHP_INI_ENTRY("mbstring.http_output", "pass", PHP_INI_ALL, OnUpdate_mbstring_http_output) + PHP_INI_ENTRY("mbstring.internal_encoding", NULL, PHP_INI_ALL, OnUpdate_mbstring_internal_encoding) #ifdef ZEND_MULTIBYTE - PHP_INI_ENTRY("mbstring.script_encoding", NULL, PHP_INI_ALL, OnUpdate_mbstring_script_encoding) + PHP_INI_ENTRY("mbstring.script_encoding", NULL, PHP_INI_ALL, OnUpdate_mbstring_script_encoding) #endif /* ZEND_MULTIBYTE */ - PHP_INI_ENTRY("mbstring.substitute_character", NULL, PHP_INI_ALL, OnUpdate_mbstring_substitute_character) - STD_PHP_INI_ENTRY("mbstring.func_overload", "0", - PHP_INI_SYSTEM, OnUpdateLong, func_overload, zend_mbstring_globals, mbstring_globals) - - STD_PHP_INI_BOOLEAN("mbstring.encoding_translation", "0", - PHP_INI_SYSTEM | PHP_INI_PERDIR, OnUpdate_mbstring_encoding_translation, - encoding_translation, zend_mbstring_globals, mbstring_globals) - - STD_PHP_INI_BOOLEAN("mbstring.strict_detection", "0", - PHP_INI_ALL, OnUpdateLong, strict_detection, zend_mbstring_globals, mbstring_globals) + PHP_INI_ENTRY("mbstring.substitute_character", NULL, PHP_INI_ALL, OnUpdate_mbstring_substitute_character) + STD_PHP_INI_ENTRY("mbstring.func_overload", "0", + PHP_INI_SYSTEM, OnUpdateLong, func_overload, zend_mbstring_globals, mbstring_globals) + + STD_PHP_INI_BOOLEAN("mbstring.encoding_translation", "0", + PHP_INI_SYSTEM | PHP_INI_PERDIR, + OnUpdate_mbstring_encoding_translation, + encoding_translation, zend_mbstring_globals, mbstring_globals) + PHP_INI_ENTRY("mbstring.http_output_conv_mimetypes", + "^(text/|application/xhtml\\+xml)", + PHP_INI_ALL, + OnUpdate_mbstring_http_output_conv_mimetypes) + + STD_PHP_INI_BOOLEAN("mbstring.strict_detection", "0", + PHP_INI_ALL, + OnUpdateLong, + strict_detection, zend_mbstring_globals, mbstring_globals) PHP_INI_END() /* }}} */ @@ -1163,6 +1282,7 @@ static PHP_GINIT_FUNCTION(mbstring) mbstring_globals->encoding_translation = 0; mbstring_globals->strict_detection = 0; mbstring_globals->outconv = NULL; + mbstring_globals->http_output_conv_mimetypes = NULL; #if HAVE_MBREGEX mbstring_globals->mb_regex_globals = php_mb_regex_globals_alloc(TSRMLS_C); #endif @@ -1172,6 +1292,20 @@ static PHP_GINIT_FUNCTION(mbstring) /* {{{ PHP_GSHUTDOWN_FUNCTION */ static PHP_GSHUTDOWN_FUNCTION(mbstring) { + if (mbstring_globals->http_input_list) { + free(mbstring_globals->http_input_list); + } +#ifdef ZEND_MULTIBYTE + if (mbstring_globals->script_encoding_list) { + free(mbstring_globals->script_encoding_list); + } +#endif /* ZEND_MULTIBYTE */ + if (mbstring_globals->detect_order_list) { + free(mbstring_globals->detect_order_list); + } + if (mbstring_globals->http_output_conv_mimetypes) { + _php_mb_free_regex(mbstring_globals->http_output_conv_mimetypes); + } #if HAVE_MBREGEX php_mb_regex_globals_free(mbstring_globals->mb_regex_globals TSRMLS_CC); #endif @@ -1210,18 +1344,6 @@ PHP_MSHUTDOWN_FUNCTION(mbstring) { UNREGISTER_INI_ENTRIES(); - if (MBSTRG(http_input_list)) { - free(MBSTRG(http_input_list)); - } -#ifdef ZEND_MULTIBYTE - if (MBSTRG(script_encoding_list)) { - free(MBSTRG(script_encoding_list)); - } -#endif /* ZEND_MULTIBYTE */ - if (MBSTRG(detect_order_list)) { - free(MBSTRG(detect_order_list)); - } - #if HAVE_MBREGEX PHP_MSHUTDOWN(mb_regex) (INIT_FUNC_ARGS_PASSTHRU); #endif @@ -1402,9 +1524,7 @@ PHP_MINFO_FUNCTION(mbstring) php_info_print_table_start(); php_info_print_table_row(2, "Multibyte Support", "enabled"); php_info_print_table_row(2, "Multibyte string engine", "libmbfl"); - if (MBSTRG(encoding_translation)) { - php_info_print_table_row(2, "HTTP input encoding translation", "enabled"); - } + php_info_print_table_row(2, "HTTP input encoding translation", MBSTRG(encoding_translation) ? "enabled": "disabled"); php_info_print_table_end(); php_info_print_table_start(); @@ -1839,8 +1959,11 @@ PHP_FUNCTION(mb_output_handler) } /* analyze mime type */ - if (SG(sapi_headers).mimetype && - strncmp(SG(sapi_headers).mimetype, "text/", 5) == 0) { + if (SG(sapi_headers).mimetype && + _php_mb_match_regex( + MBSTRG(http_output_conv_mimetypes), + SG(sapi_headers).mimetype, + strlen(SG(sapi_headers).mimetype))) { if ((s = strchr(SG(sapi_headers).mimetype,';')) == NULL){ mimetype = estrdup(SG(sapi_headers).mimetype); } else { |
