[62] [DFN[ToUnicode]] は、[[Unicode]] の[[文字列]]をできるだけ[[正規化]]し、 [[Punycode]] を[[復号]]する[[操作]]です。 [[IDNA2003]] では[[ラベル]]に対して、[[UTS #46]] では[[ドメイン名]]に対して [[ToUnicode]] [[操作]]が定義されています。また、 [[UTS #46]] では実質的に [[ToUnicode]] と同じ[[操作]]である [DFN[[[Unicode IDNA互換性処理]]]]と [DFN[[[IDNA2008前処理]]]]も定義されています。 * 仕様書 - [26] [[IDNA2003]] -- [2] [CITE@en[RFC 3490 - Internationalizing Domain Names in Applications (IDNA)]] - [22] [CITE@en-us[UTS #46: Unicode IDNA Compatibility Processing]] ([TIME[2010-10-30 01:01:25 +09:00]] 版) -- [25] -- [44] '''''' -- [17] '''''' -- [23] '''''' * IDNA2003 の ToUnicode 演算 [1] [[IDNA2003]] の [DFN@en[[CODE@en[ToUnicode]]]] [[演算]]は、 [[国際化ラベル]]を[[ACEラベル]]でない[[国際化ラベル]]に変換します。 大まかに言うと [[Punycode]] を[[復号]]して人間可読な[[文字列]]に戻す操作です。 ** 入力 - [3] [[国際化ラベル]]、すなわち [[Unicode]] [[符号位置]]の列。 [SRC@en[RFC 3490 4.2]] - [9] [[フラグ]] [CODE@en[[[AllowUnassigned]]]]。 [SRC@en[RFC 3490 4.2]] - [10] [[フラグ]] [CODE@en[[[UseSTD3ASCIIRules]]]]。 [SRC@en[RFC 3490 4.2]] [11] [[ToASCII]] を内部的に呼び出すので、 >>10 が入力となっています。直接は使っていません。 ** 出力 - [4] [[国際化ラベル]]、すなわち [[Unicode]] [[符号位置]]の列。 [SRC@en[RFC 3490 4.2]] -- [12] [[入力]]が [[ACE名札]]なら、 [[等価]]で[[ACE名札]]では''ない''[[国際化名札]]。 -- [13] そうでなければ、元のままの[[国際化名札]]。 [5] [CODE@en[[[ToUnicode]]]] は[[失敗]]しません。 >>8 の[[算法]]が[[失敗]]した場合、 [[入力]]をそのまま[[出力]]とします。 [SRC@en[RFC 3490 4.2]] ** 算法 [8] = すべての[[符号位置]]が [[ASCII]] の範囲 ([CODE(char)[[[U+0000]]]]〜[CODE(char)[[[U+007F]]]]) に収まっていれば、 3 に進みます。 = [[Nameprep]] を適用します ([[旗]] [CODE@en[[[AllowUnassigned]]]] を使用します)。 [[誤り]]があれば[[失敗]]とします。 = [[ACE接頭辞]]ではじまることを確認し、 [[符号位置]]の列の複製を作ります。 = [[ACE接頭辞]]を削除します。 = [[Punycode]] を[[復号]]します。 [[誤り]]があれば[[失敗]]とします。 結果の列の複製を作ります。 = [CODE@en[[[ToASCII]]]] を適用します。 = 6 の結果が 3 で作成した複製と[[一致]]することを確認します。 ここで、[[一致]]するかは [[ASCII]] の[[大文字]]・[[小文字]]を区別しない[[比較]]によります。 = 5 で作成した複製を出力とします。 [15] 確認して違っていたらどうするのでしょう。[[失敗]]とすることを想定しているように見えますが、 明記されていません。 [16] 失敗した場合、 >>5 によりもとの入力が [[ToUnicode]] の結果となります。 ** 性質 -[7] [[出力]]が[[入力]]より[[符号位置]]が増えることはありません。 [SRC@en[RFC 3490 4.2]] * UTS #46 の ToUnicode 演算 [18] [[UTS #46]] の [[ToUnicode]] [[演算]]は、[[ラベル]]ではなく[[ドメイン名]]全体に対して定義されています。 [19] [[UTS #46]] の [[ToUnicode]] [[演算]]は、[[入力]]である[[文字列]]に対して[[非移行的処理]]を適用するというものです [SRC[>>17]]。 [[誤り]]があるかもしれませんが、常に結果として[[文字列]]を[[出力]]します [SRC[>>17]]。 * IDNA2008 前処理 [20] [[UTS #46]] の[DFN[[RUBYB[[[IDNA2008前処理]]]@en[Preprocessing for IDNA2008]]]]は、 [WEAK[(完全な [[Unicode IDNA互換性処理]]を行うのとは違って)]] [[IDNA2008]] の規定する処理に対する[[前処理]]として使うことができる[[算法]]であり、 その[[適合性]]の[[クラス]]です。これは移行処理が特に必要がない場面で利用できます [SRC[>>25]]。 [21] [[IDNA2008前処理]]とは、[[入力]]となる[[文字列]]に [[ToUnicode]] [[演算]] (>>19) を適用することと定義されています [SRC[>>23]]。 ;; [24] [[IDNA2008前処理]]を適用すると[[大文字]]から[[小文字]]への変換など [[IDNA2003]]では行われていた処理の一部がなされるようになります。 これだけでは [[IDNA2008]] で認められていない[[文字]]が一部素通しされてしまいますが、 「前」処理であるので問題にはなりません [SRC[>>23]]。 * Unicode IDNA 互換性処理 [63] [DFN[Unicode IDNA [RUBY[互換性処理][Compatibility Processing]]]]は[[ドメイン名]]に含まれる[[文字]]を[[正規化]]し、 [[Punycode]] を[[復号]]します。これは [[ToUnicode]] [[操作]]そのものであると共に、 [[IDNA2008前処理]]として [[IDNA2008]] 本体での処理の前段階として用いたり、 [[ToASCII]] [[操作]]の最初の手順として用いたりします。 [[Unicode]] に戻すために使うだけでなく、 [[ASCII]] ([[Punycode]]) にしたいときもまずはできるだけ [[Unicode]] 化して[[正規化]]した状態にするということですね。 ** 入力 [41] [[Unicode IDNA互換性処理]]への[[入力]]は、 - [42] [[Unicode]] [[文字列]] [VAR@en[domain_name]] - [43] [DFN[[RUBYB[[[移行的処理]]]@en[Transitional Processing]]]]または[DFN[[RUBYB[[[非移行的処理]]]@en[Nontransitional Processing]]]]のいずれであるか ... です [SRC[>>44]]。 [64] [[移行的処理]]と[[非移行的処理]]の違いは [[IDNA2003]] と [[IDNA2008]] で [[Aラベル]] ([[ACEラベル]]) への変換結果が変わってしまう4文字の扱いだけ [SRC[>>25]] です。 [[移行的処理]]はこの4文字を [[IDNA2003]] 風に[[写像]]して他の文字に変えたり削除したりしますが、 [[非移行的処理]]ではそのまま残します。 ** 出力 [45] [[Unicode IDNA互換性処理]]の[[出力]]は、 - [46] [[Unicode]] [[文字列]] [VAR@en[domain_name]] - [47] [[誤り]]があったか否かの[[フラグ]] ... です。[[誤り]]が途中で発生していたとしても、可能なかぎりの処理がなされた状態の [VAR@en[domain_name]] は返されます。 [SRC[>>44]] ;; [65] 出力の [VAR@en[domain_name]] は[[文字列]]ですが、[[算法]]の内部では一旦[[切断]] (>>59) しています。実装ではそのまま[[配列]]などとして返すこともできましょうし、 そうでなくても [CODE(charname)@en[[[FULL STOP]]]] で分離するだけで容易に[[ラベル]]を取り出せます。 ** 手続き [34] この[[算法]]では次のような処理を行います。 [SRC[>>44]] = [49] [RUBYB[[[写像]]]@en[map]]: [VAR@en[domain_name]] 中の各[[符号位置]]について、 [SRC[>>44]] == [50] [[IDNA写像表]]における[[状態値]]が、 ==- [51] [[禁止]]なら、その[[符号位置]]はそのままとし、[[誤り]]を記録します。 ==- [52] [[無視]]なら、その[[符号位置]]を削除します。 ==- [53] [[写像]]なら、その[[符号位置]]を[[IDNA写像表]]における[[写像値]]に置き換えます。 ==- [54] [[偏差]]なら、 ==-- [55] [[移行的処理]]においては、その[[符号位置]]を[[IDNA写像表]]における[[写像値]]に置き換えます。 ==-- [56] [[非移行的処理]]においては、その[[符号位置]]はそのままとします。 ==- [57] [[妥当]]なら、その[[符号位置]]はそのままとします。 = [58] [RUBYB[[[正規化]]]@en[normalize]]: [VAR@en[domain_name]] を [[NFC]] で[[正規化]]します。 [SRC[>>44]] = [59] [RUBYB[[[切断]]]@en[break]]: [VAR@en[domain_name]] を [CODE(charname)@en[[[FULL STOP]]]] で[[切断]]して[[ラベル]]の並びとします。 [SRC[>>44]] =- [39] [[ラベル分離子]]は4種類ありますが、すべて >>23 で [CODE(charname)@en[[[FULL STOP]]]] に[[正規化]]されています。 [SRC[>>44 4.5]] = [60] [RUBYB[[[変換]]・[[妥当性検証]]]@en[convert/validate]]: [VAR@en[domain_name]] 中の各[[ラベル]]について、 [SRC[>>44]] == [61] [[ラベル]]が [CODE[[[xn--]]]] から始まる場合、 === [48] [[ラベル]]の残りの部分を [[Punycode]] により[[復号]]して [[Unicode]] に変換しようと試みます。 ==== [28] 変換に[[失敗]]した場合は、[[誤り]]を記録し、次の[[ラベル]]へと進みます。 ==== [29] そうでなければ、元の[[ラベル]]を変換結果により置き換えます。 === [30] [[ラベル]]の妥当性を[[非移行的処理]]用の方法で検証します。 ([[ラベル]]の項を参照。) 妥当性の制約を満たさない場合は、[[誤り]]を記録します。 == [31] [[ラベル]]が [CODE[[[xn--]]]] から始まらない場合、 [SRC[>>44]] ==- [32] [[ラベル]]の妥当性を、[[入力]]で指定 (>>10) された方法で検証します。 ([[ラベル]]の項を参照。) 妥当性の制約を満たさない場合は、[[誤り]]を記録します。 [SRC[>>44]] ==-- [38] [[妥当性]]の条件の中には「[[NFC]] であること」が含まれていますが、これは省略できます。 [SRC[>>44 4.5]] >>23 で[[正規化]]しており、 >>59 の[[切断]]でその結果が変わることはないためです。 [33] [[誤り]]が記録されていなければ [VAR@en[domain_name]] の処理は[[成功]]であり、 記録されていれば[[失敗]]です。 [SRC[>>44]] ** 性質 [35] この[[算法]]は[[冪等]]です。 [SRC[>>44]] [37] [[移行的処理]]、[[非移行的処理]]のどちらであっても、元々 [[Punycode]] 化されていれば、それは変更されずに出力されます。ですから、 [[IDNA写像表]]の[[状態値]]が[[偏差]]の[[文字]]はそのままでは[[移行的処理]]か[[非移行的処理]]かによって結果が変わってしまいますが、 [[Punycode]] 化した[[Aラベル]]であれば回避できます。 [SRC[>>44]] ** 移行的処理と非移行的処理の選択 [66] 移行期間中の [[DNS]] [[lookup]] では[[移行的処理]]を、表示を含むそれ以外の場面では[[非移行的処理]]を使うべきです。 [SRC[>>25 2.1]] 両者の違いは[[偏差]]に分類される4文字だけであり、 [[lookup]] では[[移行的処理]]を使っていたとしても、 表示においては[[非移行的処理]]が[[利用者]]の入力により近い形になるので好ましいです。 ** レジストリーにおける対応 [67] [[レジストリー]]にあっては次のいずれかの対応を行うことが強く推奨されています [RSC[>>25 2.2]]。 - [[Bundling]]: [[移行的処理]]と[[非移行的処理]]の結果が異なるなら、両方が登録される場合には[[登録者]]が同じでなければならない - [[Blocking]]: [[移行的処理]]と[[非移行的処理]]の結果が異なるなら、両方が登録されることを認めない、あるいはそもそも[[偏差]]の4文字を認めない ** 例 [40] にこの[[算法]]の適用例がいくつも示されています。 ** メモ [36] [[利用者]]に[[ドメイン名]]を提示する時には更に変更を加えても構いません。 禁止されている[[文字]]を [CODE(char)[[[U+FFFD]]]] に置き換えたり、 [[妥当性検証]]で失敗した[[ラベル]]を [CODE(char)[[[U+FFFD]]]] その他の表示により[[利用者]]に示したりするのがよいとされています。 [SRC[>>44]] * 関連 [14] 逆の操作として、 [[ToASCII]] [[演算]]があります。