摘要
- RFC 1556 把双向文本显示分成三种责任结构:visual 模式由写信端预排可见顺序,implicit 模式由阅读端算法推导,explicit 模式则靠夹在正文中的控制序列指挥。
- MIME 可以证明非 ASCII 字符被编码和传送,却不能单凭这一点证明收件人看见了作者预期的阅读顺序;字符集、方向模式与渲染上下文必须分别留证。
- 这是一份 1993 年 12 月的 Informational RFC,不是 Internet Standard。后来的 HTML、Unicode 与 UTF-8 邮件仍面对同一层次边界,但不能被写成 RFC 1556 的直系实现史。
归档文件没有坏,句子却换了位置
先不要想象丢包。想象一份保存完好的旧邮件:正文里有希伯来语、一个英语产品名、一串数字和句末标点。归档系统能给出原始文件的哈希;MIME 解码器得到的每个字符也都正确。可是在旧终端、现代阅读器与复制后的文本框里,英语词组和数字分别落在不同位置。
“字节一致”没有回答争议。它只证明运输没有改写序列。屏幕还要回答另一个问题:一行里哪些字符向右推进,哪些片段向左推进,中性标点跟随哪一侧,换行之后又从哪一方向开始。
RFC 1556 的题目是 Handling of Bi-directional Texts in MIME。Hank Nussbacher 于 1993 年 12 月发布它;RFC Editor 记录与 IETF Datatracker都将其列为 Informational。正文也明确说,它不规定任何 Internet Standard。
这份文件的语法野心很小:说明 MIME 双向文本可使用的 direction 约定。它揭开的工程边界却很大——能够把字符送到对面,不等于已经决定字符如何成为人读到的句子。
MIME 先修通了运输层
RFC 1521 让邮件正文不再只能是平坦的 ASCII。正文部件可以声明媒体类型和字符集,并用 Base64 或 Quoted-Printable 穿过仍按旧假设工作的邮件设施。RFC 1521 的信息页保存了这段 MIME Part One 的历史身份。
RFC 1522 又把非 ASCII 表达带到部分邮件头。写信程序把原文变成 encoded-word,支持它的阅读器识别编码、还原字符,再按指定字符集显示。信息页说明它是与正文机制相配套的 Header Extensions。
这两步解决的是“怎样让对方拿到这些字符”。charset 说明编码值对应哪些字符,transfer encoding 保护这些值怎样通过旧链路。对于英语独占的一行,这常常已经接近用户期待;但 ISO-8859-6 的阿拉伯语或 ISO-8859-8 的希伯来语与拉丁文本同处一行时,字符身份并不包含唯一的可见排列。
RFC 1556 因而站在 MIME 成功的终点上继续提问。邮件可以解码成功,阅读仍可以失败。
RFC 1555 留下了一份视觉顺序样本
同月发布的 RFC 1555 由 Nussbacher 与 Yehavi Bourvine 合著,讨论用 MIME 与 ISO-8859-8 传输希伯来语。RFC Editor 信息页同样把它标作 Informational。
它说默认方向是 visual。希伯来文录入时从右向左,但编码时先排成从左向右的视觉序列,再由标准 MIME 机制从左向右传送。阅读器不必理解句子的逻辑结构;写信程序已经替预期屏幕完成排列。
这不是“没有方向性”,而是方向决定被提前了。只要收件端老老实实按单向文本显示,画面可以正确。一旦后来的程序把这份 visual-order 数据当成 logical-order 数据,再运行一次双向算法,原本已经排列过的文字就会被二次重排。
RFC 1555 还记录了邮件列表软件的具体破坏路径:有的 Listserv 转发会省略完整 MIME 头,自动归档也可能不保留它们。编码后的主体还在,说明如何解释它的元数据却丢了。保存了文件,不代表保存了文件与阅读规则之间的联系。
更重要的是它对 8-bit mail 的预期。即使未来透明的 8 位传输让 Base64 或 Quoted-Printable 部分退出,Content-Type 和 directionality 仍然需要。管道更透明,只会减少一种运输转换,不会替屏幕选择顺序。
Visual:写信端已经替收信端做了决定
RFC 1556 把 visual 定为默认模式,仍使用普通 ISO-8859 字符集名,不加后缀。显示设备只有一个从左到右的主方向;阅读程序不知道内容本身的方向,把它当作单向文本。写信程序必须事先把字符排成显示正确的序列,显示时不用控制字符,也不用次序算法。
它的现实优势是兼容简单终端。旧阅读器无需理解希伯来语或阿拉伯语的方向属性,也能把已排好的行照样放到屏幕上。
代价则藏在后续动作里。光标移动、搜索、编辑、复制和重新换行面对的是为某一屏幕宽度制作的视觉序列,而不是句子的逻辑序列。插入一个拉丁缩写,或让窗口在另一个位置折行,原来的排列承诺便可能失效。
因此 visual 模式的责任方是 composer。运输只需忠实,viewer 则必须保持“不聪明”。
Implicit:规则引擎在收件端接手
隐式方向使用 ISO-8859-6-i 与 ISO-8859-8-i。这里的文本不必由写信端记录每一次局部移动;显示算法根据字符类型、字符与相邻字符的位置关系以及主方向来计算呈现次序。RFC 1556 因完整算法复杂而让实现者查阅 ECMA TR/53。
责任从 composer 移向 renderer。收件端要认识后缀,给字符赋予相容的方向属性,还要知道段落的基方向和边界。数字、标点和其他中性字符依靠上下文决定位置;换行在哪里发生,也会改变算法处理的单元。
隐式规则并非随意。共同算法正是为了让实现可以互操作。但它产生的是新的可核验结果,而非传输结果的自动延伸。两个客户端即使拿到相同字符,也可能因为算法版本、基方向、标记边界或折行位置不同而显示不同。
这时只保存 payload hash 不够。要复现画面,必须同时保存决定环境。
Explicit:命令进入正文,解释器必须保住状态
显式方向使用 ISO-8859-6-e 与 ISO-8859-8-e。控制序列夹在正文中,直接规定方向上下文。发送者可以明确开始、改变或结束一段方向,而不是完全依赖相邻字符的类型。
“显式”并不等于“天然安全”。控制序列没有可见字形,清洗器可能把它当作多余或危险内容删除;转换器可能原样保留,却交给不认识这些指令的显示程序;作用域若没有正确结束,方向影响还可能越过作者原本设想的边界。
RFC 1556 说,它所依据的 ECMA TR/53 新增了三个控制功能,并修改了 ECMA-48 中 22 个既有功能。这不是加一个“向右读”的按钮。方向会影响活动位置、字符推进和数据表面与显示表面之间的映射。
显式模式于是有两份责任:发送端要放入正确控制,接收端要保存并执行它们。任何一方只保住可见字母,都还没有保住句子。
ECMA 模型把“数据位置”与“显示位置”分开
ECMA TR/53 把双向设备画成一台接收图形字符与控制函数、再产生供人阅读图像的设备。模型可以同时拥有 data component 与 presentation component,并分别维护 active data position 和 active presentation position。
这组区分解释了为何问题不能缩成字体选择。字体回答某个字符用什么字形。呈现模型回答字形落在哪里、光标如何移动、回车或退格作用于哪个位置,以及一组存储字符如何成为一行图像。
RFC 1556 把这套较深的设备机制压缩成 MIME 侧的模式声明。接收端至少需要知道,它拿到的是 composer 已经排好的视觉序列、等待算法处理的隐式序列,还是携带状态命令的显式序列。模式丢失,就可能把完全正确的数据送进错误的显示机器。
四种故障都可能保住全部字母
第一种是元数据消失。网关保住正文,却把 ISO-8859-8-i 归一化成 ISO-8859-8,或者转发时省略 Content-Type。字符没少,模式选择没了。
第二种是二次重排。旧 composer 已经制作 visual order,现代 viewer 却按 logical order 运行 implicit 算法。双方都执行了自己的设计,合在一起反而错误。
第三种是控制字符被剥离。显式方向命令被安全过滤器删除;若比较时只看可见字符,报告会说内容相同,真正的显示指令却已经不存在。
第四种是上下文漂移。两个 implicit renderer 使用不同基方向、不同换行或不同高层标记边界。它们的 decoded sequence 相同,resolved visual sequence 不同。
数字、标点和标识符让这件事超出排版美观。一个大段落反向很容易发现;标点粘到编号的另一侧,或复制出来的逻辑顺序与眼睛所见不同,却可能进入地址、金额、日期或认证提示。完整字符集合不能证明人读到的关系完整。
后来的机制延续边界,不提供血统证明
1997 年的 RFC 2070 为 HTML 加入 DIR 属性和 BDO override 等国际化机制,信息页说明它属于另一套 Web 标记语境。它可以证明高层上下文仍需承担方向责任,不能证明 HTML 机制由 RFC 1556 直接演化。
早期的 Unicode Bidirectional Algorithm 报告把 Unicode 的内存表示称为 logical order,并说明方向格式字符只影响显示次序。现行 UAX #9已经历大量演进,也明确规定高层协议可以怎样提供段落级别或方向覆盖。
2012 年的 RFC 6532允许在端到端支持 UTF-8 的邮件头中直接使用 UTF-8;信息页记录了它的独立标准身份。字符可以更直接地进入邮件,并不表示存储顺序和显示顺序合并成了一层。
这些资料只证明问题边界持续存在。它们不证明 RFC 1556 的 -i、-e 名称获得普遍部署,更不证明它是 Unicode、HTML dir 或 SMTPUTF8 的单一起点。
调试需要三张收据
运输收据保存原始 octets、哈希、transfer encoding 与解码后的 code-point sequence。它回答途中是否改变。
解释收据保存 Content-Type、charset 与方向模式,所有显式控制,段落基方向,高层 markup/style,以及 renderer 和算法版本。它回答接收方认为自己该使用什么规则。
呈现收据保存换行边界、resolved visual order、截图和复制粘贴后的结果。它回答某一环境里实际出现了什么。
截图单独只能证明某块屏幕曾显示某种排列;payload hash 单独只能证明序列一致。测试样本应把阿拉伯语或希伯来语与拉丁片段、数字、标点、中性字符、嵌套方向和不同窗口宽度组合起来,同时比较逻辑序列与视觉序列。
迁移 renderer 时,应保留新旧结果直到差异得到解释。若为了“清理”旧档案而原地重排,最关键的原始证据会消失,错误迁移也就失去回退路径。
发布文档仍不是运行现实
Heng Lu 的 Running-Code Primacy 提供了一条今日可用的纪律:规范是协调材料,仍需经过实现、运行与采用检验。RFC 1556 被发表,只能证明方向约定写进了公开记录,不能证明哪些客户端执行过它。
Minimum Initial Specification、Localized Future Decision 与 Voluntary Adoption追问,公共规则中究竟什么是最小、确定、可本地核验的。RFC 1556 的教训恰是:传输字符相等,不足以构成双向邮件可读的共同不变量;模式、上下文和相容 renderer 也需成为证据。
Reality Layers要求表示、运输、解释和结果各自留证。这些是后来的分析语言,不是对 Nussbacher 或 ECMA 主观意图的证明。它们的作用,是阻止我们用一层的成功替另一层背书。
三个责任方不能被一句“送达”吞掉
Visual、implicit 与 explicit 不只是三种排版选项。Visual 表示 composer 已经行动;implicit 表示 renderer 的算法将行动;explicit 表示发送端写入命令,接收端执行命令。若系统不知道自己接手的是哪一种,完全忠于本地规则也会背叛原文。
所以 RFC 1556 的历史不是“MIME 无法传希伯来语或阿拉伯语”。MIME 修通了字符的旅程。这份短 RFC 只是拒绝让旅程的收据冒充阅读的收据。
原始序列一致,证明消息完整抵达。方向模式和控制仍在,证明解释上下文被保存。指定 renderer 的成对测试通过,才证明某个可见结果。只有三者同时成立,“正确送达”才不只是“字节到了”。
来源
- https://datatracker.ietf.org/doc/rfc1556/
- https://www.rfc-editor.org/info/rfc1556/
- https://www.rfc-editor.org/rfc/rfc1556.html
- https://www.rfc-editor.org/info/rfc1521/
- https://www.rfc-editor.org/rfc/rfc1521.html
- https://www.rfc-editor.org/info/rfc1522/
- https://www.rfc-editor.org/rfc/rfc1522.html
- https://www.rfc-editor.org/info/rfc1555/
- https://www.rfc-editor.org/rfc/rfc1555.html
- https://ecma-international.org/wp-content/uploads/ECMA_TR-53_2nd_edition_june_1992.pdf
- https://www.rfc-editor.org/info/rfc2070/
- https://www.rfc-editor.org/rfc/rfc2070.html
- https://www.unicode.org/reports/tr9/tr9-4.html
- https://www.unicode.org/reports/tr9/
- https://www.rfc-editor.org/info/rfc6532/
- https://www.rfc-editor.org/rfc/rfc6532.html
- https://heng.lu/running-code-primary-the-patch-needed-to-preserve-the-internet-original-design/
- https://heng.lu/minimum-initial-specification-localized-future-decision-voluntary-adoption-internet-coordination-system/
- https://heng.lu/on-reality-layers-symbolic-power-and-why-clarity-feels-so-hostile/
会员简报
档案背景详情
使用相应会员等级登录,即可解锁完整简报与来源注释。
仅限 Strategic Circle
Strategic Circle
所有读者均可浏览。加入并登录后可解锁档案简报。
加入 Strategic Circle仅限 Leadership Alliance
Leadership Alliance
符合条件的 IP 资产所有者和管理层可登录查看 Leadership Alliance 简报。
加入 Leadership Alliance
