要約

  • RFC 2070 は、具体的な HTML リソースの外部バイト符号化と、HTML が固定して持つ抽象 UCS 文書文字集合を分離した。HTTP/MIME の charset は前者を復号する写像を示した。
  • 数字文字参照は固定文書文字集合で評価されるため、マークアップを運ぶ外部符号化が変わっても文字の同一性は変わらない。
  • 復号の成功は一段階の受領証にすぎない。SGML 構文解析、言語・双方向処理、フォントの有無、グリフ出力、読者の理解にはそれぞれ別の証拠が要る。

キリル大文字 И を考える。あるリソースは対応する外部符号化で文字を直接運び、別のリソースは И と記述できる。さらに、その参照自体を多バイト UCS 符号化で保存することもできる。線上のオクテットは互いに違う。それでも受信側が正しいデコーダーを選び、マークアップが妥当なら、三つの経路は HTML 文書中の同じ文字番号に到達する。

RFC 2070 の境界は、外部表現の可変性を入口に閉じ込め、文書内の目標を安定させた。もしバイトと文字番号を同一視すれば、サーバーが転送符号化を変えるだけで数字参照の意味まで変わってしまう。

SGML は構文解析より先に文字空間を必要とした

当時の HTML は SGML アプリケーションだった。SGML の文書文字集合とは、単一ファイルで許されるバイト一覧ではない。文字のレパートリーと、文書型および実体が文字を識別する番号体系の組み合わせである。DTD、マークアップ、データ文字は一つの番号空間で解釈された。

RFC 1866 の HTML 2.0 は Latin-1 を含み、その位置を ISO 10646 と整合させ、より大きなレパートリーへの道を示した。RFC 2070 は HTML 2.x の国際化プロファイルで、修正を含む ISO 10646:1993 の Universal Character Set を採用した。発行当時、RFC はこれを Unicode 1.1 とコード位置ごとに同一だと説明している。

範囲の拡張は、あらゆる整数の許可ではない。SGML 宣言では 128~159 が未使用なので、’ はこのモデルでは不正だった。後年のソフトウェアがそこに句読記号のような見た目を与えても、歴史的な合法性は変わらない。「Unicode のページ」という表現には、HTML が名指せる抽象文字と、個別リソースが採用した外部符号化という二つの主張が隠れている。

charset は入口を選ぶが、行き先を作り直さない

外部符号化は転送・保存環境から与えられた。HTTP では応答 Content-Type の charset パラメーターが外部文字符号化を指定し、電子メールでは MIME の同名パラメーターが既定規則とともにその役割を担った。RFC 2070 は、当時の FTP や分散ファイルシステムには標準化された通知手段がなかったとも記録した。

MIME の charset は単なる文字一覧ではなく、オクテット列から文字列への写像方式だった。複数のオクテット列が同じ文字結果へ至る場合もある。RFC 2045 は、登録された MIME charset がその写像を完全に定義することを要求したが、抽象文字すべてを逆向きに符号化できるとは保証しなかった。

RFC 2070 の参照モデルは、リソース → デコーダー → エンティティ管理器 → SGML パーサー → アプリケーション → 表示、という順序を置く。デコーダーが外部表現を文書文字集合へ変え、後段が文字として意味を処理し、表示側が装置表現へ変換する。実装内部に同名の箱がなくてもよい。外から見た振る舞いがこの境界を守る必要がある。これは 1997 年のブラウザー部品表ではなく、観測可能な契約である。

数字参照は復号後にあるから不変だった

RFC 2070 は、数字文字参照の不変性をモデルの最重要な帰結と呼んだ。参照先は固定文書文字集合なので、外部符号化に左右されず同じ文字を表す。

ただし順序は重要だ。受信側はまずバイトを &、#、数字、; というマークアップ文字へ正しく復号しなければならない。その後で SGML が参照を認識して番号を解決する。数字参照は誤復号されたストリームを救済しない。正しく境界を越えた後にだけ安定する。

反対方向のバイトも固定されない。RFC 2070 は、フォームの未編集の初期値でさえ、送信時には元文書と異なる有効なオクテットになり得ると注意した。合成列と合成済み文字も、等価なテキスト要素を異なる形で表せる。コピー、保存、送信は新しい符号化イベントであり、原ファイルのバイト再現ではない。

符号化ラベルにも証拠の順位があった

RFC 2070 は 1997 年の配備上の問題として、サーバーが適切な charset を送らず、一部ブラウザーが charset 付き Content-Type を誤処理したと記した。これは歴史的観察であり、現在のブラウザー利用状況を示す数字ではない。

優先されたのは文書の取得元から届く charset で、次が文書冒頭の META HTTP-EQUIV、その次がリンクの助言的な CHARSET 属性だった。META には自己参照的な難点がある。そこへ到達するまでのバイトが十分に復号されなければ、パーサーは宣言を発見できない。RFC が「絶対確実ではない」としたのはこのためで、冒頭で ASCII 値オクテットを適切に扱える符号化に実用範囲が限られた。

順位は権威と入手しやすさを分ける。手元のヒントが早く見えても、応答メタデータと同じ権威は得ない。一方、権威あるラベルも主張にすぎず、本文が写像に従うことやデコーダー実装の忠実さを暗号学的に証明はしない。

文字が得られても、画面では失敗できる

UCS を文書文字集合にしてもフォントは生成されない。RFC 2070 は、解析できても表示できない文字を予期し、唯一の代替表示を規定しなかった。豆腐形の欠字記号や十六進番号は表示方針であって、別の文字同一性ではない。

言語と方向も別の状態を加える。LANG はグリフの選択、引用符、ハイフネーション、合字、間隔、音声に影響し得る。DIR、BDO、Unicode 双方向アルゴリズムは意味を読める視覚順序を変える。いずれも復号済みの文字を扱うのであり、外部バイトの意味を再定義しない。

よって、符号化信号の誤り、デコーダーの誤出力、パーサーの拒否・誤構造化、フォント欠落や言語・方向処理の失敗は別々の事故である。スクリーンショットだけでは先に壊れた層を特定できず、正しいバイトハッシュだけでも後段の成功は証明できない。

発行主体が移っても境界は残った

HTML 仕様の主導が W3C へ移ると、RFC 2854 は RFC 2070 と初期の IETF HTML 文書を廃止した。これは統治と文書履歴の事実であり、デコーダー境界が消えた証拠ではない。後の text/html 登録も charset を HTML 文書をバイトで表現するときの符号化と説明し、HTML 4.01 も文書文字集合だけでは交換されたバイト列を解釈できないと述べた。

Lu Heng が後に論じた「最小限の初期仕様、ローカルな将来判断、任意採用」という区分は、この設計を振り返る補助線になる。固定文字番号は小さな共通不変条件である一方、対応デコーダー、エラー処理、フォント、表示は受信側の実装判断に残る。規範の公開はコードの実行ではない。

RFC 2070 から残る運用原則は単純だ。バイトの到着は文書の成立ではなく、文字番号の確定はグリフの出現ではない。遷移ごとに固有の証拠が必要で、前段の受領証を借りても後段の成功範囲は広がらない。

出典