diff options
Diffstat (limited to 'ext/jstring/jstring.c')
-rw-r--r-- | ext/jstring/jstring.c | 2445 |
1 files changed, 2445 insertions, 0 deletions
diff --git a/ext/jstring/jstring.c b/ext/jstring/jstring.c new file mode 100644 index 0000000000..4280b24bba --- /dev/null +++ b/ext/jstring/jstring.c @@ -0,0 +1,2445 @@ +/* + +----------------------------------------------------------------------+ + | PHP version 4.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 2001 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Tsukada Takuya <tsukada@fminn.nagano.nagano.jp> | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +/* + * PHP4 Japanese String module "jstring" + * + * History: + * 2000.5.19 Release php-4.0RC2_jstring-1.0 + * 2001.4.1 Release php4_jstring-1.0.91 + * 2001.4.30 Release php4_jstring-1.1 (contribute to The PHP Group) + */ + +/* + * PHP3 Internationalization support program. + * + * Copyright (c) 1999,2000 by the PHP3 internationalization team. + * All rights reserved. + * + * See README_PHP3-i18n-ja for more detail. + * + * Authors: + * Hironori Sato <satoh@jpnnet.com> + * Shigeru Kanemoto <sgk@happysize.co.jp> + * Tsukada Takuya <tsukada@fminn.nagano.nagano.jp> + */ + + +#include "php.h" +#include "php_ini.h" +#include "php_config.h" +#include "jstring.h" +#include "ext/standard/php_string.h" +#include "ext/standard/php_mail.h" +#include "ext/standard/url.h" +#include "ext/standard/php_output.h" + +#include "php_variables.h" +#include "php_globals.h" +#include "rfc1867.h" +#include "php_content_types.h" +#include "SAPI.h" + +#if HAVE_JSTRING + +static enum mbfl_no_encoding php_jstr_default_identify_list[] = { + mbfl_no_encoding_ascii, + mbfl_no_encoding_jis, + mbfl_no_encoding_utf8, + mbfl_no_encoding_euc_jp, + mbfl_no_encoding_sjis +}; + +static int php_jstr_default_identify_list_size = sizeof(php_jstr_default_identify_list)/sizeof(enum mbfl_no_encoding); + +static unsigned char third_and_rest_force_ref[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE_REST }; + +SAPI_POST_HANDLER_FUNC(php_jstr_post_handler); + +static sapi_post_entry jstr_post_entries[] = { + { DEFAULT_POST_CONTENT_TYPE, sizeof(DEFAULT_POST_CONTENT_TYPE)-1, sapi_read_standard_form_data, php_jstr_post_handler }, + { MULTIPART_CONTENT_TYPE, sizeof(MULTIPART_CONTENT_TYPE)-1, sapi_read_standard_form_data, rfc1867_post_handler }, + { NULL, 0, NULL } +}; + +function_entry jstring_functions[] = { + PHP_FE(jstr_internal_encoding, NULL) + PHP_FE(jstr_http_input, NULL) + PHP_FE(jstr_http_output, NULL) + PHP_FE(jstr_detect_order, NULL) + PHP_FE(jstr_substitute_character, NULL) + PHP_FE(jstr_gpc_handler, NULL) + PHP_FE(jstr_output_handler, NULL) + PHP_FE(jstr_preferred_mime_name, NULL) + PHP_FE(jstr_strlen, NULL) + PHP_FE(jstr_strpos, NULL) + PHP_FE(jstr_strrpos, NULL) + PHP_FE(jstr_substr, NULL) + PHP_FE(jstr_strcut, NULL) + PHP_FE(jstr_strwidth, NULL) + PHP_FE(jstr_strimwidth, NULL) + PHP_FE(jstr_convert_encoding, NULL) + PHP_FE(jstr_detect_encoding, NULL) + PHP_FE(jstr_convert_kana, NULL) + PHP_FE(jstr_encode_mimeheader, NULL) + PHP_FE(jstr_decode_mimeheader, NULL) + PHP_FE(jstr_convert_variables, third_and_rest_force_ref) + PHP_FE(jstr_encode_numericentity, NULL) + PHP_FE(jstr_decode_numericentity, NULL) + PHP_FE(jstr_send_mail, NULL) + PHP_FALIAS(mbstrlen, jstr_strlen, NULL) + PHP_FALIAS(mbstrpos, jstr_strpos, NULL) + PHP_FALIAS(mbstrrpos, jstr_strrpos, NULL) + PHP_FALIAS(mbsubstr, jstr_substr, NULL) + PHP_FALIAS(mbstrcut, jstr_strcut, NULL) + PHP_FALIAS(i18n_internal_encoding, jstr_internal_encoding, NULL) + PHP_FALIAS(jstr_default_encoding, jstr_internal_encoding, NULL) + PHP_FALIAS(i18n_http_input, jstr_http_input, NULL) + PHP_FALIAS(i18n_http_output, jstr_http_output, NULL) + PHP_FALIAS(i18n_convert, jstr_convert_encoding, NULL) + PHP_FALIAS(i18n_discover_encoding, jstr_detect_encoding, NULL) + PHP_FALIAS(i18n_mime_header_encode, jstr_encode_mimeheader, NULL) + PHP_FALIAS(i18n_mime_header_decode, jstr_decode_mimeheader, NULL) + PHP_FALIAS(i18n_ja_jp_hantozen, jstr_convert_kana, NULL) + PHP_FALIAS(jstr_convert_hantozen, jstr_convert_kana, NULL) + { NULL, NULL, NULL } +}; + +zend_module_entry jstring_module_entry = { + "jstring", + jstring_functions, + PHP_MINIT(jstring), + PHP_MSHUTDOWN(jstring), + PHP_RINIT(jstring), + PHP_RSHUTDOWN(jstring), + PHP_MINFO(jstring), + STANDARD_MODULE_PROPERTIES +}; + +ZEND_DECLARE_MODULE_GLOBALS(jstring) + +#ifdef COMPILE_DL_JSTRING +ZEND_GET_MODULE(jstring) +#endif + + +static int +php_jstring_parse_encoding_list(const char *value, int value_length, int **return_list, int *return_size, int persistent) +{ + int n, l, size, bauto, *src, *list, *entry; + char *p, *p1, *p2, *endp, *tmpstr; + enum mbfl_no_encoding no_encoding; + + list = NULL; + if (value == NULL || value_length <= 0) { + return 0; + } else { + /* copy the value string for work */ + tmpstr = (char *)estrndup(value, value_length); + if (tmpstr == NULL) { + return 0; + } + /* count the number of listed encoding names */ + endp = tmpstr + value_length; + n = 1; + p1 = tmpstr; + while ((p2 = php_memnstr(p1, ",", 1, endp)) != NULL) { + p1 = p2 + 1; + n++; + } + size = n + php_jstr_default_identify_list_size; + /* make list */ + list = (int *)pecalloc(size, sizeof(int), persistent); + if (list != NULL) { + entry = list; + n = 0; + bauto = 0; + p1 = tmpstr; + do { + p2 = p = php_memnstr(p1, ",", 1, endp); + if (p == NULL) { + p = endp; + } + *p = '\0'; + /* trim spaces */ + while (p1 < p && (*p1 == ' ' || *p1 == '\t')) { + p1++; + } + p--; + while (p > p1 && (*p == ' ' || *p == '\t')) { + *p = '\0'; + p--; + } + /* convert to the encoding number and check encoding */ + no_encoding = mbfl_name2no_encoding(p1); + if (no_encoding == mbfl_no_encoding_auto) { + if (!bauto) { + bauto = 1; + l = php_jstr_default_identify_list_size; + src = php_jstr_default_identify_list; + while (l > 0) { + *entry++ = *src++; + l--; + n++; + } + } + } else if (no_encoding != mbfl_no_encoding_invalid) { + *entry++ = no_encoding; + n++; + } + p1 = p2 + 1; + } while (n < size && p2 != NULL); + *return_list = list; + *return_size = n; + } + efree(tmpstr); + } + + if (list == NULL) { + return 0; + } + + return 1; +} + +static int +php_jstring_parse_encoding_array(zval *array, int **return_list, int *return_size, int persistent) +{ + zval **hash_entry; + HashTable *target_hash; + int i, n, l, size, bauto, *list, *entry, *src; + enum mbfl_no_encoding no_encoding; + + list = NULL; + if (Z_TYPE_P(array) == IS_ARRAY) { + target_hash = array->value.ht; + zend_hash_internal_pointer_reset(target_hash); + i = zend_hash_num_elements(target_hash); + size = i + php_jstr_default_identify_list_size; + list = (int *)pecalloc(size, sizeof(int), persistent); + if (list != NULL) { + entry = list; + bauto = 0; + n = 0; + while (i > 0) { + if (zend_hash_get_current_data(target_hash, (void **) &hash_entry) == FAILURE) { + break; + } + convert_to_string_ex(hash_entry); + no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(hash_entry)); + if (no_encoding == mbfl_no_encoding_auto) { + if (!bauto) { + bauto = 1; + l = php_jstr_default_identify_list_size; + src = php_jstr_default_identify_list; + while (l > 0) { + *entry++ = *src++; + l--; + n++; + } + } + } else if (no_encoding != mbfl_no_encoding_invalid) { + *entry++ = no_encoding; + n++; + } + zend_hash_move_forward(target_hash); + i--; + } + *return_list = list; + *return_size = n; + } + } + + if (list == NULL) { + return 0; + } + + return 1; +} + + +/* php.ini directive handler */ +static PHP_INI_MH(OnUpdate_jstring_detect_order) +{ + int *list, size; + JSTRLS_FETCH(); + + if (php_jstring_parse_encoding_list(new_value, new_value_length, &list, &size, 1)) { + if (JSTRG(detect_order_list) != NULL) { + free(JSTRG(detect_order_list)); + } + JSTRG(detect_order_list) = list; + JSTRG(detect_order_list_size) = size; + } else { + return FAILURE; + } + + return SUCCESS; +} + +static PHP_INI_MH(OnUpdate_jstring_http_input) +{ + int *list, size; + JSTRLS_FETCH(); + + if (php_jstring_parse_encoding_list(new_value, new_value_length, &list, &size, 1)) { + if (JSTRG(http_input_list) != NULL) { + free(JSTRG(http_input_list)); + } + JSTRG(http_input_list) = list; + JSTRG(http_input_list_size) = size; + } else { + return FAILURE; + } + + return SUCCESS; +} + +static PHP_INI_MH(OnUpdate_jstring_http_output) +{ + enum mbfl_no_encoding no_encoding; + JSTRLS_FETCH(); + + no_encoding = mbfl_name2no_encoding(new_value); + if (no_encoding != mbfl_no_encoding_invalid) { + JSTRG(http_output_encoding) = no_encoding; + JSTRG(current_http_output_encoding) = no_encoding; + } else { + if (new_value != NULL && new_value_length > 0) { + return FAILURE; + } + } + + return SUCCESS; +} + +static PHP_INI_MH(OnUpdate_jstring_internal_encoding) +{ + enum mbfl_no_encoding no_encoding; + JSTRLS_FETCH(); + + no_encoding = mbfl_name2no_encoding(new_value); + if (no_encoding != mbfl_no_encoding_invalid) { + JSTRG(internal_encoding) = no_encoding; + JSTRG(current_internal_encoding) = no_encoding; + } else { + if (new_value != NULL && new_value_length > 0) { + return FAILURE; + } + } + + return SUCCESS; +} + +static PHP_INI_MH(OnUpdate_jstring_substitute_character) +{ + JSTRLS_FETCH(); + + if (new_value != NULL) { + if (strcasecmp("none", new_value) == 0) { + JSTRG(filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE; + } else if (strcasecmp("long", new_value) == 0) { + JSTRG(filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG; + } else { + JSTRG(filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR; + JSTRG(filter_illegal_substchar) = zend_atoi(new_value, new_value_length); + } + } + + return SUCCESS; +} + +/* php.ini directive registration */ +PHP_INI_BEGIN() + PHP_INI_ENTRY("jstring.detect_order", NULL, PHP_INI_ALL, OnUpdate_jstring_detect_order) + PHP_INI_ENTRY("jstring.http_input", NULL, PHP_INI_ALL, OnUpdate_jstring_http_input) + PHP_INI_ENTRY("jstring.http_output", NULL, PHP_INI_ALL, OnUpdate_jstring_http_output) + PHP_INI_ENTRY("jstring.internal_encoding", NULL, PHP_INI_ALL, OnUpdate_jstring_internal_encoding) + PHP_INI_ENTRY("jstring.substitute_character", NULL, PHP_INI_ALL, OnUpdate_jstring_substitute_character) +PHP_INI_END() + + +/* module global initialize handler */ +static void +php_jstring_init_globals(zend_jstring_globals *pglobals) +{ + pglobals->language = mbfl_no_language_japanese; + pglobals->current_language = mbfl_no_language_japanese; + pglobals->internal_encoding = mbfl_no_encoding_euc_jp; + pglobals->current_internal_encoding = mbfl_no_encoding_euc_jp; + pglobals->http_output_encoding = mbfl_no_encoding_invalid; + pglobals->current_http_output_encoding = mbfl_no_encoding_invalid; + pglobals->http_input_identify = mbfl_no_encoding_invalid; + pglobals->http_input_identify_get = mbfl_no_encoding_invalid; + pglobals->http_input_identify_post = mbfl_no_encoding_invalid; + pglobals->http_input_identify_cookie = mbfl_no_encoding_invalid; + pglobals->http_input_list = NULL; + pglobals->http_input_list_size = 0; + pglobals->detect_order_list = NULL; + pglobals->detect_order_list_size = 0; + pglobals->current_detect_order_list = NULL; + pglobals->current_detect_order_list_size = 0; + pglobals->filter_illegal_mode = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR; + pglobals->filter_illegal_substchar = 0x3f; /* '?' */ + pglobals->current_filter_illegal_mode = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR; + pglobals->current_filter_illegal_substchar = 0x3f; /* '?' */ + pglobals->outconv = NULL; +} + +PHP_MINIT_FUNCTION(jstring) +{ + ZEND_INIT_MODULE_GLOBALS(jstring, php_jstring_init_globals, NULL); + REGISTER_INI_ENTRIES(); + +#if defined(JSTR_ENC_TRANS) + sapi_unregister_post_entry(jstr_post_entries); + sapi_register_post_entries(jstr_post_entries); +#endif + + return SUCCESS; +} + + +PHP_MSHUTDOWN_FUNCTION(jstring) +{ + JSTRLS_FETCH(); + UNREGISTER_INI_ENTRIES(); + + if (JSTRG(http_input_list)) { + free(JSTRG(http_input_list)); + } + if (JSTRG(detect_order_list)) { + free(JSTRG(detect_order_list)); + } + + return SUCCESS; +} + + +PHP_RINIT_FUNCTION(jstring) +{ + int n, *list, *entry; + JSTRLS_FETCH(); + + JSTRG(current_language) = JSTRG(language); + JSTRG(current_internal_encoding) = JSTRG(internal_encoding); + JSTRG(current_http_output_encoding) = JSTRG(http_output_encoding); + JSTRG(current_filter_illegal_mode) = JSTRG(filter_illegal_mode); + JSTRG(current_filter_illegal_substchar) = JSTRG(filter_illegal_substchar); + JSTRG(http_input_identify) = mbfl_no_encoding_invalid; + JSTRG(http_input_identify_get) = mbfl_no_encoding_invalid; + JSTRG(http_input_identify_post) = mbfl_no_encoding_invalid; + JSTRG(http_input_identify_cookie) = mbfl_no_encoding_invalid; + n = 0; + if (JSTRG(detect_order_list)) { + list = JSTRG(detect_order_list); + n = JSTRG(detect_order_list_size); + } + if (n <= 0) { + list = php_jstr_default_identify_list; + n = php_jstr_default_identify_list_size; + } + entry = (int *)emalloc(n*sizeof(int)); + if (entry != NULL) { + JSTRG(current_detect_order_list) = entry; + JSTRG(current_detect_order_list_size) = n; + while (n > 0) { + *entry++ = *list++; + n--; + } + } + + return SUCCESS; +} + + +PHP_RSHUTDOWN_FUNCTION(jstring) +{ + JSTRLS_FETCH(); + + if (JSTRG(current_detect_order_list) != NULL) { + efree(JSTRG(current_detect_order_list)); + JSTRG(current_detect_order_list) = NULL; + JSTRG(current_detect_order_list_size) = 0; + } + if (JSTRG(outconv) != NULL) { + mbfl_buffer_converter_delete(JSTRG(outconv)); + JSTRG(outconv) = NULL; + } + + return SUCCESS; +} + + +PHP_MINFO_FUNCTION(jstring) +{ + php_info_print_table_start(); + php_info_print_table_header(2, "Japanese Support", "enabled"); +#if defined(JSTR_ENC_TRANS) + php_info_print_table_row(2, "http input encoding translation", "enabled"); +#endif + php_info_print_table_end(); + + DISPLAY_INI_ENTRIES(); +} + + + +/* {{{ proto string jstr_internal_encoding([string encoding]) + Sets the current internal encoding or Returns the current internal encoding as a string. */ +PHP_FUNCTION(jstr_internal_encoding) +{ + pval **arg1; + char *name; + enum mbfl_no_encoding no_encoding; + JSTRLS_FETCH(); + + if (ZEND_NUM_ARGS() == 0) { + name = (char *)mbfl_no_encoding2name(JSTRG(current_internal_encoding)); + if (name != NULL) { + RETURN_STRING(name, 1); + } else { + RETURN_FALSE; + } + } else if (ZEND_NUM_ARGS() == 1 && zend_get_parameters_ex(1, &arg1) != FAILURE) { + convert_to_string_ex(arg1); + no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(arg1)); + if (no_encoding == mbfl_no_encoding_invalid) { + php_error(E_WARNING, "unknown encoding \"%s\"", Z_STRVAL_PP(arg1)); + RETURN_FALSE; + } else { + JSTRG(current_internal_encoding) = no_encoding; + RETURN_TRUE; + } + } else { + WRONG_PARAM_COUNT; + } +} +/* }}} */ + + +/* {{{ proto string jstr_http_input([string type]) + Returns the input encoding. */ +PHP_FUNCTION(jstr_http_input) +{ + pval **arg1; + int result, retname, n, *entry; + char *name; + JSTRLS_FETCH(); + + retname = 1; + if (ZEND_NUM_ARGS() == 0) { + result = JSTRG(http_input_identify); + } else if (ARG_COUNT(ht) == 1 && zend_get_parameters_ex(1, &arg1) != FAILURE) { + convert_to_string_ex(arg1); + switch (*(Z_STRVAL_PP(arg1))) { + case 'G': + case 'g': + result = JSTRG(http_input_identify_get); + break; + case 'P': + case 'p': + result = JSTRG(http_input_identify_post); + break; + case 'C': + case 'c': + result = JSTRG(http_input_identify_cookie); + break; + case 'I': + case 'i': + if (array_init(return_value) == FAILURE) { + RETURN_FALSE; + } + entry = JSTRG(http_input_list); + n = JSTRG(http_input_list_size); + while (n > 0) { + name = (char *)mbfl_no_encoding2name(*entry); + if (name) { + add_next_index_string(return_value, name, 1); + } + entry++; + n--; + } + retname = 0; + break; + default: + result = JSTRG(http_input_identify); + break; + } + } else { + WRONG_PARAM_COUNT; + } + + if (retname) { + name = (char *)mbfl_no_encoding2name(result); + if (name != NULL) { + RETVAL_STRING(name, 1); + } else { + RETVAL_FALSE; + } + } +} +/* }}} */ + + +/* {{{ proto string jstr_http_output([string encoding]) + Sets the current output_encoding or Returns the current output_encoding as a string. */ +PHP_FUNCTION(jstr_http_output) +{ + pval **arg1; + char *name; + enum mbfl_no_encoding no_encoding; + JSTRLS_FETCH(); + + if (ZEND_NUM_ARGS() == 0) { + name = (char *)mbfl_no_encoding2name(JSTRG(current_http_output_encoding)); + if (name != NULL) { + RETURN_STRING(name, 1); + } else { + RETURN_FALSE; + } + } else if (ZEND_NUM_ARGS() == 1 && zend_get_parameters_ex(1, &arg1) != FAILURE) { + convert_to_string_ex(arg1); + no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(arg1)); + if (no_encoding == mbfl_no_encoding_invalid) { + php_error(E_WARNING, "unknown encoding \"%s\"", Z_STRVAL_PP(arg1)); + RETURN_FALSE; + } else { + JSTRG(current_http_output_encoding) = no_encoding; + RETURN_TRUE; + } + } else { + WRONG_PARAM_COUNT; + } +} +/* }}} */ + + +/* {{{ proto array jstr_detect_order([mixed encoding-list]) + Sets the current detect_order or Return the current detect_order as a array. */ +PHP_FUNCTION(jstr_detect_order) +{ + pval **arg1; + int n, size, *list, *entry; + char *name; + JSTRLS_FETCH(); + + if (ZEND_NUM_ARGS() == 0) { + if (array_init(return_value) == FAILURE) { + RETURN_FALSE; + } + entry = JSTRG(current_detect_order_list); + n = JSTRG(current_detect_order_list_size); + while (n > 0) { + name = (char *)mbfl_no_encoding2name(*entry); + if (name) { + add_next_index_string(return_value, name, 1); + } + entry++; + n--; + } + } else if (ZEND_NUM_ARGS() == 1 && zend_get_parameters_ex(1, &arg1) != FAILURE) { + list = NULL; + size = 0; + switch (Z_TYPE_PP(arg1)) { + case IS_ARRAY: + php_jstring_parse_encoding_array(*arg1, &list, &size, 0); + break; + default: + convert_to_string_ex(arg1); + php_jstring_parse_encoding_list(Z_STRVAL_PP(arg1), Z_STRLEN_PP(arg1), &list, &size, 0); + break; + } + if (list == NULL) { + RETVAL_FALSE; + } else { + if (JSTRG(current_detect_order_list)) { + efree(JSTRG(current_detect_order_list)); + } + JSTRG(current_detect_order_list) = list; + JSTRG(current_detect_order_list_size) = size; + RETVAL_TRUE; + } + } else { + WRONG_PARAM_COUNT; + } +} +/* }}} */ + + +/* {{{ proto mixed jstr_substitute_character([mixed substchar]) + Sets the current substitute_character or Returns the current substitute_character. */ +PHP_FUNCTION(jstr_substitute_character) +{ + pval **arg1; + JSTRLS_FETCH(); + + if (ZEND_NUM_ARGS() == 0) { + if (JSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) { + RETVAL_STRING("none", 1); + } else if(JSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG) { + RETVAL_STRING("long", 1); + } else { + RETVAL_LONG(JSTRG(current_filter_illegal_substchar)); + } + } else if (ZEND_NUM_ARGS() == 1 && zend_get_parameters_ex(1, &arg1) != FAILURE) { + switch (Z_TYPE_PP(arg1)) { + case IS_STRING: + if (strcasecmp("none", Z_STRVAL_PP(arg1)) == 0) { + JSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE; + } else if (strcasecmp("long", Z_STRVAL_PP(arg1)) == 0) { + JSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG; + } else { + convert_to_long_ex(arg1); + JSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR; + JSTRG(current_filter_illegal_substchar) = Z_LVAL_PP(arg1); + } + break; + default: + convert_to_long_ex(arg1); + JSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR; + JSTRG(current_filter_illegal_substchar) = Z_LVAL_PP(arg1); + break; + } + } else { + WRONG_PARAM_COUNT; + } +} +/* }}} */ + + +/* {{{ proto string jstr_preferred_mime_name(string encoding) + Return the preferred MIME name (charset) as a string. */ +PHP_FUNCTION(jstr_preferred_mime_name) +{ + pval **arg1; + enum mbfl_no_encoding no_encoding; + const char *name; + JSTRLS_FETCH(); + + if (ZEND_NUM_ARGS() == 1 && zend_get_parameters_ex(1, &arg1) != FAILURE) { + convert_to_string_ex(arg1); + no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(arg1)); + if (no_encoding == mbfl_no_encoding_invalid) { + php_error(E_WARNING, "unknown encoding \"%s\"", Z_STRVAL_PP(arg1)); + RETVAL_FALSE; + } else { + name = mbfl_no2preferred_mime_name(no_encoding); + if (name == NULL || *name == '\0') { + php_error(E_WARNING, "no name for \"%s\"", Z_STRVAL_PP(arg1)); + RETVAL_FALSE; + } else { + RETVAL_STRING((char *)name, 1); + } + } + } else { + WRONG_PARAM_COUNT; + } +} +/* }}} */ + + +static php_jstr_encoding_handler(zval *arg, char *res, char *separator) { + char *var, *val; + char *strtok_buf = NULL, **val_list; + zval *array_ptr = (zval *) arg; + int n, num, *len_list, *elist, elistsz; + enum mbfl_no_encoding from_encoding, to_encoding; + mbfl_string string, result, *ret; + mbfl_encoding_detector *identd; + mbfl_buffer_converter *convd; + JSTRLS_FETCH(); + ELS_FETCH(); + PLS_FETCH(); + + mbfl_string_init(&string); + mbfl_string_init(&result); + string.no_language = JSTRG(current_language); + string.no_encoding = JSTRG(current_internal_encoding); + + /* count the variables contained in the query */ + num = 1; + var = res; + n = strlen(res); + while(n > 0) { + if (*var == *separator) { + num++; + } + var++; + n--; + } + num *= 2; + val_list = (char **)ecalloc(num, sizeof(char *)); + len_list = (int *)ecalloc(num, sizeof(int)); + + /* split and decode the query */ + n = 0; + strtok_buf = NULL; + var = php_strtok_r(res, separator, &strtok_buf); + + while (var && n < num) { + val = strchr(var, '='); + if (val) { /* have a value */ + *val++ = '\0'; + val_list[n] = var; + len_list[n] = php_url_decode(var, strlen(var)); + n++; + val_list[n] = val; + len_list[n] = php_url_decode(val, strlen(val)); + } else { + val_list[n] = var; + len_list[n] = php_url_decode(var, strlen(var)); + n++; + val_list[n] = NULL; + len_list[n] = 0; + } + n++; + var = php_strtok_r(NULL, separator, &strtok_buf); + } + num = n; + + /* initialize converter */ + to_encoding = JSTRG(current_internal_encoding); + elist = JSTRG(http_input_list); + elistsz = JSTRG(http_input_list_size); + if (elistsz <= 0) { + from_encoding = mbfl_no_encoding_pass; + } else if (elistsz == 1) { + from_encoding = *elist; + } else { + /* auto detect */ + from_encoding = mbfl_no_encoding_invalid; + identd = mbfl_encoding_detector_new(elist, elistsz); + if (identd) { + n = 0; + while (n < num) { + string.val = val_list[n]; + string.len = len_list[n]; + if (mbfl_encoding_detector_feed(identd, &string)) { + break; + } + n++; + } + from_encoding = mbfl_encoding_detector_judge(identd); + mbfl_encoding_detector_delete(identd); + } + if (from_encoding == mbfl_no_encoding_invalid) { + from_encoding = mbfl_no_encoding_pass; + } + } + convd = NULL; + if (from_encoding != mbfl_no_encoding_pass) { + convd = mbfl_buffer_converter_new(from_encoding, to_encoding, 0); + if (convd != NULL) { + mbfl_buffer_converter_illegal_mode(convd, JSTRG(current_filter_illegal_mode)); + mbfl_buffer_converter_illegal_substchar(convd, JSTRG(current_filter_illegal_substchar)); + } else { + php_error(E_WARNING, "Unable to create converter in php_jstr_encoding_handler()"); + } + } + + /* convert encoding */ + string.no_encoding = from_encoding; + n = 0; + while (n < num) { + string.val = val_list[n+1]; + string.len = len_list[n+1]; + ret = NULL; + if (convd) { + ret = mbfl_buffer_converter_feed_result(convd, &string, &result); + } + if (ret != NULL) { + php_register_variable_safe(val_list[n], ret->val, ret->len, array_ptr ELS_CC PLS_CC); + } else { + php_register_variable_safe(val_list[n], val_list[n+1], len_list[n+1], array_ptr ELS_CC PLS_CC); + } + n+=2; + } + if (convd != NULL) { + mbfl_buffer_converter_delete(convd); + } + if (val_list != NULL) { + efree((void *)val_list); + } + if (len_list != NULL) { + efree((void *)len_list); + } + +} + +SAPI_POST_HANDLER_FUNC(php_jstr_post_handler) +{ + php_jstr_encoding_handler(arg, SG(request_info).post_data, "&"); +} + +/* http input processing */ +void jstr_treat_data(int arg, char *str, zval* destArray ELS_DC PLS_DC SLS_DC) +{ + char *res = NULL, *var, *val, *separator=NULL; + const char *c_var; + pval *array_ptr; + int free_buffer=0; + + switch (arg) { + case PARSE_POST: + case PARSE_GET: + case PARSE_COOKIE: + ALLOC_ZVAL(array_ptr); + array_init(array_ptr); + INIT_PZVAL(array_ptr); + switch (arg) { + case PARSE_POST: + PG(http_globals)[TRACK_VARS_POST] = array_ptr; + break; + case PARSE_GET: + PG(http_globals)[TRACK_VARS_GET] = array_ptr; + break; + case PARSE_COOKIE: + PG(http_globals)[TRACK_VARS_COOKIE] = array_ptr; + break; + } + break; + default: + array_ptr=destArray; + break; + } + + if (arg==PARSE_POST) { + sapi_handle_post(array_ptr SLS_CC); + return; + } + + if (arg == PARSE_GET) { /* GET data */ + c_var = SG(request_info).query_string; + if (c_var && *c_var) { + res = (char *) estrdup(c_var); + free_buffer = 1; + } else { + free_buffer = 0; + } + } else if (arg == PARSE_COOKIE) { /* Cookie data */ + c_var = SG(request_info).cookie_data; + if (c_var && *c_var) { + res = (char *) estrdup(c_var); + free_buffer = 1; + } else { + free_buffer = 0; + } + } else if (arg == PARSE_STRING) { /* String data */ + res = str; + free_buffer = 1; + } + + if (!res) { + return; + } + + switch (arg) { + case PARSE_POST: + case PARSE_GET: + case PARSE_STRING: + separator = (char *) estrdup(PG(arg_separator).input); + break; + case PARSE_COOKIE: + separator = ";\0"; + break; + } + + php_jstr_encoding_handler(array_ptr, res, separator); + + if(arg != PARSE_COOKIE) { + efree(separator); + } + + if (free_buffer) { + efree(res); + } +} + +/* {{{ proto array jstr_gpc_handler(string query, int type) + */ +PHP_FUNCTION(jstr_gpc_handler) +{ + pval **arg_str; + char *var, *val, *strtok_buf, **val_list; + int n, num, *len_list, *elist, elistsz; + enum mbfl_no_encoding from_encoding, to_encoding; + mbfl_string string, result, *ret; + mbfl_encoding_detector *identd; + mbfl_buffer_converter *convd; + JSTRLS_FETCH(); + + if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg_str) == FAILURE) { + WRONG_PARAM_COUNT; + } + if (array_init(return_value) == FAILURE) { + RETURN_FALSE; + } + + convert_to_string_ex(arg_str); + mbfl_string_init(&string); + mbfl_string_init(&result); + string.no_language = JSTRG(current_language); + string.no_encoding = JSTRG(current_internal_encoding); + + /* count the variables contained in the query */ + num = 1; + var = Z_STRVAL_PP(arg_str); + n = Z_STRLEN_PP(arg_str); + while (n > 0) { + if (*var == '&') { + num++; + } + var++; + n--; + } + num *= 2; + val_list = (char **)ecalloc(num, sizeof(char *)); + len_list = (int *)ecalloc(num, sizeof(int)); + + /* split and decode the query */ + n = 0; + strtok_buf = NULL; + var = php_strtok_r(Z_STRVAL_PP(arg_str), "&", &strtok_buf); + while (var && n < num) { + val = strchr(var, '='); + if (val) { /* have a value */ + *val++ = '\0'; + val_list[n] = var; + len_list[n] = php_url_decode(var, strlen(var)); + n++; + val_list[n] = val; + len_list[n] = php_url_decode(val, strlen(val)); + } else { + val_list[n] = var; + len_list[n] = php_url_decode(var, strlen(var)); + n++; + val_list[n] = NULL; + len_list[n] = 0; + } + n++; + var = php_strtok_r(NULL, "&", &strtok_buf); + } + num = n; + + /* initialize converter */ + to_encoding = JSTRG(current_internal_encoding); + elist = JSTRG(http_input_list); + elistsz = JSTRG(http_input_list_size); + if (elistsz <= 0) { + from_encoding = mbfl_no_encoding_pass; + } else if (elistsz == 1) { + from_encoding = *elist; + } else { + /* auto detect */ + from_encoding = mbfl_no_encoding_invalid; + identd = mbfl_encoding_detector_new(elist, elistsz); + if (identd != NULL) { + n = 0; + while (n < num) { + string.val = val_list[n]; + string.len = len_list[n]; + if (mbfl_encoding_detector_feed(identd, &string)) { + break; + } + n++; + } + from_encoding = mbfl_encoding_detector_judge(identd); + mbfl_encoding_detector_delete(identd); + } + if (from_encoding == mbfl_no_encoding_invalid) { + from_encoding = mbfl_no_encoding_pass; + } + } + convd = NULL; + if (from_encoding != mbfl_no_encoding_pass) { + convd = mbfl_buffer_converter_new(from_encoding, to_encoding, 0); + if (convd != NULL) { + mbfl_buffer_converter_illegal_mode(convd, JSTRG(current_filter_illegal_mode)); + mbfl_buffer_converter_illegal_substchar(convd, JSTRG(current_filter_illegal_substchar)); + } else { + php_error(E_WARNING, "Unable to create converter in jstr_gpc_handler()"); + } + } + + /* convert encoding */ + string.no_encoding = from_encoding; + n = 0; + while (n < num) { + string.val = val_list[n]; + string.len = len_list[n]; + ret = NULL; + if (convd) { + ret = mbfl_buffer_converter_feed_result(convd, &string, &result); + } + if (ret != NULL) { + add_next_index_stringl(return_value, ret->val, ret->len, 0); + } else { + add_next_index_stringl(return_value, val_list[n], len_list[n], 1); + } + n++; + } + if (convd != NULL) { + mbfl_buffer_converter_delete(convd); + } + if (val_list != NULL) { + efree((void *)val_list); + } + if (len_list != NULL) { + efree((void *)len_list); + } +} +/* }}} */ + + + +/* {{{ proto string jstr_output_handler(string contents, int status) + Returns string in output buffer converted to the http_output encoding */ +PHP_FUNCTION(jstr_output_handler) +{ + pval **arg_string, **arg_status; + mbfl_string string, result, *ret; + SLS_FETCH(); + JSTRLS_FETCH(); + + if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg_string, &arg_status) == FAILURE) { + WRONG_PARAM_COUNT; + } + + convert_to_string_ex(arg_string); + convert_to_long_ex(arg_status); + + ret = NULL; + if (SG(sapi_headers).send_default_content_type && + JSTRG(current_http_output_encoding) != mbfl_no_encoding_pass && + JSTRG(outconv) == NULL) { + JSTRG(outconv) = mbfl_buffer_converter_new(JSTRG(current_internal_encoding), JSTRG(current_http_output_encoding), 0); + } + if (SG(sapi_headers).send_default_content_type && JSTRG(outconv) != NULL) { + mbfl_buffer_converter_illegal_mode(JSTRG(outconv), JSTRG(current_filter_illegal_mode)); + mbfl_buffer_converter_illegal_substchar(JSTRG(outconv), JSTRG(current_filter_illegal_substchar)); + mbfl_string_init(&string); + string.no_language = JSTRG(current_language); + string.no_encoding = JSTRG(current_internal_encoding); + string.val = Z_STRVAL_PP(arg_string); + string.len = Z_STRLEN_PP(arg_string); + if ((Z_LVAL_PP(arg_status) & PHP_OUTPUT_HANDLER_END) != 0) { + ret = mbfl_buffer_converter_feed_result(JSTRG(outconv), &string, &result); + } else { + ret = mbfl_buffer_converter_feed_getbuffer(JSTRG(outconv), &string, &result); + } + } + + if (ret != NULL) { + RETVAL_STRINGL(ret->val, ret->len, 0); /* the string is already strdup()'ed */ + } else { + zval_dtor(return_value); + *return_value = **arg_string; + zval_copy_ctor(return_value); + } + if ((Z_LVAL_PP(arg_status) & PHP_OUTPUT_HANDLER_END) != 0) { + mbfl_buffer_converter_delete(JSTRG(outconv)); + JSTRG(outconv) = NULL; + } +} +/* }}} */ + + + +/* {{{ proto int jstr_strlen(string str, [string encoding]) + Get character numbers of a string */ +PHP_FUNCTION(jstr_strlen) +{ + pval **arg1, **arg2; + int n; + mbfl_string string; + JSTRLS_FETCH(); + + n = ZEND_NUM_ARGS(); + if ((n == 1 && zend_get_parameters_ex(1, &arg1) == FAILURE) || + (n == 2 && zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) || + n < 1 || n > 2) { + WRONG_PARAM_COUNT; + } + convert_to_string_ex(arg1); + mbfl_string_init(&string); + string.no_language = JSTRG(current_language); + string.no_encoding = JSTRG(current_internal_encoding); + string.val = Z_STRVAL_PP(arg1); + string.len = Z_STRLEN_PP(arg1); + + if (n == 2) { + convert_to_string_ex(arg2); + string.no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(arg2)); + if(string.no_encoding == mbfl_no_encoding_invalid) { + php_error(E_WARNING, "unknown encoding \"%s\"", Z_STRVAL_PP(arg2)); + RETURN_FALSE; + } + } + + n = mbfl_strlen(&string); + if (n >= 0) { + RETVAL_LONG(n); + } else { + RETVAL_FALSE; + } +} +/* }}} */ + + + +/* {{{ proto int jstr_strpos(string haystack, string needle [, int offset [, string encoding]]) + Find position of first occurrence of a string within another */ +PHP_FUNCTION(jstr_strpos) +{ + pval **arg1, **arg2, **arg3, **arg4; + int offset, n; + mbfl_string haystack, needle; + JSTRLS_FETCH(); + + mbfl_string_init(&haystack); + mbfl_string_init(&needle); + haystack.no_language = JSTRG(current_language); + haystack.no_encoding = JSTRG(current_internal_encoding); + needle.no_language = JSTRG(current_language); + needle.no_encoding = JSTRG(current_internal_encoding); + offset = 0; + switch (ZEND_NUM_ARGS()) { + case 2: + if (zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + break; + case 3: + if (zend_get_parameters_ex(3, &arg1, &arg2, &arg3) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long_ex(arg3); + offset = Z_LVAL_PP(arg3); + break; + case 4: + if (zend_get_parameters_ex(4, &arg1, &arg2, &arg3, &arg4) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long_ex(arg3); + offset = Z_LVAL_PP(arg3); + convert_to_string_ex(arg4); + haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(arg4)); + if(haystack.no_encoding == mbfl_no_encoding_invalid) { + php_error(E_WARNING, "unknown encoding \"%s\"", Z_STRVAL_PP(arg4)); + RETURN_FALSE; + } + break; + default: + WRONG_PARAM_COUNT; + } + + convert_to_string_ex(arg1); + convert_to_string_ex(arg2); + if (offset < 0) { + php_error(E_WARNING,"offset is minus value"); + offset = 0; + } + if (offset > Z_STRLEN_PP(arg1)) { + php_error(E_WARNING,"offset not contained in string"); + RETURN_FALSE; + } + if (Z_STRLEN_PP(arg2) == 0) { + php_error(E_WARNING,"Empty needle"); + RETURN_FALSE; + } + haystack.val = Z_STRVAL_PP(arg1); + haystack.len = Z_STRLEN_PP(arg1); + needle.val = Z_STRVAL_PP(arg2); + needle.len = Z_STRLEN_PP(arg2); + + n = mbfl_strpos(&haystack, &needle, offset, 0); + if (n >= 0) { + RETVAL_LONG(n); + } else { + RETVAL_FALSE; + } +} +/* }}} */ + + + +/* {{{ proto int jstr_strrpos(string haystack, string needle [, string encoding]) + Find the last occurrence of a character in a string within another */ +PHP_FUNCTION(jstr_strrpos) +{ + pval **arg1, **arg2, **arg3; + int n; + mbfl_string haystack, needle; + JSTRLS_FETCH(); + + mbfl_string_init(&haystack); + mbfl_string_init(&needle); + haystack.no_language = JSTRG(current_language); + haystack.no_encoding = JSTRG(current_internal_encoding); + needle.no_language = JSTRG(current_language); + needle.no_encoding = JSTRG(current_internal_encoding); + switch (ZEND_NUM_ARGS()) { + case 2: + if (zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + break; + case 3: + if (zend_get_parameters_ex(3, &arg1, &arg2, &arg3) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string_ex(arg3); + haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(arg3)); + if(haystack.no_encoding == mbfl_no_encoding_invalid) { + php_error(E_WARNING, "unknown encoding \"%s\"", Z_STRVAL_PP(arg3)); + RETURN_FALSE; + } + break; + default: + WRONG_PARAM_COUNT; + } + + convert_to_string_ex(arg1); + convert_to_string_ex(arg2); + if (Z_STRLEN_PP(arg1) <= 0) { + php_error(E_WARNING,"Empty haystack"); + RETURN_FALSE; + } + if (Z_STRLEN_PP(arg2) <= 0) { + php_error(E_WARNING,"Empty needle"); + RETURN_FALSE; + } + haystack.val = Z_STRVAL_PP(arg1); + haystack.len = Z_STRLEN_PP(arg1); + needle.val = Z_STRVAL_PP(arg2); + needle.len = Z_STRLEN_PP(arg2); + n = mbfl_strpos(&haystack, &needle, 0, 1); + if (n >= 0) { + RETVAL_LONG(n); + } else { + RETVAL_FALSE; + } +} +/* }}} */ + + + +/* {{{ proto string jstr_substr(string str, int start [, int length [, string encoding]]) + Return part of a string */ +PHP_FUNCTION(jstr_substr) +{ + pval **arg1, **arg2, **arg3, **arg4; + int argc, from, len, mblen; + mbfl_string string, result, *ret; + JSTRLS_FETCH(); + + mbfl_string_init(&string); + string.no_language = JSTRG(current_language); + string.no_encoding = JSTRG(current_internal_encoding); + + argc = ZEND_NUM_ARGS(); + switch (argc) { + case 2: + if (zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + break; + case 3: + if (zend_get_parameters_ex(3, &arg1, &arg2, &arg3) == FAILURE) { + WRONG_PARAM_COUNT; + } + break; + case 4: + if (zend_get_parameters_ex(4, &arg1, &arg2, &arg3, &arg4) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string_ex(arg4); + string.no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(arg4)); + if (string.no_encoding == mbfl_no_encoding_invalid) { + php_error(E_WARNING, "unknown encoding \"%s\"", Z_STRVAL_PP(arg4)); + RETURN_FALSE; + } + break; + default: + WRONG_PARAM_COUNT; + } + + convert_to_string_ex(arg1); + string.val = Z_STRVAL_PP(arg1); + string.len = Z_STRLEN_PP(arg1); + + convert_to_long_ex(arg2); + from = Z_LVAL_PP(arg2); + if (argc >= 3) { + convert_to_long_ex(arg3); + len = Z_LVAL_PP(arg3); + } else { + len = Z_STRLEN_PP(arg1); + } + + /* measures length */ + mblen = 0; + if (from < 0 || len < 0) { + mblen = mbfl_strlen(&string); + } + + /* if "from" position is negative, count start position from the end + * of the string + */ + if (from < 0) { + from = mblen + from; + if (from < 0) { + from = 0; + } + } + + /* if "length" position is negative, set it to the length + * needed to stop that many chars from the end of the string + */ + if (len < 0) { + len = (mblen - from) + len; + if (len < 0) { + len = 0; + } + } + + ret = mbfl_substr(&string, &result, from, len); + if (ret != NULL) { + RETVAL_STRINGL(ret->val, ret->len, 0); /* the string is already strdup()'ed */ + } else { + RETVAL_FALSE; + } +} +/* }}} */ + + + +/* {{{ proto string jstr_strcut(string str, int start [, int length [, string encoding]]) + Return part of a string */ +PHP_FUNCTION(jstr_strcut) +{ + pval **arg1, **arg2, **arg3, **arg4; + int argc, from, len; + mbfl_string string, result, *ret; + JSTRLS_FETCH(); + + mbfl_string_init(&string); + string.no_language = JSTRG(current_language); + string.no_encoding = JSTRG(current_internal_encoding); + + argc = ZEND_NUM_ARGS(); + switch (argc) { + case 2: + if (zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + break; + case 3: + if (zend_get_parameters_ex(3, &arg1, &arg2, &arg3) == FAILURE) { + WRONG_PARAM_COUNT; + } + break; + case 4: + if (zend_get_parameters_ex(4, &arg1, &arg2, &arg3, &arg4) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string_ex(arg4); + string.no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(arg4)); + if (string.no_encoding == mbfl_no_encoding_invalid) { + php_error(E_WARNING, "unknown encoding \"%s\"", Z_STRVAL_PP(arg4)); + RETURN_FALSE; + } + break; + default: + WRONG_PARAM_COUNT; + } + + convert_to_string_ex(arg1); + string.val = Z_STRVAL_PP(arg1); + string.len = Z_STRLEN_PP(arg1); + + convert_to_long_ex(arg2); + from = Z_LVAL_PP(arg2); + if (argc >= 3) { + convert_to_long_ex(arg3); + len = Z_LVAL_PP(arg3); + } else { + len = Z_STRLEN_PP(arg1); + } + + /* if "from" position is negative, count start position from the end + * of the string + */ + if (from < 0) { + from = (*arg1)->value.str.len + from; + if (from < 0) { + from = 0; + } + } + + /* if "length" position is negative, set it to the length + * needed to stop that many chars from the end of the string + */ + if (len < 0) { + len = ((*arg1)->value.str.len - from) + len; + if (len < 0) { + len = 0; + } + } + + ret = mbfl_strcut(&string, &result, from, len); + if (ret != NULL) { + RETVAL_STRINGL(ret->val, ret->len, 0); /* the string is already strdup()'ed */ + } else { + RETVAL_FALSE; + } +} +/* }}} */ + + + +/* {{{ proto int jstr_strwidth(string str, [string encoding]) + Get terminal width of a string */ +PHP_FUNCTION(jstr_strwidth) +{ + pval **arg1, **arg2; + int n; + mbfl_string string; + JSTRLS_FETCH(); + + n = ZEND_NUM_ARGS(); + if ((n == 1 && zend_get_parameters_ex(1, &arg1) == FAILURE) || + (n == 2 && zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) || + n < 1 || n > 2) { + WRONG_PARAM_COUNT; + } + convert_to_string_ex(arg1); + mbfl_string_init(&string); + string.no_language = JSTRG(current_language); + string.no_encoding = JSTRG(current_internal_encoding); + string.val = Z_STRVAL_PP(arg1); + string.len = Z_STRLEN_PP(arg1); + + if (n == 2){ + convert_to_string_ex(arg2); + string.no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(arg2)); + if(string.no_encoding == mbfl_no_encoding_invalid) { + php_error(E_WARNING, "unknown encoding \"%s\"", Z_STRVAL_PP(arg2)); + RETURN_FALSE; + } + } + + n = mbfl_strwidth(&string); + if (n >= 0) { + RETVAL_LONG(n); + } else { + RETVAL_FALSE; + } +} +/* }}} */ + + + +/* {{{ proto string jstr_strimwidth(string str, int start, int width [, string trimmarker [, string encoding]]) + Trim the string in terminal width */ +PHP_FUNCTION(jstr_strimwidth) +{ + pval **arg1, **arg2, **arg3, **arg4, **arg5; + int from, width; + mbfl_string string, result, marker, *ret; + JSTRLS_FETCH(); + + mbfl_string_init(&string); + mbfl_string_init(&marker); + string.no_language = JSTRG(current_language); + string.no_encoding = JSTRG(current_internal_encoding); + marker.no_language = JSTRG(current_language); + marker.no_encoding = JSTRG(current_internal_encoding); + marker.val = NULL; + marker.len = 0; + + switch (ZEND_NUM_ARGS()) { + case 3: + if (zend_get_parameters_ex(3, &arg1, &arg2, &arg3) == FAILURE) { + WRONG_PARAM_COUNT; + } + break; + case 4: + if (zend_get_parameters_ex(4, &arg1, &arg2, &arg3, &arg4) == FAILURE) { + WRONG_PARAM_COUNT; + } + break; + case 5: + if (zend_get_parameters_ex(5, &arg1, &arg2, &arg3, &arg4, &arg5) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string_ex(arg5); + string.no_encoding = marker.no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(arg5)); + if (string.no_encoding == mbfl_no_encoding_invalid) { + php_error(E_WARNING, "unknown encoding \"%s\"", Z_STRVAL_PP(arg5)); + RETURN_FALSE; + } + break; + default: + WRONG_PARAM_COUNT; + } + + convert_to_string_ex(arg1); + string.val = Z_STRVAL_PP(arg1); + string.len = Z_STRLEN_PP(arg1); + + convert_to_long_ex(arg2); + from = Z_LVAL_PP(arg2); + convert_to_long_ex(arg3); + width = Z_LVAL_PP(arg3); + + if (ZEND_NUM_ARGS() >= 4) { + convert_to_string_ex(arg4); + marker.val = Z_STRVAL_PP(arg4); + marker.len = Z_STRLEN_PP(arg4); + } + + ret = mbfl_strimwidth(&string, &marker, &result, from, width); + if (ret != NULL) { + RETVAL_STRINGL(ret->val, ret->len, 0); /* the string is already strdup()'ed */ + } else { + RETVAL_FALSE; + } +} +/* }}} */ + + + +/* {{{ proto string jstr_convert_encoding(string str, string to-encoding [, mixed from-encoding]) + Returns converted string in desired encoding */ +PHP_FUNCTION(jstr_convert_encoding) +{ + pval **arg_str, **arg_new, **arg_old; + mbfl_string string, result, *ret; + enum mbfl_no_encoding from_encoding, to_encoding; + mbfl_buffer_converter *convd; + int size, *list; + JSTRLS_FETCH(); + + if (ZEND_NUM_ARGS() == 2) { + if (zend_get_parameters_ex(2, &arg_str, &arg_new) == FAILURE) { + WRONG_PARAM_COUNT; + } + } else if (ZEND_NUM_ARGS() == 3) { + if (zend_get_parameters_ex(3, &arg_str, &arg_new, &arg_old) == FAILURE) { + WRONG_PARAM_COUNT; + } + } else { + WRONG_PARAM_COUNT; + } + + /* new encoding */ + convert_to_string_ex(arg_new); + to_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(arg_new)); + if (to_encoding == mbfl_no_encoding_invalid) { + php_error(E_WARNING, "unknown encoding \"%s\"", Z_STRVAL_PP(arg_new)); + RETURN_FALSE; + } + + /* initialize string */ + convert_to_string_ex(arg_str); + mbfl_string_init(&string); + mbfl_string_init(&result); + from_encoding = JSTRG(current_internal_encoding); + string.no_encoding = from_encoding; + string.no_language = JSTRG(current_language); + string.val = Z_STRVAL_PP(arg_str); + string.len = Z_STRLEN_PP(arg_str); + + /* pre-conversion encoding */ + if (ZEND_NUM_ARGS() >= 3) { + list = NULL; + size = 0; + switch (Z_TYPE_PP(arg_old)) { + case IS_ARRAY: + php_jstring_parse_encoding_array(*arg_old, &list, &size, 0); + break; + default: + convert_to_string_ex(arg_old); + php_jstring_parse_encoding_list(Z_STRVAL_PP(arg_old), Z_STRLEN_PP(arg_old), &list, &size, 0); + break; + } + if (size == 1) { + from_encoding = *list; + } else if (size > 1) { + /* auto detect */ + from_encoding = mbfl_identify_encoding_no(&string, list, size); + if (from_encoding != mbfl_no_encoding_invalid) { + string.no_encoding = from_encoding; + } else { + php_error(E_WARNING, "Unable to detect encoding in jstr_convert_encoding()"); + from_encoding = mbfl_no_encoding_pass; + to_encoding = from_encoding; + string.no_encoding = from_encoding; + } + } else { + php_error(E_WARNING, "illegal from-encoding in jstr_convert_encoding()"); + } + if (list != NULL) { + efree((void *)list); + } + } + + /* initialize converter */ + convd = mbfl_buffer_converter_new(from_encoding, to_encoding, string.len); + if (convd == NULL) { + php_error(E_WARNING, "Unable to create converter in jstr_convert_encoding()"); + RETURN_FALSE; + } + mbfl_buffer_converter_illegal_mode(convd, JSTRG(current_filter_illegal_mode)); + mbfl_buffer_converter_illegal_substchar(convd, JSTRG(current_filter_illegal_substchar)); + + /* do it */ + ret = mbfl_buffer_converter_feed_result(convd, &string, &result); + if (ret != NULL) { + RETVAL_STRINGL(ret->val, ret->len, 0); /* the string is already strdup()'ed */ + } else { + RETVAL_FALSE; + } + + mbfl_buffer_converter_delete(convd); +} +/* }}} */ + + + +/* {{{ proto string jstr_detect_encoding(string str [, mixed encoding_list]) + Encoding of the given string is returned (as a string) */ +PHP_FUNCTION(jstr_detect_encoding) +{ + pval **arg_str, **arg_list; + mbfl_string string; + const char *ret; + enum mbfl_no_encoding *elist; + int size, *list; + JSTRLS_FETCH(); + + if (ZEND_NUM_ARGS() == 1) { + if (zend_get_parameters_ex(1, &arg_str) == FAILURE) { + WRONG_PARAM_COUNT; + } + } else if (ZEND_NUM_ARGS() == 2) { + if (zend_get_parameters_ex(2, &arg_str, &arg_list) == FAILURE) { + WRONG_PARAM_COUNT; + } + } else { + WRONG_PARAM_COUNT; + } + + /* make encoding list */ + list = NULL; + size = 0; + if (ZEND_NUM_ARGS() >= 2) { + switch (Z_TYPE_PP(arg_list)) { + case IS_ARRAY: + php_jstring_parse_encoding_array(*arg_list, &list, &size, 0); + break; + default: + convert_to_string_ex(arg_list); + php_jstring_parse_encoding_list(Z_STRVAL_PP(arg_list), Z_STRLEN_PP(arg_list), &list, &size, 0); + break; + } + if (size <= 0) { + php_error(E_WARNING, "illegal argument"); + } + } + + if (size > 0 && list != NULL) { + elist = list; + } else { + elist = JSTRG(current_detect_order_list); + size = JSTRG(current_detect_order_list_size); + } + + convert_to_string_ex(arg_str); + mbfl_string_init(&string); + string.no_language = JSTRG(current_language); + string.val = Z_STRVAL_PP(arg_str); + string.len = Z_STRLEN_PP(arg_str); + ret = mbfl_identify_encoding_name(&string, elist, size); + if (list != NULL) { + efree((void *)list); + } + if (ret != NULL) { + RETVAL_STRING((char *)ret, 1); + } else { + RETVAL_FALSE; + } +} +/* }}} */ + + + +/* {{{ proto string jstr_encode_mimeheader(string str [, string charset [, string transfer-encoding [, string linefeed]]]) + Convert the string to MIME "encoded-word" in the format of =?charset?(B|Q)?encoded_string?= */ +PHP_FUNCTION(jstr_encode_mimeheader) +{ + pval **argv[4]; + enum mbfl_no_encoding charset, transenc; + mbfl_string string, result, *ret; + char *p, *linefeed; + JSTRLS_FETCH(); + + if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 4 || zend_get_parameters_array_ex(ZEND_NUM_ARGS(), argv) == FAILURE) { + WRONG_PARAM_COUNT; + } + + charset = mbfl_no_encoding_pass; + transenc = mbfl_no_encoding_base64; + if (ZEND_NUM_ARGS() >= 2) { + convert_to_string_ex(argv[1]); + charset = mbfl_name2no_encoding(Z_STRVAL_PP(argv[1])); + if (charset == mbfl_no_encoding_invalid) { + php_error(E_WARNING, "unknown encoding \"%s\"", Z_STRVAL_PP(argv[1])); + RETURN_FALSE; + } + } else { + switch (JSTRG(current_language)) { + case mbfl_no_language_japanese: + charset = mbfl_no_encoding_2022jp; + break; + case mbfl_no_language_english: + charset = mbfl_no_encoding_8859_1; + transenc = mbfl_no_encoding_qprint; + break; + default: + charset = mbfl_no_encoding_utf8; + break; + } + } + + if (ZEND_NUM_ARGS() >= 3) { + convert_to_string_ex(argv[2]); + p = Z_STRVAL_PP(argv[2]); + if (*p == 'B' || *p == 'b') { + transenc = mbfl_no_encoding_base64; + } else if (*p == 'Q' || *p == 'q') { + transenc = mbfl_no_encoding_qprint; + } + } + + linefeed = "\r\n"; + if (ZEND_NUM_ARGS() >= 4) { + convert_to_string_ex(argv[3]); + linefeed = Z_STRVAL_PP(argv[3]); + } + + convert_to_string_ex(argv[0]); + mbfl_string_init(&string); + mbfl_string_init(&result); + string.no_language = JSTRG(current_language); + string.no_encoding = JSTRG(current_internal_encoding); + string.val = Z_STRVAL_PP(argv[0]); + string.len = Z_STRLEN_PP(argv[0]); + ret = mbfl_mime_header_encode(&string, &result, charset, transenc, linefeed, 0); + if (ret != NULL) { + RETVAL_STRINGL(ret->val, ret->len, 0) /* the string is already strdup()'ed */ + } else { + RETVAL_FALSE; + } +} +/* }}} */ + + + +/* {{{ proto string jstr_decode_mimeheader(string string) + Decodes the MIME "encoded-word" in the string */ +PHP_FUNCTION(jstr_decode_mimeheader) +{ + pval **arg_str; + mbfl_string string, result, *ret; + JSTRLS_FETCH(); + + if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg_str) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string_ex(arg_str); + mbfl_string_init(&string); + mbfl_string_init(&result); + string.no_language = JSTRG(current_language); + string.no_encoding = JSTRG(current_internal_encoding); + string.val = Z_STRVAL_PP(arg_str); + string.len = Z_STRLEN_PP(arg_str); + ret = mbfl_mime_header_decode(&string, &result, JSTRG(current_internal_encoding)); + if (ret != NULL) { + RETVAL_STRINGL(ret->val, ret->len, 0) /* the string is already strdup()'ed */ + } else { + RETVAL_FALSE; + } +} +/* }}} */ + + + +/* {{{ proto string jstr_convert_kana(string str [,string option] [, string encoding]) + Conversion between full-width character and half-width character (Japanese) */ +PHP_FUNCTION(jstr_convert_kana) +{ + pval **arg1, **arg2, **arg3; + int argc, opt, i, n; + char *p; + mbfl_string string, result, *ret; + enum mbfl_no_encoding no_encoding; + JSTRLS_FETCH(); + + mbfl_string_init(&string); + string.no_language = JSTRG(current_language); + string.no_encoding = JSTRG(current_internal_encoding); + + argc = ZEND_NUM_ARGS(); + if ((argc == 1 && zend_get_parameters_ex(1, &arg1) == FAILURE) || + (argc == 2 && zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) || + (argc == 3 && zend_get_parameters_ex(3, &arg1, &arg2, &arg3) == FAILURE) || + argc < 1 || argc > 3) { + WRONG_PARAM_COUNT; + } + + convert_to_string_ex(arg1); + string.val = Z_STRVAL_PP(arg1); + string.len = Z_STRLEN_PP(arg1); + + /* option */ + if (argc >= 2){ + convert_to_string_ex(arg2); + p = Z_STRVAL_PP(arg2); + n = Z_STRLEN_PP(arg2); + i = 0; + opt = 0; + while (i < n) { + i++; + switch (*p++) { + case 'A': + opt |= 0x1; + break; + case 'a': + opt |= 0x10; + break; + case 'R': + opt |= 0x2; + break; + case 'r': + opt |= 0x20; + break; + case 'N': + opt |= 0x4; + break; + case 'n': + opt |= 0x40; + break; + case 'S': + opt |= 0x8; + break; + case 's': + opt |= 0x80; + break; + case 'K': + opt |= 0x100; + break; + case 'k': + opt |= 0x1000; + break; + case 'H': + opt |= 0x200; + break; + case 'h': + opt |= 0x2000; + break; + case 'V': + opt |= 0x800; + break; + case 'C': + opt |= 0x10000; + break; + case 'c': + opt |= 0x20000; + break; + case 'M': + opt |= 0x100000; + break; + case 'm': + opt |= 0x200000; + break; + } + } + } else { + opt = 0x900; + } + + /* encoding */ + if (argc == 3) { + convert_to_string_ex(arg3); + no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(arg3)); + if (no_encoding == mbfl_no_encoding_invalid) { + php_error(E_WARNING, "unknown encoding \"%s\"", Z_STRVAL_PP(arg3)); + RETURN_FALSE; + } else { + string.no_encoding = no_encoding; + } + } + + ret = mbfl_ja_jp_hantozen(&string, &result, opt); + if (ret != NULL) { + RETVAL_STRINGL(ret->val, ret->len, 0); /* the string is already strdup()'ed */ + } else { + RETVAL_FALSE; + } +} +/* }}} */ + + + +/* {{{ proto string jstr_convert_variables(string to-encoding, mixed from-encoding, mixed ...) + Convert the string resource in variables to desired encoding */ +PHP_FUNCTION(jstr_convert_variables) +{ + pval ***args, **hash_entry; + HashTable *target_hash; + zend_uchar arg_type; + mbfl_string string, result, *ret; + enum mbfl_no_encoding from_encoding, to_encoding; + mbfl_encoding_detector *identd; + mbfl_buffer_converter *convd; + int n, i, f, argc, *elist, elistsz; + char *name; + JSTRLS_FETCH(); + + argc = ZEND_NUM_ARGS(); + if (argc < 3) { + WRONG_PARAM_COUNT; + } + args = (pval ***)ecalloc(argc, sizeof(pval *)); + if (zend_get_parameters_array_ex(argc, args) == FAILURE) { + efree((void *)args); + WRONG_PARAM_COUNT; + } + + /* new encoding */ + convert_to_string_ex(args[0]); + to_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(args[0])); + if (to_encoding == mbfl_no_encoding_invalid) { + php_error(E_WARNING, "unknown encoding \"%s\"", Z_STRVAL_PP(args[0])); + RETURN_FALSE; + } + + /* initialize string */ + mbfl_string_init(&string); + mbfl_string_init(&result); + from_encoding = JSTRG(current_internal_encoding); + string.no_encoding = from_encoding; + string.no_language = JSTRG(current_language); + + /* pre-conversion encoding */ + elist = NULL; + elistsz = 0; + switch (Z_TYPE_PP(args[1])) { + case IS_ARRAY: + php_jstring_parse_encoding_array(*args[1], &elist, &elistsz, 0); + break; + default: + convert_to_string_ex(args[1]); + php_jstring_parse_encoding_list(Z_STRVAL_PP(args[1]), Z_STRLEN_PP(args[1]), &elist, &elistsz, 0); + break; + } + if (elistsz <= 0) { + from_encoding = mbfl_no_encoding_pass; + } else if (elistsz == 1) { + from_encoding = *elist; + } else { + /* auto detect */ + from_encoding = mbfl_no_encoding_invalid; + identd = mbfl_encoding_detector_new(elist, elistsz); + if (identd != NULL) { + f = 0; + n = 2; + while (n < argc) { + arg_type = Z_TYPE_PP(args[n]); + if (arg_type == IS_ARRAY || arg_type == IS_OBJECT) { + target_hash = HASH_OF(*args[n]); + if (target_hash != NULL) { + zend_hash_internal_pointer_reset(target_hash); + i = zend_hash_num_elements(target_hash); + while (i > 0) { + if (zend_hash_get_current_data(target_hash, (void **) &hash_entry) == FAILURE) { + break; + } + if (Z_TYPE_PP(hash_entry) == IS_STRING) { + string.val = Z_STRVAL_PP(hash_entry); + string.len = Z_STRLEN_PP(hash_entry); + if (mbfl_encoding_detector_feed(identd, &string)) { + f = 1; + break; + } + } + zend_hash_move_forward(target_hash); + i--; + } + } + } else if (arg_type == IS_STRING) { + string.val = Z_STRVAL_PP(args[n]); + string.len = Z_STRLEN_PP(args[n]); + if (mbfl_encoding_detector_feed(identd, &string)) { + f = 1; + } + } + if (f != 0) { + break; + } + n++; + } + from_encoding = mbfl_encoding_detector_judge(identd); + mbfl_encoding_detector_delete(identd); + } + if (from_encoding == mbfl_no_encoding_invalid) { + php_error(E_WARNING, "Unable to detect encoding in jstr_convert_variables()"); + from_encoding = mbfl_no_encoding_pass; + } + } + if (elist != NULL) { + efree((void *)elist); + } + /* create converter */ + convd = NULL; + if (from_encoding != mbfl_no_encoding_pass) { + convd = mbfl_buffer_converter_new(from_encoding, to_encoding, 0); + if (convd == NULL) { + php_error(E_WARNING, "Unable to create converter in jstr_convert_variables()"); + RETURN_FALSE; + } + mbfl_buffer_converter_illegal_mode(convd, JSTRG(current_filter_illegal_mode)); + mbfl_buffer_converter_illegal_substchar(convd, JSTRG(current_filter_illegal_substchar)); + } + + /* convert */ + if (convd != NULL) { + n = 2; + while (n < argc) { + if (ParameterPassedByReference(ht, n + 1)) { + arg_type = Z_TYPE_PP(args[n]); + if (arg_type == IS_ARRAY || arg_type == IS_OBJECT) { + target_hash = HASH_OF(*args[n]); + if (target_hash) { + zend_hash_internal_pointer_reset(target_hash); + i = zend_hash_num_elements(target_hash); + while (i > 0) { + if (zend_hash_get_current_data(target_hash, (void **) &hash_entry) == FAILURE) { + break; + } + if (Z_TYPE_PP(hash_entry) == IS_STRING) { + string.val = Z_STRVAL_PP(hash_entry); + string.len = Z_STRLEN_PP(hash_entry); + ret = mbfl_buffer_converter_feed_result(convd, &string, &result); + if (ret != NULL) { + STR_FREE(Z_STRVAL_PP(hash_entry)); + Z_STRVAL_PP(hash_entry) = ret->val; + Z_STRLEN_PP(hash_entry) = ret->len; + } + } + zend_hash_move_forward(target_hash); + i--; + } + } + } else if (arg_type == IS_STRING) { + string.val = Z_STRVAL_PP(args[n]); + string.len = Z_STRLEN_PP(args[n]); + ret = mbfl_buffer_converter_feed_result(convd, &string, &result); + if (ret != NULL) { + STR_FREE(Z_STRVAL_PP(args[n])); + Z_STRVAL_PP(args[n]) = ret->val; + Z_STRLEN_PP(args[n]) = ret->len; + } + } + } else { + php_error(E_WARNING, "argument %d not passed by reference", n + 1); + } + n++; + } + } + + mbfl_buffer_converter_delete(convd); + efree((void *)args); + + name = (char *)mbfl_no_encoding2name(from_encoding); + if (name != NULL) { + RETURN_STRING(name, 1); + } else { + RETURN_FALSE; + } +} +/* }}} */ + + +/* HTML numeric entity */ +static void +php_jstr_numericentity_exec(INTERNAL_FUNCTION_PARAMETERS, int type) +{ + pval **arg1, **arg2, **arg3, **hash_entry; + HashTable *target_hash; + int argc, i, *convmap, *mapelm, mapsize; + mbfl_string string, result, *ret; + enum mbfl_no_encoding no_encoding; + JSTRLS_FETCH(); + + argc = ZEND_NUM_ARGS(); + if ((argc == 2 && zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) || + (argc == 3 && zend_get_parameters_ex(3, &arg1, &arg2, &arg3) == FAILURE) || + argc < 2 || argc > 3) { + WRONG_PARAM_COUNT; + } + + convert_to_string_ex(arg1); + mbfl_string_init(&string); + string.no_language = JSTRG(current_language); + string.no_encoding = JSTRG(current_internal_encoding); + string.val = Z_STRVAL_PP(arg1); + string.len = Z_STRLEN_PP(arg1); + + /* encoding */ + if (argc == 3) { + convert_to_string_ex(arg3); + no_encoding = mbfl_name2no_encoding(Z_STRVAL_PP(arg3)); + if (no_encoding == mbfl_no_encoding_invalid) { + php_error(E_WARNING, "unknown encoding \"%s\"", Z_STRVAL_PP(arg3)); + RETURN_FALSE; + } else { + string.no_encoding = no_encoding; + } + } + + /* conversion map */ + convmap = NULL; + if (Z_TYPE_PP(arg2) == IS_ARRAY){ + target_hash = (*arg2)->value.ht; + zend_hash_internal_pointer_reset(target_hash); + i = zend_hash_num_elements(target_hash); + if (i > 0) { + convmap = (int *)emalloc(i*sizeof(int)); + if (convmap != NULL) { + mapelm = convmap; + mapsize = 0; + while (i > 0) { + if (zend_hash_get_current_data(target_hash, (void **) &hash_entry) == FAILURE) { + break; + } + convert_to_long_ex(hash_entry); + *mapelm++ = Z_LVAL_PP(hash_entry); + mapsize++; + i--; + zend_hash_move_forward(target_hash); + } + } + } + } + if (convmap == NULL) { + RETURN_FALSE; + } + mapsize /= 4; + + ret = mbfl_html_numeric_entity(&string, &result, convmap, mapsize, type); + if (ret != NULL) { + RETVAL_STRINGL(ret->val, ret->len, 0); + } else { + RETVAL_FALSE; + } + efree((void *)convmap); +} + +/* {{{ proto string jstr_encode_numericentity(string string, array convmap [, string encoding]) + Convert specified characters to HTML numeric entities */ +PHP_FUNCTION(jstr_encode_numericentity) +{ + php_jstr_numericentity_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); +} +/* }}} */ + + +/* {{{ proto string jstr_decode_numericentity(string string, array convmap [, string encoding]) + Convert HTML numeric entities to character code */ +PHP_FUNCTION(jstr_decode_numericentity) +{ + php_jstr_numericentity_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); +} +/* }}} */ + + + +#if HAVE_SENDMAIL +/* {{{ proto int jstr_send_mail(string to, string subject, string message [, string additional_headers]) + Send an email message with MIME scheme */ +PHP_FUNCTION(jstr_send_mail) +{ + int argc, n; + pval **argv[4]; + char *to=NULL, *message=NULL, *headers=NULL, *subject=NULL; + char *message_buf=NULL, *subject_buf=NULL, *p; + mbfl_string orig_str, conv_str; + mbfl_string *pstr; /* pointer to mbfl string for return value */ + enum mbfl_no_encoding + tran_cs, /* transfar text charset */ + head_enc, /* header transfar encoding */ + body_enc; /* body transfar encoding */ + mbfl_memory_device device; /* automatic allocateable buffer for additional header */ + int err = 0; + JSTRLS_FETCH(); + + /* initialize */ + mbfl_memory_device_init(&device, 0, 0); + mbfl_string_init(&orig_str); + mbfl_string_init(&conv_str); + + /* character-set, transfer-encoding */ + tran_cs = mbfl_no_encoding_utf8; + head_enc = mbfl_no_encoding_base64; + body_enc = mbfl_no_encoding_base64; + switch (JSTRG(current_language)) { + case mbfl_no_language_japanese: + tran_cs = mbfl_no_encoding_2022jp; + body_enc = mbfl_no_encoding_7bit; + break; + case mbfl_no_language_english: + tran_cs = mbfl_no_encoding_8859_1; + head_enc = mbfl_no_encoding_qprint; + body_enc = mbfl_no_encoding_qprint; + break; + } + + argc = ZEND_NUM_ARGS(); + if (argc < 3 || argc > 4 || zend_get_parameters_array_ex(argc, argv) == FAILURE) { + WRONG_PARAM_COUNT; + } + + /* To: */ + convert_to_string_ex(argv[0]); + if (Z_STRVAL_PP(argv[0])) { + to = Z_STRVAL_PP(argv[0]); + } else { + php_error(E_WARNING, "No to field in jstr_send_mail()"); + err = 1; + } + + /* Subject: */ + convert_to_string_ex(argv[1]); + if (Z_STRVAL_PP(argv[1])) { + orig_str.no_language = JSTRG(current_language); + orig_str.val = Z_STRVAL_PP(argv[1]); + orig_str.len = Z_STRLEN_PP(argv[1]); + orig_str.no_encoding = mbfl_identify_encoding_no(&orig_str, JSTRG(current_detect_order_list), JSTRG(current_detect_order_list_size)); + if(orig_str.no_encoding == mbfl_no_encoding_invalid) { + orig_str.no_encoding = JSTRG(current_internal_encoding); + } + pstr = mbfl_mime_header_encode(&orig_str, &conv_str, tran_cs, head_enc, "\n", sizeof("Subject: [PHP-jp nnnnnnnn]")); + if (pstr != NULL) { + subject_buf = subject = pstr->val; + } else { + subject = Z_STRVAL_PP(argv[1]); + } + } else { + php_error(E_WARNING, "No subject field in jstr_send_mail()"); + err = 1; + } + + /* message body */ + convert_to_string_ex(argv[2]); + if (Z_STRVAL_PP(argv[2])) { + orig_str.no_language = JSTRG(current_language); + orig_str.val = Z_STRVAL_PP(argv[2]); + orig_str.len = Z_STRLEN_PP(argv[2]); + orig_str.no_encoding = mbfl_identify_encoding_no(&orig_str, JSTRG(current_detect_order_list), JSTRG(current_detect_order_list_size)); + if(orig_str.no_encoding == mbfl_no_encoding_invalid) { + orig_str.no_encoding = JSTRG(current_internal_encoding); + } + pstr = mbfl_convert_encoding(&orig_str, &conv_str, tran_cs); + if (pstr != NULL) { + message_buf = message = pstr->val; + } else { + message = Z_STRVAL_PP(argv[2]); + } + } else { + /* this is not really an error, so it is allowed. */ + php_error(E_WARNING, "No message string in jstr_send_mail()"); + message = NULL; + } + + /* other headers */ +#define PHP_JSTR_MAIL_MIME_HEADER1 "Mime-Version: 1.0\nContent-Type: text/plain" +#define PHP_JSTR_MAIL_MIME_HEADER2 "; charset=" +#define PHP_JSTR_MAIL_MIME_HEADER3 "\nContent-Transfer-Encoding: " + if (argc == 4) { + convert_to_string_ex(argv[3]); + p = Z_STRVAL_PP(argv[3]); + n = Z_STRLEN_PP(argv[3]); + mbfl_memory_device_strncat(&device, p, n); + if (p[n - 1] != '\n') { + mbfl_memory_device_strncat(&device, "\n", 1); + } + } + mbfl_memory_device_strncat(&device, PHP_JSTR_MAIL_MIME_HEADER1, sizeof(PHP_JSTR_MAIL_MIME_HEADER1) - 1); + p = (char *)mbfl_no2preferred_mime_name(tran_cs); + if (p != NULL) { + mbfl_memory_device_strncat(&device, PHP_JSTR_MAIL_MIME_HEADER2, sizeof(PHP_JSTR_MAIL_MIME_HEADER2) - 1); + mbfl_memory_device_strcat(&device, p); + } + mbfl_memory_device_strncat(&device, PHP_JSTR_MAIL_MIME_HEADER3, sizeof(PHP_JSTR_MAIL_MIME_HEADER3) - 1); + p = (char *)mbfl_no2preferred_mime_name(body_enc); + if (p == NULL) { + p = "7bit"; + } + mbfl_memory_device_strcat(&device, p); + mbfl_memory_device_output('\0', &device); + headers = device.buffer; + + if (!err && php_mail(to, subject, message, headers, NULL)){ + RETVAL_TRUE; + } else { + RETVAL_FALSE; + } + + if (subject_buf) { + efree((void *)subject_buf); + } + if (message_buf) { + efree((void *)message_buf); + } + mbfl_memory_device_clear(&device); +} +/* }}} */ + +#else /* HAVE_SENDMAIL */ + +PHP_FUNCTION(jstr_send_mail) +{ + RETURN_FALSE; +} + +#endif /* HAVE_SENDMAIL */ + +#endif /* HAVE_JSTRING */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ |