Archive for August 2005

Wrong Encoding? Whose Fault

早在 2004 年,Tim Bray, Nick BradburyMark Pilgrim 这几位大牛就有过一场著名的口水战,围绕着客户端是否应该接受不 valid 的 XML (XHTML) 而展开,这场口水战以 Mark Pilgrim 的一篇堪称经典的 Thought Experiment 而告结束。Mark 举的一个例子就是页面本来是完全 valid 的,但别人发来了一个 trackback,其中包含了非法的字符,导致整个页面都无法通过校验。

时至今日,一年半过去了,乱码的 trackback 仍然随处可见,我们的 blog 工具版本号一升再升,难道就是解决不了这个问题?

为什么要解决这个问题?

有人会问,为什么要解决这种问题呢?人人都用 UTF-8 不就好了么?没错,在一个理想的世界里,UTF-8 解决了一切问题。问题在于,在一个理想的世界里,M$ 不是坏蛋,IE 还支持 CSS 3 呢!所以我们不能依靠这种白日梦。踏实一点来看,我们现在生活的世界情况是这样的:Apache 占据了大部分的市场,PHP 和 Perl 是两种主要的 Web 脚本语言——尤其对 Blog 而言,MySQL 是大部分开源 Web 程序使用的数据库,可是主机服务上还往往不如人意,大部分的用户不能自如的指定自己 Blog 使用的字符编码,转换 MySQL 存储数据的编码也不是天天没事就能转来转去玩儿的。

这个环境,说明我们应该对他人的页面使用的编码宽容一些。

这个问题理应如何解决

Trackback 不是一个标准,更没有标准化组织进行维护,它只是 MovableType 中发明的一种格式,最权威的说明,就是这篇 TrackBack Technical Specification。而这个规范中对编码唯一的说明是:

The client SHOULD include the character encoding of the content being sent (title, excerpt, and weblog name) in the charset attribute of the Content-Type header.

例如:

POST http://www.example.com/trackback/5
Content-Type: application/x-www-form-urlencoded; charset=utf-8

但接收这个 trackback 的那一方如何获取这个 charset 的值呢?如果在 PHP 中,唯一的方法是用 getallheaders() 函数,但这是在“PHP 作为 Apache 模块安装时才可使用”——事实上许多主机提供商是以 CGI 方式安装 PHP 的。

所以此路不通,我们应该对 Trackback 的协议进行扩展,在 POST 的数据中添加关于字符编码的一项,WordPress 就是以这种方式来实现的,让我们先打开 wp-trackback.php,这是接收 trackback 用的:

$charset   = $_POST['charset'];

if ($charset)
    $charset = strtoupper( trim($charset) );
else
    $charset = ‘ASCII, UTF-8, ISO-8859-1, JIS, EUC-JP, SJIS’;

if ( function_exists(’mb_convert_encoding’) ) {
    $title = mb_convert_encoding($title, 
    get_settings(’blog_charset’), $charset);
    …

上面的代码说明,WP 会从 POST 数据的 charset 一列中取得 trackback 发送者使用的字符编码,如果找不到就使用一套预设的编码 (从这个预设的编码我们可以肯定,90% 的可能是有个日本人给 WordPress 官方报告了 trackback 错误的问题,所以它们头痛医头,只加上了三个日文编码),然后使用 mb_convert_encoding 函数把这个编码转换为 blog 当前使用的编码。

让我们注意三点:

  1. 每个 PHP 安装不一定都启用了 mbstring 模块,也就是说,不一定能进行这个转换,例如,我自己的电脑上安装的 PHP 5,默认就没有打开这个模块。
  2. 当给出一列来源编码时,转换函数以一种猜测的方式来尝试转换 (我在 Planet 的 patch 中描述了这种转换的原理),但这种猜测未必是对的,例如,Big-5 的编码和 GB2312 的编码有部分是重合的,此时无论把 Big-5 列在前还是 GB2312 列在前,都无法同时正确解码这两种编码的文档。
  3. 我们有理由相信这是 WP 私自作出的扩展,MT 不知道这一点 (我手头没有 MT 的代码,使用 MT 的朋友若有兴趣,请帮忙查查)。

WP 糟糕在哪里和我们如何改进

WP 的问题是,它使用 POST 数据中的 charset 一栏来分辨编码,但它自己发送的 trackback 中,不包含这一栏 (trackback() 函数在 wp-includes/functions.php 中),我必须承认我搞不懂这是为什么。

有了上面的解释,我们很容易提出下列的改进:

  1. 提出更改 Trackback 的规范,增加 charset 这一项。
  2. 建议 WP 和 MT 都在发送 Trackback 时,包含这一项。
  3. 建议 WP 和 MT 在发送 Trackback 时,先转换成 UTF-8 再发送。

CSS-based Drop Shadow

又一个基于 CSS 的阴影效果,这次来自 6A Pronet。

IE Reserved ID?

IE 有保留的 HTML id 值Jason 在编辑 ALA 的一篇文章时发现这个问题,Eric Meyer 作了进一步的研究。

防止跨站攻击

Matt 在讨论如何防止跨站脚本攻击的问题,有人给出了 Chris Shiflett 的一篇文章: Foiling Cross-Site Attacks

说说 TeX 的字体 (1)

“TeX fonts are mess…”Ulrik Vieth 和 Taco Hoekwater 在 Euro TeX’99 的 presentation 中如是说。看到这行话的时候,Thunderbird 告诉我从 context 邮件列表发来了新邮件,正好是 Taco 回复我的一封,此时我正被郁闷的 afm2tfm 抓狂着。

或许生而迟钝,大概花了三四天的时间,我才把 TeX 字体的基本原理理清一个思路,原因很简单,没有哪篇文档愿意从头到尾说清楚,它们都只愿意把一小部分的内容说出来,而我的感觉正如刚刚打开了四十二章经的封皮,所不同之处只在于我不打算去找满清龙脉,只希望把 TeX 的字体从安装、到使用,直到最后生成一份可打印的文档这整个过程了解清楚。

当然下面要说的也只是一个简化以后的细节,我这里一不涉及中文的使用,二不涉及 PDF,三不涉及 plain TeX 和 LaTeX 以外的格式。但只要我涉及的部分,就尽量不删减任何过程。

下面的叙述中,我尽量给出一些可以实践的例子,当你发现某处你很希望实践,而我又没有给出例子,那你可以肯定一点:此文的作者确实是不懂这个。

字体是怎么来的

字体是怎么来的?一般而言,TeX 的字体是用 MetaFont 设计出来的,用 MetaFont 的语言描写曲线和点划,这些描述保存在 .mf 文件中,通过 MetaFont 生成 GF 格式,GF 即 Generic Font 的缩写。尔后你通过一个叫做 gftopk 的工具,生成一种叫做 PK 的格式 (packed font),这种 PK 字体是基于 MetaFont 的传统设计方式最终嵌入文档的字体。

为什么要先生成 gf 再转换成 pk?其实这两种格式都是位图 (bitmap) 格式而非矢量格式,也就是说没有优劣的区别,如果你非要问为什么,我也只能说是历史原因。

但这只是字形 (glyph) 文件,也就是单个的字符长得什么样子,那几个字符放在一起,它们的间距如何调整,而众所周知拉丁字母有个基线 (baseline),字符的基线若不对齐当然是很难看的,我们又在哪里指定这个基线呢?在字距 (metric) 文件中。

TeX 使用的字距文件,有两种格式,一种是二进制的,叫做 TFM (TeX font metric) 文件,另一种是我们可读的,叫做 PL (Property List ) 文件。两者之间可以通过 tftopl 和 pltotf 相互转换。系统地说,metric 文件描述的是每个字符的宽、高、深和斜体修正 (不明白什么是斜体修正?看 The TeXBook 第四章去),以及两个字符之间的间距调整 (kerning) 和连字 (ligature) (这两个概念先前我在 blog 上都提到过,请自行搜索)。

好,下面让我们来实践一下 (以 MikTeX 为例,其他发行版请自行调整):

$ kpsewhich ptmr8r.tfm (先找个 tfm 文件出来)
C:/CTeX/texmf/fonts/tfm/adobe/times/ptmr8r.tfm
$ tftopl C:/CTeX/texmf/fonts/tfm/adobe/times/ptmr8r.tfm ptmr8r.pl
.... (一堆输出信息,注意,编号是八进制的)
$ dir
....
2005-08-30  02:54            61,002 ptmr8r.pl
$ vim ptmr8r.pl (让我们找个文本编辑器打开这个文件)
...
(CHARACTER O 275
   (CHARWD R 0.75)
   (CHARHT R 0.677991)
   (CHARDP R 0.007001)
   )

上边就是一个编码 (我们以后再谈编码的问题) 为 275 (八进制) 的字符的宽度、高度和深度了。

事实上 TeX 排版中是不需要用到字形 (glyph) 文件的,也就是说,TeX 不需要知道这个字符的轮廓是什么样的,只需要知道给它留多大的空间就行了,所以你用 TeX 生成的 DVI 文件里只包含了 TFM 文件的信息,至于你预览 DVI 时看到的,其实是 DVI 阅读器提供的功能,它能够根据 TFM 的信息找到应该使用的 PK 文件,将它们载入。还是让我们实验一下,做个最简单的 TeX 文件 (下边 $* 开头的都是用户的输入,括号内的不用输入):

$ tex (打开 tex 控制台)
This is TeX, Version 3.141592 (MiKTeX 2.4)
**\relax (先放松一下)
*\font\myfont=cmr10 at 12pt (定义一个字体)
*\myfont Hello, World! (用这个字体输入一段文本)
*\end (完成)
[1]
Output written on texput.dvi (1 page, 272 bytes).
Transcript written on texput.log.

搞定,让我们看看输出的文件:

$ yap texput.dvi

如果你有兴趣,还可以看看 YAP 的菜单中 File->Document Properties 提供的信息,里面描述了如何从一个 TFM 的名称映射到一个 PK 文件的。

OK,这就是 TeX 使用字体的传统过程,没有 PostScript,没有 PDF,没有 Adobe,有的只是 good old days 的老工具。谢谢大家的支持,今天我们就讲到这里,请关注我们下次的连载。

也谈网页设计学习历程

看了 hlb 兄的《網頁設計學習路》,也想回忆一下。

我是 97 年开始接触网络,98 年的时候,应该是初二,用一台 Pentium 120 上面装的 Word 97 写了第一个网页,把剪贴画插上几幅,随手打上点文字,虽然粗陋,但也自得其乐。而后才开始用 FrontPage Express,这是 IE 4 套件中的一员,特别简单的所见即所得工具,而后在偶然买的一张 D 版盘中找到 FrontPage 98,才发现网页设计别有天地,不过那时也只是套用几个预设的主题,信手改一改。其间还用过 Dreamweaver 2,特别有印象的是这个东西设计表格要比 FrontPage 方便。

到此时其实所有的创作都还是在自己的电脑上做的,根本没机会发布到网上,直到高一我才有机会真正把自己做的东西贴出来 (最早用的是网易提供的免费空间,而 jjgod 这个 id 则是在申请 163 邮箱时起的),当时喜欢搞 mud,也做过几个和 mud 有关的主页,多是用 FrontPage 2000,慢慢的摸索出用 CSS 来定制字体,用表格来布局页面,嗯,当时我不知道做这玩意儿还需要看书,也从未在网上找过相关的资料。

再然后接触了 ASP、PHP,觉得动态网页才是发展的方向,使用 ASP 的网站我搭过几个,但因为不喜欢 VBScript 的语法,始终未曾入门。而 PHP 则是在高二高三亲手写过几个网站之后才比较熟悉。

高考之后的暑假,百无聊赖之下逛到 hlb 兄的主页,在他的指点下搭建 Tavi 的 wiki,也跟着了解了许多 Web 设计的新概念。不过也只是了解而已,未曾自己参与,直到去年年初,onestab 兄的网站上线,看他将 hlb 兄的许多译作介绍到大陆,才想到自己未尝不可翻译一些。

于是便有了《为何使用表格排版是不明智的》,这是我翻译得最认真的作品,记得年前几天,搓着冻红的双手,把英文的内容 COPY 到 UltraEdit 中,一段段翻译,然后一段段 COPY 回原来的网页中,翻译完成后寄给 onestab 审校……这份翻译稿直到 onestab 兄从原作者哪里得到所有插图上美国俚语的解释,逐条翻译,再由我把原来的图片改为中文才正式大功告成。

此后我才开始认真地读 A List Apart, mezzoblue 这些网站,搭建 Web4C,着手翻译或介绍一些我觉得有意思的东西,一直到现在。不过时至今日,原来创办的思路也有了不小的改观,现在的 Web4C,或应称作 Facts & Options about Web standards,我努力多写一些原创的东西,而不仅限于翻译。

回顾完昨天,大概该写点展望,我一直觉得甚为遗憾的是,WSDN 的 wiki 未能发展起来,我们这里中文的资料还是零落在各个 blog 中,一个真正全面的,大家都可以参与的知识库,理应是有吸引力的,为何迟迟未能出现呢?

今日购书如下

  1. Learning Python, 2nd Edition, 东南大学出版社影印
  2. Modern Operating System, Tanenbaum, 机械工业出的中文版, 郁闷,找不到影印版
  3. Linux Programming by Example, Arnold Robbins, 机械工业影印
  4. Advanced Compiler Design Implementaion, Muchnick, 机械工业影印

本来还想买龙书的,居然中文版和影印版都找不到,打倒广州购书中心~

顺便补全了上次在搜狐买的一套《基地》里缺的一本,广州这里科幻实在太少了,标着科幻的架上全是侦探、恐怖和中式奇幻,正经科幻小说没几本。

讨论的层次

刚刚看见这篇“不用 IE 用什么”,说实在,这类的话见得实在很多了,本来无须专门拿出来说一番,但想想这种胡搅蛮缠的东西多了也有害风气,就简单说说我的看法。

浏览器的口水战,哪里都不缺,我偶尔也逛逛水木社区 (newsoftware 版)、mozcn 的论坛和 Maxthon 的论坛,再加上各个 blog 里看到的,从我个人的态度来说,有点重技术而轻说教的偏见,下面的议论也以此而发,请别见怪。

  • 这第一层次是只知 IE,不知其他浏览器,这类人很多,不过一般还没能力参加口水战。
  • 第二层次是用用 Maxthon、GoSurf 和 GreenBrowser 等 IE 内核的浏览器,或者下个 Firefox 装插件装得开心,第二层次的两类人均自觉得手上有了 Tab-Browsing、AdBlock、Mouse Gesture 等武器,比只知 IE 的猪头强了不少。
  • 第三层次是知道 Maxthon 等等其实用的都是 IE 的内核,于是纷纷作义愤状,说用别人内核的东西还敢来分一杯羹说三道四?
  • 第四层次是能随口扯出些论据的家伙,比如 Firefox 其实不安全啦、Firefox 有内存泄露啦、Firefox 速度慢啦等等。同一层次的还有一批以 Web 标准为幌子,侃侃而谈 IE 如何不标准,Firefox 如何符合标准,其实他本人多半未曾做过 Web 设计。
  • 第五层次,做过点 Web 开发,也了解一些统计的结果,能够引用比较真实而权威的评测资料,进行讨论,这些人的话就比较可信了。
  • 第六层次是我最为佩服的,能够亲自开发 Firefox 的扩展和补丁,或者亲自用 IE 的控件做过浏览器或者扩展开发的,以亲身经历,举出实际评测的例子,有理有节,即便我的看法与之不同,我也会很敬佩他。

口水战的主力军以三四层次者为多,他们说的东西造成的误解也最多,这里我不妨试着澄清一二:

用别人的内核就没有发言权吗?

首先,“内核”这个词,在这里指的是渲染引擎,而渲染引擎这个东西,虽然在浏览器软件中最为重要,但远非全部,比如说我们知道如下事实:

  1. Firefox 用的渲染引擎是 Gecko,尽管 Firefox 是隶属于 Mozilla 组织的一个项目,算作官方开发的浏览器,但也有其他的软件,不是 Mozilla 组织 (或者其下属) 开发的,也用到了 Gecko 引擎,比如 GNOME 默认的浏览器 Epiphany,所见即所得的 Web 开发工具 Nvu 等。
  2. Maxthon 等软件用的是 IE/Win 的渲染引擎 Trident,当然,纯粹的渲染引擎我们这些开发者是接触不到的,不像 Gecko 那样可以剥离出代码来,Microsoft 给 IE 作了 COM 的包装,提供了许多方便开发者的 API,但是,图形用户界面、程序配置等重要的功能,IE 的控件是没有提供的,Maxthon 等软件都是自己开发这些功能的。
  3. 开发软件的图形用户界面很花时间,设计出简洁实用的界面也很不容易。
  4. 软件开发中调用别人设计好的库相当普遍,比如 GTK+ 2.8 是基于 cairo 图形库的,cairo 的文本渲染又依赖于 FreeType 库,GTK+ 的文本布局要用到 pango 库,这些库在软件的开发中都发挥了重要作用,但没人会说那些软件作者本身的努力可以忽略不计。

描述上面的事实时,我努力避免“如果哪个不服气,自己做一个去”这样的话,但有的时候,的确是不亲力亲为无以了解软件开发的困难。

在此,我个人的一点希望是,这个 Blog 的读者尽量多做一些具体技术的讨论,少做传道式的宣传,浏览器不是扯皮扯出来的,是开发人员一行行代码写出来的,体谅这点,或许能让我们对 Web 的了解更进一步。

Recent Stuffs

下面是最近关注的东东:

  • A List Apart 重构!原来的域名要等 DNS 生效以后才会启用,现在可以用 TextDrive 的地址访问
  • Wikiwyg,wiki 上方便的所见即所得编辑器,看这个 demo
  • Cairo 的 Win32 开发包,你可能需要一些 GTK+ Win32 的GnuWin32 提供的库才能编译。(用到的库包括: fontconfig, freetype, libpng, expat 等)。
  • Wordpress.COM 能做什么?这个只有一个 Invitation 的东西……

Web Accessibility Toolbar

Accessible Information Solutions 有很多关于网站亲和力的资源,其中 Web Accessibility ToolbarColour Contrast Analyser 就是很方便的两个工具。