用 [Gaim] 上 IRC, 在 #debian-zh@freenode.net 看到了一个[url=http://zh.wikipedia.org/wiki/标点符号][中文链接][/url], 然后就右键点击这个链接, 选择 "Open Link in Brower", 那么不管在 Firefox 还是 IE 中都显示的是 "鏍囩偣绗﹀彿", 当然在 wikipedia 上是找不到了的. 第一感觉就是字符个数不对, 原来是四个, 现在是六个, 估计跟 UTF-8 有关系. 在 Gaim 中使用的是 UTF-8, 每个中文字是三个字节, GBK/GB2312 每个中文是两个字节, 这样字节数就对上了.
首先需要在 Firefox 中地址栏输入"about:config", filter 中输入 "url", 然后双击"network.standard-url.encode-utf8" 把缺省的 false 改成 true, 这样在命令行中 "firefox.exe http://zh.wikipedia.org/wiki/标点符号" 以及在地址栏中直接输入带有中文的 URL 也没有问题的.
然后在 Emacs 中做测试, "标点符号"的 UTF-8 编码是 E6A087 E782B9 E7ACA6 E58FB7, 每两个字节拆开, 在 hexl-mode 下编辑一个文件, 就成了 E6A0 87E7 82B9 E7AC A6E5 8FB7, 以 RAW 保存, 用其他文本工具打开(比如 notepad), 显示的就是 "鏍囩偣绗﹀彿". 说明猜想是正确的.
那么原因是什么呢? 在 Gaim 中, 当点击 "Open Link in Brower" 时候, 调用过程如下:
-
src/gtkimhtml.c:1567: tag_event()
-
src/gtkimhtml.c:1488: url_open() /* 触发了一个 signal URL_CLICKED "url_clicked" */
-
-
src/gtkutils.c:95: gaim_setup_imhtml() /* 连接到 signal "url_clicked" */
-
src/gtkutils.c:77: url_clicked_cb()
-
src/gtkutils.c:69: url_clicked_idle_cb()
-
src/notify.c:401: gaim_notify_uri()
-
src/gtknotify.c:1084: GaimNotifyUiOps ops; /* 定义了 notify_uri 为 gaim_gtk_notify_uri() */
-
src/gtknotify.c:1069: gaim_gtk_notify_uri()
-
src/w32def.c:361: wgaim_notify_uri() /* 最后调用了 ShellExecuteEx */
先看看非 Windows 系统上是怎么处理的, 同样是在 gaim_gtk_notify_uri() 中, 首先就对 URI 进行了转义处理, 也就是转成了 "%E6%A0%87%E7%82%B9%E7%AC%A6%E5%8F%B7", 这样直接用 Firefox, Opera 或者其他浏览器是没有问题的.
对于 Windows 来讲, 对于一个 URI 直接调用 ShellExecuteEx 需要在注册表中查找此协议的处理命令, 为 HKEY_LOCAL_MACHINE\SOFTWARE\Classes\HTTP\shell\open\command, 如果设置 Firefox 为缺省浏览器的话, 此值为 FIREFOX.EXE -url "%1". 这样就把 UTF-8 编码的 URI 直接传递给了 Firefox. 至于 Firefox 里面怎么处理, 没看代码不太清楚, 但是在命令行直接输入却没有问题, 一下是猜想, 说明里面有一个转换(GBK/GB2312->UTF-8), 对于 UTF-8 编码的 URI, 把它当作了 GBK/GB2312 编码, 然后要转换成 UTF-8, 发到服务器以后显示出来就是我们所看到的"鏍囩偣绗﹀彿".
此想法可以通过编辑一个批处理文件来验证, 以下文件以 UTF-8 保存为 test.bat:
-
firefox.exe http://zh.wikipedia.org/wiki/标点符号
运行 test.bat 可以看到 cmd 的窗口中显示的就是类似的乱码, 也更确定了是 UTF-8 编码被当作成了 GBK/GB2312.
但是问题该怎么解决呢? 最好的办法是在 Gaim 的 wgaim_notify_uri() 之前仍然进行转义, 这样在任何情况下都不会出错.




RFC 1738
RFC 1738: Uniform Resource Locators (URL) 描述了 URL 具体应该是什么样.
问题解决
参照了 [Sylpheed] 中
utils.c : execute_open_file, 对win32dep.c : wgaim_notify_uri进行了同样的改写, 如下:已经在 [Gaim Tracker] 上提交了 patch, 看有没有人处理, 在我这里没什么问题. 我估计在 Linux 下, 非 UTF-8 的 locale 下也仍然有这个问题, 可惜没有测试环境来测试一下.
已经提交
此 Patch 在昨天晚上由 Daniel 'datallah' Atallah 提交.
Post new comment