Appearance
Appearance
Wireshark 所使用的系统和 C 语言 API 提供或接收的文件名、命令行参数、环境变量以及其他字符串可能使用的各种字符编码会相当令人困惑;请参见 “Character Encodings”,了解这些字符串中可能使用的编码。
在 UN*X 系统(Linux、macOS、BSD 系统、Solaris 等)中,Wireshark 当前假定所有此类字符串都以 UTF-8 编码,并且 locale 使用 UTF-8 作为其编码;所有 Wireshark 程序都会在 main routine 早期通过调用 setlocale(LC_ALL, ""),将 C 语言 locale 初始化为默认值。
我目前不知道在所有(尤其是较旧的)*nix 版本上编码转换是否都被正确完成。- UlfLamping
在 Windows 中,大多数系统和 C 语言 API 都有两个变体,其中一个接受或提供当前 “ANSI code page” 中的字符串,另一个接受或提供 UTF-16 编码的 Unicode 字符串。Wireshark 会尽可能尝试使用 UTF-16 变体,并通过 wrapper routines 在 Wireshark 内部使用的 UTF-8 字符串与 API 中使用的 UTF-16 字符串之间进行转换,从而完整支持 Unicode。
所有 Wireshark 程序都会在 main routine 早期通过调用 setlocale(LC_ALL, ".UTF-8"),将 C 语言 locale 初始化为使用 UTF-8。请参见 Microsoft 文档中 Visual C 的 setlocale() routine 的 “UTF-8 Support” 部分。这会使 C runtime support 中所有 routines 的 “ANSI code page” 版本接受并提供以 UTF-8 编码的字符串。
该更改最初是为了修复 bug 16649。
我们不会把 “ANSI code page” 改为 UTF-8(code page 65001),因为这会导致更多 /? 在 Windows 7 上失败;UTF-8 code page 在较旧版本的 Windows 上支持得不好。较新版本的 Windows 10 中的支持相较早期 Windows 版本有所改进。
对于命令行程序,main() 函数会接收当前 “ANSI code page” 中的参数字符串,这意味着,如果当前 “ANSI code page” 不是 UTF-8 code page:
将 C 语言 locale 改为使用 UTF-8 并不会把 argv[] 值改为 UTF-8,因此我们必须自己进行转换。这通过以下方式完成:
这样 main function 就会收到 UTF-8 参数字符串。
对于 GUI 程序,我们使用 Qt。Qt 定义了一个 WinMain() 函数,它是 Windows 上 GUI 程序的 main function,并接收一个当前 “ANSI code page” 中的单个字符串,其中包含命令行参数,形式是一个包含命令行的单个字符串。Qt 的 WinMain() 调用 GetCommandLineW() 获取命令行字符串的 UTF-16 版本,将其传递给 CommandLineToArgvW(),将其解析为 argv[] 风格的 UTF-16 字符串列表,把这些字符串转换为当前 “ANSI code page”,并将参数数量和这些字符串数组传递给 main()。这意味着,诸如 Wireshark 这样的 GUI 程序的 main function 会遇到与诸如 TShark 这样的命令行程序中的 main() 函数相同的问题。
处理方式是让 Wireshark main() 函数调用 GetCommandLineW() 获取参数字符串,将其传递给 CommandLineToArgvW(),将其解析为 argv[] 风格的 UTF-16 字符串列表,把这些字符串转换为 UTF-8,并使用该数组作为参数字符串数组。
值中可能包含非 ASCII 字符的环境变量应使用 g_getenv() 而不是 getenv() 获取,因为 g_getenv() 在 Windows 上会获取环境变量的 UTF-16 值并将其转换为 UTF-8。
(注意:既然我们正在将 C-library locale 设置为使用 UTF-8,这可能不再必要。)
C library 的 _open()、fopen()、_stat() 等 routines 期望 pathnames 使用当前 “ANSI code page”。为了处理 UTF-8 pathnames,我们有诸如 ws_open()、ws_fopen()、ws_stat64() 等 wrappers,它们会将 pathnames 从 UTF-8 转换为 UTF-16,并调用 C library routines 的 “wide character” 版本。
(注意:既然我们正在将 C-library locale 设置为使用 UTF-8,这可能不再必要。)
Imported from https://wiki.wireshark.org/Development/FilenameEncoding on 2020-08-11 23:12:48 UTC