DeleGateによる日本語文字コード変換Yutaka Sato 2006年12月30日 [最終更新:2007年01月23日]
[2007年01月23日]
[2006年12月30日]
■ 日本語テキストの検出・文字コードの判別の問題 サーバ向けの文字コード変換は、リクエストヘッダのURLの中、 およびPOSTリクエストのボディ(†p1)の中に、 %XX%XX (URLのエスケープ表記) あるいは &#ddddd; (Unicode文字のHTML表記) のようにエンコードされた日本語テキストに対して適用されます。 (†p2) ここで、%XX%XX の形式でエンコードされたものについては、 それが日本語テキストであるのか、またどの日本語コードで表現され ているのかは、どこにも指示されていません。このため一つの文字列が、例えば EUC-JP としても Shift_JIS としても解釈可能な場合、 変換結果が期待通りにならない場合があります (†p3)。 ■ サーバ固有の文字コード指示との不整合の問題 サーバ固有の何らかの形式で、リクエスト中の非ASCII文字の文字コードが指示 されている場合があります。(†p4) DeleGateがそのようなリクエスト中の日本語テキストに文字コード変換を行った 場合、併せてそのような指示も書換えないと、サーバ側での文字コードの判別を 誤らせることになります。 残念ながらそのような指示の形式は標準化されたものでなく、個別に対処する しかない、一般的な解決が困難な問題です。 ■ 日本語文字コード間の文字セットの不整合の問題 DeleGate/9.4.2 現在、DeleGate がサポートしている(と思われる)日本語の 文字セットは、JIS X 0201, JIS X 0208, JIS X 0212 です。 文字コードは、ISO-2022-JP, EUC-JP, Shift_JIS および UTF-8 です。 ここで、文字コードの間で、表現できる文字セットは、それぞれに異なります。 例えば「半角カナ」は、ISO-2022-JP には含まれていないので、例えば Shift_JIS から ISO-2022-JP に変換すると、半角から全角に変換されます。 例えば EUC-JP でコード化されている「補助漢字」は、Shift_JIS に変換すると 失われます。 変換先のコードが存在しない場合その文字は(デフォルトでは)ゲタ記号(〓) にしています (†p5)。 ■ Unicodeの問題 UTF-8 (Unicode文字セット) と JIS文字セットのコードと間の変換では、 Unicode.Org から配布されている変換表を、DeleGate の起動時に (CHARSET オプションが指定されている場合)、 DeleGate.ORG 経由でダウンロードして、用いています。 DeleGate/9.4.2 現在、用いているのは、OBSOLETE と分類されている変換表で、 これは JIS X 0213 を含んでいません。 今後、必要性があると判断された段階で、実装したいと思っています。 (Unihan.txt の表から日本語の文字コードを抽出することになると思います) なお、Unicode については、よく言われているように、JISコードとの間の変換が 一意でないという問題もあります。
(†p1) POSTリクエストのボディに対する文字コード変換が適用されるのは、 デフォルトでは、そのデータ型(Content-Type)が x-www-form-urlencoded の場合のみです。 これ以外の型にも適用するには、 HTTPCONF=post-ccx-type で指定して下さい。 典型的には、FORMタグの中で ENCTYPE=multipart/form-data と 指定されて送り出される場合です。またこの場合、POSTのボディ中には、URLとして エスケープされていない生の形式で、日本語テキストが含まれることになります。 (†p2) サーバ側が明示的あるいは暗黙的に指定する受理可能な文字コード・セットで 表現できない文字をサーバに送信する際、最近のHTTPのクライアント(ブラウザ)は ddddd;という形式でそのUnicode文字のHTML表記を送ってくる、 というのが一般的なようです。URL中では "&" "#" ";" はそれぞれエスケープされて %26%23ddddd%3B となります。 (†p3) サーバからのレスポンスの場合にも同じような問題はありますが、レスポンス の場合、入力の文字コードが Content-Type や META タグで指定されていることが 多く、確実に推定するために十分な文字数がある場合が多いので、入力コードの 判別を誤ることは稀です。 (†p4) 例えば、何時の頃からか、search.yahoo.co.jp では、queryの中に、 "ei=UTF-8" とか "ei=euc-jp"のような形で入力の文字コードが指定されるように なっています。 (†p5) CHARMAP=jis:0000/2222 などとして、マップ先のない文字を、〓 (JISコードで0x222E) 以外の 文字にマップすることができます。
■ 特定の文字コードにしか対応していないクライアント
もともと DeleGateの日本語文字コード変換の機能は、黎明期のウェブブラウザ
(日本語対応前の、Win/Mac 版 NCSA Mozaic)でとりあえず日本語が読めるよう、
追加されたものでした。
現在ではメジャーなHTTPのクライアントは、各種の日本語文字コードをサポート
しているので、この問題はほとんど無いでしょう。
ただ、HTTP以外のプロトコルにおいては、このような変換が必要な状況は未だに
あるようです。
■ サーバへ送られるメール・ニュースの文字コードの統一
これもDeleGateの歴史的な用途として、ニュースリーダ(NNTPクライアント)から
投稿された記事の文字コードを、DeleGateでISO-2022-JP に強制変換してサーバに
送出するという機能が、しばらく使われていました。
この使われ方も、クライアント側の文字コード対応やネットニュースの衰退とともに、
現在ではほとんど見られなくなっていると思います。
現在では、メールを配送するSMTPの中継において、文字コードの強制や文字セットの
制限などを行う上で、必要性があるかも知れません。
■ 文字コードが指示されていない日本語テキストによる字化け
サーバから送られて来た応答テキストが、どのような文字コードによるものか、
どこにも(HTTPやMIMEのヘッダにも、HTMLのMETAタグにも)指示されていない場合
があります。
この時、その文字コードが何であるかはクライアント(ブラウザ)側で推定する
ことになりますが、その自動判別に失敗した時や、デフォルトが非日本語の状態
に設定されている時に、字化けが発生します。
(†b4)
■ 文字コードが混在した日本語テキストによる字化け
サーバから送られて来た応答テキストが、複数の文字コードの混在したものである
場合があります。ほとんどのライアント(ブラウザ)はそれに対処してくれません
ので、ここで字化けが発生します。
(†b5)
これは、サーバ側で日本語文字コードを考慮せずに、複数のソースからのデータを
マージしてレスポンスを合成した場合などに発生します。
そもそも、このようなテキストは通常の規格上許容されていないものですし、
文字コードの自動判別がより困難になりますが、DeleGateではいくつかの
ケースについて、文字コードの混在した入力を判別して、対応しています。
■ サーバ側のサポートしない文字コードでのリクエストで字化け
検索サーバや掲示版への書き込みなど、クライアント側から送信した日本語
テキストの文字コードを、サーバ側で認識・受理できない場合に字化けが起こります。
この問題は、サーバ側がどの文字コードを受理できるかをクライアントが認識・考慮
していない場合や、そのコードに対処していない場合、そのコードで表現できない
文字を送ろうとする場合、などに発生します。
(†b1) 現在 DeleGateで、クライアント向けの(サーバからクライアントへ送られる テキストの)文字コード変換をサポートしているプロトコルは、 HTTP, FTP, POP, NNTP, Telnet, Tcprelay(任意のTCP上のデータ) です。 (†b2) MIMEメッセージに対するこの変換は、text型のメッセージ、および multipart メッセージに含まれるtext型の各パートに対して適用されます。 (†b3) 現在DeleGateで、サーバ向けの文字コード変換をサポートしているプロトコルは、 HTTP, FTP, SMTP, NNTP, Telent, Tcprelay(任意のTCP上のデータ) です。 (†b4) 私の場合、実験台になる意味もあって、ブラウザには「日本語版」を使わず、英語版 を使っていますので、デフォルトの文字セットが ASCII や ISO-8859-1 である ことが多く、このようなケースに遭遇しやすいといえます。 (†b5) 例えば9.4.1以前のDeleGateでは、SHTML (SSI) で #include したテキストの 文字コードが異なる場合に対処しておらず、文字コードの混在が発生して いました。
以下は、DeleGate の参照マニュアル Manual.htm からの抜粋です。
The pseudo code name "guess" means not doing conversion but supplement
the "charset" attribute in "Content-Type" header in a message
when it is lacking, guessing it from the body of the message.
This is useful when a viewer program (ex. a web browser)
of the message is not localized to Japanese thus non-ASCII codes like
EUC-JP are guessed as European or so by the viewer.
If "tosv" is specified, the conversion is applied to
the request message (or a message toward a server).
The conversion is also applied to fragments of Japanese text in a HTTP request
message encoded in "%XX" in its request URL or in the body of a POST
message (when it is encoded in Content-Type: application/x-www-form-urlencoded).
The set of values of Content-Type to which the conversion is applied can be
specified with HTTPCONF=post-ccx-type.
The application of the conversion can be limited only to a specified
set of protocols, servers and clients specified with connMap.
In the connMap, the default value of ProtoList,
dstHostList and srcHostList is "*" which matches
any protocols or hosts.
Example: send response in UTF8 to clients and send request
in Shift_JIS to HTTP servers
For the FTP protocol, the conversion is applied only to the data
of the ASCII type relayed on the data-connections by default.
It is applied also to binary data or data on the control-connection
with FTPCONF="ccx:any".
To enable this parameter for internet-mail/news protocols
(SMTP, POP and NNTP),
also MIMECONV parameter must be specified
so that it enables character conversion (enabled by default).
A HTTP client can override this specification by sending its choice
in "Accept-Language" field in a request message,
which may be configurable in each client (WWW browser).
For example, if
"Accept-Language: (charcode=EUC)" is sent in a request from client,
the response text will be converted into EUC regardless of CHARCODE
specification of the DeleGate. If
"Accept-Language: (charcode=THRU)" is specified,
any conversion specified by the administrator of this DeleGate is disabled.
A character to be mapped is represented in a hexa-decimal value of it
(represented in more than 2 columns), or a direct character in a single columns.
The characters in the JIS X 0208 character set encoded in the variants of its
encoding (ISO-2022-JP, EUC-JP, and Shift_JIS) are represented in
its JIS code value without the most significant bits (8080) as "2121".
The characters in the JIS X 0212 character set are represented in its
JIS code value prefixed with "1" as "1222F".
The mapType is one of followings:
Example: reverse lowercase and upper case
Example: "rot13" encoding
Example: replace any Japanese character in JIS X 0208 with "GETA MARK"
Example: replace any Japanese character in JIS X 0212 with "GETA MARK"
Example: represents unknown characters by "WHITE SQUARE" instead of "GETA MARK"
|