From e33ec61f9c1baa73bfe1b03b8c48a824ab2a867e Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Wed, 14 Dec 2016 02:51:29 +0100 Subject: [PATCH] Care about intput and output encoding, as per default encoding RFC If PHP CLI is used with programs with no Unicode support, the default PHP console codepage might cause backward incompatible behaviors. This is solved with this patch by separating the handling of I/O codepage. As per https://wiki.php.net/rfc/default_encoding input_encodnig and output_encoding are centralized INI settings, so they're used for the purpose of adjusting the codepage. This gives user the ability to use UTF-8 internally, while letting the system API to convert the output to a compatible codepage. This also might solve the font issues on systems without good true type support. Note, that there no change to the default behavior - if input and output encoding are not set, which is the default case, the default charset applies to both console input and output. The patch is just a compilment to the backward compatibility, not more and not less. --- main/main.c | 6 +++++ win32/codepage.c | 57 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 10 deletions(-) diff --git a/main/main.c b/main/main.c index dd69734aeab..8cc4a9863ea 100644 --- a/main/main.c +++ b/main/main.c @@ -435,6 +435,9 @@ static PHP_INI_MH(OnUpdateInputEncoding) { if (new_value) { OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); +#ifdef PHP_WIN32 + php_win32_cp_do_update(NULL); +#endif } return SUCCESS; } @@ -446,6 +449,9 @@ static PHP_INI_MH(OnUpdateOutputEncoding) { if (new_value) { OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); +#ifdef PHP_WIN32 + php_win32_cp_do_update(NULL); +#endif } return SUCCESS; } diff --git a/win32/codepage.c b/win32/codepage.c index cddd94687de..511e42843c4 100644 --- a/win32/codepage.c +++ b/win32/codepage.c @@ -21,8 +21,12 @@ #include "php.h" #include "SAPI.h" -ZEND_TLS const struct php_win32_cp *cur_cp = NULL; +ZEND_TLS const struct php_win32_cp *cur_cp = NULL; ZEND_TLS const struct php_win32_cp *orig_cp = NULL; +ZEND_TLS const struct php_win32_cp *cur_out_cp = NULL; +ZEND_TLS const struct php_win32_cp *orig_out_cp = NULL; +ZEND_TLS const struct php_win32_cp *cur_in_cp = NULL; +ZEND_TLS const struct php_win32_cp *orig_in_cp = NULL; #include "cp_enc_map.c" @@ -291,7 +295,6 @@ PW32CP const struct php_win32_cp *php_win32_cp_get_by_enc(const char *enc) } if (0 == zend_binary_strcasecmp(enc, enc_len, cp->name, strlen(cp->name))) { - cur_cp = cp; return cp; } @@ -302,7 +305,6 @@ PW32CP const struct php_win32_cp *php_win32_cp_get_by_enc(const char *enc) while (NULL != idx) { if (0 == zend_binary_strcasecmp(enc, enc_len, start, idx - start)) { - cur_cp = cp; return cp; } start = idx + 1; @@ -310,7 +312,6 @@ PW32CP const struct php_win32_cp *php_win32_cp_get_by_enc(const char *enc) } /* Last in the list, or single charset specified. */ if (0 == zend_binary_strcasecmp(enc, enc_len, start, strlen(start))) { - cur_cp = cp; return cp; } } @@ -381,18 +382,54 @@ PW32CP wchar_t *php_win32_cp_env_any_to_w(const char* env) return envw; }/*}}}*/ +static BOOL php_win32_cp_cli_io_setup(void) +{ + if (PG(input_encoding) && PG(input_encoding)[0]) { + cur_in_cp = php_win32_cp_get_by_enc(PG(input_encoding)); + if (!cur_in_cp) { + cur_in_cp = cur_cp; + } + } else { + cur_in_cp = cur_cp; + } + + if (PG(output_encoding) && PG(output_encoding)[0]) { + cur_out_cp = php_win32_cp_get_by_enc(PG(output_encoding)); + if (!cur_out_cp) { + cur_out_cp = cur_cp; + } + } else { + cur_out_cp = cur_cp; + } + + return SetConsoleCP(cur_in_cp->id) && SetConsoleOutputCP(cur_out_cp->id); +} + PW32CP const struct php_win32_cp *php_win32_cp_do_setup(const char *enc) {/*{{{*/ if (!enc) { enc = php_win32_cp_get_enc(); } - if (!strcmp(sapi_module.name, "cli")) { - orig_cp = php_win32_cp_get_by_id(GetConsoleCP()); - } else { + cur_cp = php_win32_cp_get_by_enc(enc); + if (!orig_cp) { orig_cp = php_win32_cp_get_by_id(GetACP()); } - cur_cp = php_win32_cp_get_by_enc(enc); + if (!strcmp(sapi_module.name, "cli")) { + if (!orig_in_cp) { + orig_in_cp = php_win32_cp_get_by_id(GetConsoleCP()); + if (!orig_in_cp) { + orig_in_cp = orig_cp; + } + } + if (!orig_out_cp) { + orig_out_cp = php_win32_cp_get_by_id(GetConsoleOutputCP()); + if (!orig_out_cp) { + orig_out_cp = orig_cp; + } + } + php_win32_cp_cli_io_setup(); + } return cur_cp; }/*}}}*/ @@ -435,7 +472,7 @@ PW32CP const struct php_win32_cp *php_win32_cp_cli_do_setup(DWORD id) return NULL; } - if (SetConsoleOutputCP(cp->id) && SetConsoleCP(cp->id)) { + if (php_win32_cp_cli_io_setup()) { return cp; } @@ -448,7 +485,7 @@ PW32CP const struct php_win32_cp *php_win32_cp_cli_do_restore(DWORD id) id = orig_cp->id; } - if (SetConsoleOutputCP(id) && SetConsoleCP(id)) { + if (SetConsoleCP(orig_in_cp->id) && SetConsoleOutputCP(orig_out_cp->id)) { if (orig_cp) { return orig_cp; } else {