Yutaka Sato
2006年12月30日
[最終更新:2007年01月23日]
|
|
[2007年01月23日]
文字コード異常の例とDeleGateによる回避方法
を追加、
文字コード変換プロキシの問題点
加筆。
[2006年12月30日]
DeleGate
9.4.2
では、10年ばかり御無沙汰気味だった日本語文字コード変換機能
について見直しを行い、以下の拡張を行いました。
■ 文字コード変換リバースプロキシとしてのDeleGate |
■ リバースプロキシの構成 |
[http://www.com.dom:80] [http://serv:8880] client -------------------> DeleGate -------------------> HTTP-server |
[ DeleGateの起動コマンド ] delegated +=httpd.cnf [ httpd.cnf ファイルの内容 ] -P80 SERVER=http MOUNT="/* http://serv:8880/* vhost=-www.com.dom" URICONV=where:any PERMIT="http:serv:*" RELAY=no |
■ 文字コード変換プロキシ |
client <----- EUC-JP ------- DeleGate <===== Japanese ==== HTTP-server ------ EUC-JP ------> ------ EUC-JP -----> |
■ 文字コード変換リバースプロキシの構成 |
[http://www.com.dom:80] [http://serv:8880] client <----- UTF-8 ------- DeleGate <=================== HTTP-server ===================> DeleGate ----- EUC-JP ------> |
[ httpd.cnfの内容 ] -P80 SERVER=http MOUNT="/* http://serv:8880/* vhost=-www.com.dom" URICONV=where:any PERMIT="http:serv:*" RELAY=no CHARCODE=UTF-8 CHARCODE=EUC-JP:tosv |
■ 文字コード変換プロキシの問題点 |
■ 日本語テキストの検出・文字コードの判別の問題
サーバ向けの文字コード変換は、リクエストヘッダの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コードとの間の変換が 一意でないという問題もあります。
■ 文字コード異常の例とDeleGateによる回避方法 |
■ 特定の文字コードにしか対応していないクライアント
もともと DeleGateの日本語文字コード変換の機能は、黎明期のウェブブラウザ
(日本語対応前の、Win/Mac 版 NCSA Mozaic)でとりあえず日本語が読めるよう、
追加されたものでした。
現在ではメジャーなHTTPのクライアントは、各種の日本語文字コードをサポート
しているので、この問題はほとんど無いでしょう。
ただ、HTTP以外のプロトコルにおいては、このような変換が必要な状況は未だに
あるようです。
この問題は、サーバからクライアントにテキストを中継する際に、文字コードを
クライアントがサポートしているものに変換してやることで回避できます。
例えばクライアントが EUC-JP に対応しているなら、
CHARCODE=euc-jp
のように指定します。
(†b1)
■ サーバへ送られるメール・ニュースの文字コードの統一
これもDeleGateの歴史的な用途として、ニュースリーダ(NNTPクライアント)から
投稿された記事の文字コードを、DeleGateでISO-2022-JP に強制変換してサーバに
送出するという機能が、しばらく使われていました。
この使われ方も、クライアント側の文字コード対応やネットニュースの衰退とともに、
現在ではほとんど見られなくなっていると思います。
現在では、メールを配送するSMTPの中継において、文字コードの強制や文字セットの
制限などを行う上で、必要性があるかも知れません。
メール・ニュースのケースは、受信者(の使用クライアントプログラム)が不特定
多数であるため、受理可能な文字コードが特定できない場合といえます。
このため、日本語メール・ニュースについては、推奨されている(はずの)
ISO-2022-JP に揃えるのが安全策(であるはず)です。
例えばサーバに送出(中継)するメッセージの文字コードを ISO-2022-JP に統一する
には、
CHARCODE=iso-2022-jp:tosv
のように指定します。
(†b2)
(†b3)
■ 文字コードが指示されていない日本語テキストによる字化け
サーバから送られて来た応答テキストが、どのような文字コードによるものか、
どこにも(HTTPやMIMEのヘッダにも、HTMLのMETAタグにも)指示されていない場合
があります。
この時、その文字コードが何であるかはクライアント(ブラウザ)側で推定する
ことになりますが、その自動判別に失敗した時や、デフォルトが非日本語の状態
に設定されている時に、字化けが発生します。
(†b4)
このようなケースの多くは、リバースプロキシあるいはクライアント側のDeleGate
において、応答の文字コードを推定し、HTTPヘッダ (Content-Type 中の charset
パラメタ) に指示してやることで、回避することができます。
DeleGateにこれを行わせるには、
CHARCODE=guess
のように指定します。
■ 文字コードが混在した日本語テキストによる字化け
サーバから送られて来た応答テキストが、複数の文字コードの混在したものである
場合があります。ほとんどのライアント(ブラウザ)はそれに対処してくれません
ので、ここで字化けが発生します。
(†b5)
これは、サーバ側で日本語文字コードを考慮せずに、複数のソースからのデータを
マージしてレスポンスを合成した場合などに発生します。
そもそも、このようなテキストは通常の規格上許容されていないものですし、
文字コードの自動判別がより困難になりますが、DeleGateではいくつかの
ケースについて、文字コードの混在した入力を判別して、対応しています。
このようなケースでもやはり、リバースプロキシあるいはクライアント側のDeleGate
において、特定の文字コードへのコード変換を行えば解消します。
例えば文字コードを EUC-JP に揃えるには、
CHARCODE=euc-jp
のように指定します。
■ サーバ側のサポートしない文字コードでのリクエストで字化け
検索サーバや掲示版への書き込みなど、クライアント側から送信した日本語
テキストの文字コードを、サーバ側で認識・受理できない場合に字化けが起こります。
この問題は、サーバ側がどの文字コードを受理できるかをクライアントが認識・考慮
していない場合や、そのコードに対処していない場合、そのコードで表現できない
文字を送ろうとする場合、などに発生します。
この問題は、DeleGateによってサーバ向けのデータ中の文字コードを適切に
変換してやることで回避することができます。
DeleGateをリバースプロキシとしての使用する場合など、対象サーバの数が
少なくその受理できる文字コードが特定できる場合には、
CHARCODE=euc-jp:tosv
あるいは、
CHARCODE=euc-jp:tosv:http:server1,server2
などと指定することで対応できます。
(HTTPの)クライアント側のプロキシで、対象サーバが特定できない場合、
クライアント向けの文字コード変換、例えば
CHARCODE=euc-jp
などを指定すると、クライアント向けの変換の際にサーバの元の文字コードを
Cookie中
(svcc) に記憶させ、
これに基づいてサーバ向けの文字コード変換を行います。
PageViews: 215 hits / 46 nets |
以下は、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"
CHARCODE parameter* == CHARCODE=[inputCode/]outputCode[:[tosv][:connMap]]
outputCode == charCode
charCode == iso-2022-jp | euc-jp | shift_jis | utf-8 | us-ascii |
JIS | EUC | SJIS | UTF8 | ASCII | guess
connMap == [ProtoList][:[dstHostList][:[srcHostList]]]
-- restriction: applicable to HTTP, FTP, SMTP, POP,
NNTP, Telnet, Tcprelay
-- default: none
If specified, DeleGate will convert the JIS code in text type response
message into the specified character code.
When UTF8 is specified, a mapping table necessary for conversion between
Unicode and JIS code is downloaded automatically from the server
at Unicode.Org via DeleGate.ORG.
CHARMAP parameter* == CHARMAP=mapType:charMap[,charMap]*[:tosv]
mapType == ascii | ucs | jis | ucsjis | jisucs
charMap == inCharCode1[-inCharCode2]/outCharCode2[-[outCharCode2]]
charCode == hexa-decimal code | single ASCII character
-- default: none
If specified, a character in texts relayed in a message of an application
protocol is mapped to another character.
By default, the mapping is applied to the response data to client.
It can be applied to the request data to server specifying ":tosv".
If inCharCode2 and outCharCode2 is specified, each character in
the range is mapped to the corresponding character.
If no -outCharCode2 is given, any input characters in the range
is mapped to outCharCode1.
CHARMAP=ascii:a-z/A-Z,A-Z/a-z
CHARMAP=ascii:a-m/n-z,n-z/a-m,A-M/N-Z,N-Z/A-M
CHARMAP=jis:0100-7F7F/222E
CHARMAP=jis:10000-1FFFF/222E
CHARMAP=jis:0000/2222