diff options
-rw-r--r-- | Zend/zend.c | 4 | ||||
-rw-r--r-- | Zend/zend_virtual_cwd.c | 14 | ||||
-rw-r--r-- | Zend/zend_virtual_cwd.h | 4 | ||||
-rw-r--r-- | ext/standard/tests/file/windows_mb_path/bug75063_cp1251.phpt | 80 | ||||
-rw-r--r-- | ext/standard/tests/file/windows_mb_path/bug75063_utf8.phpt | 81 | ||||
-rw-r--r-- | main/main.c | 14 |
6 files changed, 195 insertions, 2 deletions
diff --git a/Zend/zend.c b/Zend/zend.c index 0f59704553..6adf73747b 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -717,6 +717,10 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions) / extern zend_php_scanner_globals language_scanner_globals; #endif +#ifdef ZEND_WIN32 + php_win32_cp_set_by_id(65001); +#endif + start_memory_manager(); virtual_cwd_startup(); /* Could use shutdown to free the main cwd but it would just slow it down for CGI */ diff --git a/Zend/zend_virtual_cwd.c b/Zend/zend_virtual_cwd.c index e9ffda7cc3..3e95795b08 100644 --- a/Zend/zend_virtual_cwd.c +++ b/Zend/zend_virtual_cwd.c @@ -389,16 +389,21 @@ static void cwd_globals_dtor(virtual_cwd_globals *cwd_g) /* {{{ */ } /* }}} */ -CWD_API void virtual_cwd_startup(void) /* {{{ */ +void virtual_cwd_main_cwd_init(uint8_t reinit) /* {{{ */ { char cwd[MAXPATHLEN]; char *result; + if (reinit) { + free(main_cwd_state.cwd); + } #ifdef ZEND_WIN32 ZeroMemory(&cwd, sizeof(cwd)); -#endif + result = php_win32_ioutil_getcwd(cwd, sizeof(cwd)); +#else result = getcwd(cwd, sizeof(cwd)); +#endif if (!result) { cwd[0] = '\0'; @@ -411,7 +416,12 @@ CWD_API void virtual_cwd_startup(void) /* {{{ */ } #endif main_cwd_state.cwd = strdup(cwd); +} +/* }}} */ +CWD_API void virtual_cwd_startup(void) /* {{{ */ +{ + virtual_cwd_main_cwd_init(0); #ifdef ZTS ts_allocate_id(&cwd_globals_id, sizeof(virtual_cwd_globals), (ts_allocate_ctor) cwd_globals_ctor, (ts_allocate_dtor) cwd_globals_dtor); #else diff --git a/Zend/zend_virtual_cwd.h b/Zend/zend_virtual_cwd.h index c1b48cfd45..dee87c0a36 100644 --- a/Zend/zend_virtual_cwd.h +++ b/Zend/zend_virtual_cwd.h @@ -238,6 +238,10 @@ CWD_API zend_long realpath_cache_size(void); CWD_API zend_long realpath_cache_max_buckets(void); CWD_API realpath_cache_bucket** realpath_cache_get_buckets(void); +#ifdef CWD_EXPORTS +extern void virtual_cwd_main_cwd_init(uint8_t); +#endif + /* The actual macros to be used in programs using TSRM * If the program defines VIRTUAL_DIR it will use the * virtual_* functions diff --git a/ext/standard/tests/file/windows_mb_path/bug75063_cp1251.phpt b/ext/standard/tests/file/windows_mb_path/bug75063_cp1251.phpt new file mode 100644 index 0000000000..1c890ed53a --- /dev/null +++ b/ext/standard/tests/file/windows_mb_path/bug75063_cp1251.phpt @@ -0,0 +1,80 @@ +--TEST-- +Bug #75063 Many filesystem-related functions do not work with multibyte file names, cp1251 +--SKIPIF-- +<?php +include dirname(__FILE__) . DIRECTORY_SEPARATOR . "util.inc"; + +skip_if_not_win(); +if (getenv("SKIP_SLOW_TESTS")) die("skip slow test"); +skip_if_no_required_exts(); + +?> +--INI-- +default_charset=cp1251 +--FILE-- +<?php + +/* This file is in cp1251. */ + +include dirname(__FILE__) . DIRECTORY_SEPARATOR . "util.inc"; + +$dir_basename = ""; +$prefix = dirname(__FILE__) . DIRECTORY_SEPARATOR . "bug75063-cp1251"; +$d0 = $prefix . DIRECTORY_SEPARATOR . $dir_basename; + +mkdir($prefix); +create_verify_dir($prefix, $dir_basename, 1251); + +var_dump(get_basename_with_cp($d0, 1251, false)); + +$old_cwd = getcwd(); +var_dump(chdir($d0)); + +$code = <<<CODE +<?php + +foreach(["test", ""] as \$fn) { + file_put_contents("\$fn.txt", ""); +} + +var_dump(getcwd()); +if (\$dh = opendir(getcwd())) { + while ((\$file = readdir(\$dh)) !== false) { + if ("." == \$file || ".." == \$file) continue; + var_dump(\$file); + } + closedir(\$dh); +} +CODE; +$code_fn = "code.php"; +file_put_contents($code_fn, $code); + +print(shell_exec(getenv('TEST_PHP_EXECUTABLE') . " -n -d default_charset=cp1251 -f code.php")); + +chdir($old_cwd); + +/* --CLEAN-- section were the right place, but it won't accept default_charset ATM, it seems. */ +$dir_basename = ""; +$prefix = dirname(__FILE__) . DIRECTORY_SEPARATOR . "bug75063-cp1251"; +$d0 = $prefix . DIRECTORY_SEPARATOR . $dir_basename; + +$obj = scandir($d0); +foreach ($obj as $file) { + if ("." == $file || ".." == $file) continue; + unlink($d0 . DIRECTORY_SEPARATOR . $file); +} + +rmdir($d0); +rmdir($prefix); +?> +===DONE=== + +--EXPECTF-- +string(4) "" +bool(true) +string(%d) "%sbug75063-cp1251%e" +string(8) "code.php" +string(8) "test.txt" +string(8) ".txt" +===DONE=== + diff --git a/ext/standard/tests/file/windows_mb_path/bug75063_utf8.phpt b/ext/standard/tests/file/windows_mb_path/bug75063_utf8.phpt new file mode 100644 index 0000000000..b4a59d1afc --- /dev/null +++ b/ext/standard/tests/file/windows_mb_path/bug75063_utf8.phpt @@ -0,0 +1,81 @@ +--TEST-- +Bug #75063 Many filesystem-related functions do not work with multibyte file names, UTF-8 +--SKIPIF-- +<?php +include dirname(__FILE__) . DIRECTORY_SEPARATOR . "util.inc"; + +skip_if_not_win(); +if (getenv("SKIP_SLOW_TESTS")) die("skip slow test"); +skip_if_no_required_exts(); + +?> +--FILE-- +<?php + +/* This file is in UTF-8. */ + +include dirname(__FILE__) . DIRECTORY_SEPARATOR . "util.inc"; + +$dir_basename = "тест"; +$prefix = dirname(__FILE__) . DIRECTORY_SEPARATOR . "bug75063-utf8"; +$d0 = $prefix . DIRECTORY_SEPARATOR . $dir_basename; + +mkdir($prefix); +create_verify_dir($prefix, $dir_basename); + +var_dump(get_basename_with_cp($d0, 65001, false)); + +$old_cwd = getcwd(); +var_dump(chdir($d0)); + +$code = <<<CODE +<?php + +foreach(["test", "таст"] as \$fn) { + file_put_contents("\$fn.txt", ""); +} + +var_dump(getcwd()); +if (\$dh = opendir(getcwd())) { + while ((\$file = readdir(\$dh)) !== false) { + if ("." == \$file || ".." == \$file) continue; + var_dump(\$file); + } + closedir(\$dh); +} +CODE; +$code_fn = "code.php"; +file_put_contents($code_fn, $code); + +print(shell_exec(getenv('TEST_PHP_EXECUTABLE') . " -nf code.php")); + +chdir($old_cwd); + +?> +===DONE=== +--CLEAN-- +<?php +$dir_basename = "тест"; +$prefix = dirname(__FILE__) . DIRECTORY_SEPARATOR . "bug75063-utf8"; +$d0 = $prefix . DIRECTORY_SEPARATOR . $dir_basename; + +$obj = scandir($d0); +foreach ($obj as $file) { + if ("." == $file || ".." == $file) continue; + unlink($d0 . DIRECTORY_SEPARATOR . $file); +} + +rmdir($d0); +rmdir($prefix); + +?> + +--EXPECTF-- +string(8) "тест" +bool(true) +string(%d) "%sbug75063-utf8%eтест" +string(8) "code.php" +string(8) "test.txt" +string(12) "таст.txt" +===DONE=== + diff --git a/main/main.c b/main/main.c index 0b18bbbc6e..3f7047e8e1 100644 --- a/main/main.c +++ b/main/main.c @@ -2230,6 +2230,20 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod /* Register Zend ini entries */ zend_register_standard_ini_entries(); +#ifdef ZEND_WIN32 + /* Until the current ini values was setup, the current cp is 65001. + If the actual ini vaues are different, some stuff needs to be updated. + It concerns at least main_cwd_state and there might be more. As we're + still in the startup phase, lets use the chance and reinit the relevant + item according to the current codepage. Still, if ini_set() is used + later on, a more intelligent way to update such stuff is needed. + Startup/shutdown routines could involve touching globals and thus + can't always be used on demand. */ + if (!php_win32_cp_use_unicode()) { + virtual_cwd_main_cwd_init(1); + } +#endif + /* Disable realpath cache if an open_basedir is set */ if (PG(open_basedir) && *PG(open_basedir)) { CWDG(realpath_cache_size_limit) = 0; |