【Ajax】日本語文字列防忘メモ
Ajaxでサーバーとやりとりする時の日本語文字列扱いについて、
防忘録のための整理。不得意分野なので、つっこみ大歓迎。
1:サーバー上の日本語をブラウザで表示するだけの場合
サーバーから一方的にPCが日本語をAjaxで受け取るケースです。
このケースでは、むき出しの日本語を、サーバーからPCへ送るとSafari,
Konquerorで文字化けします(参考:
responseされる文字コードの調査)。
そこで、この、Safari,
Konqueror対策として、今のところ、私の場合は、あらかじめ、PCのJavaScriptでencodeURI()
などした文字列をサーバー側に置き、受信した文字列をdecodeURI()などしてみてい
ます( 例 :
Allabout /Ajaxはじめの一歩 XMLHttpRequest) 。
あらかじめ用意する理由は、PHPやJavaのURLエンコードとJavaScriptのURL
エンコードが微妙に違うためです。つまり、JavaScriptのURLエンコード方式だけでやりと
りすることでデコード間違いのリスクを減らすというわけです。
JavaScriptのURLエンコード方式には
「escpe()/unescape()」「encodeURI()/decodeURI()」「encodeURIComponent()/decodeURIComponent()」
の3方式(6つのメソッド)がありますが、escpe/unescapeはブラウザ毎に実装が異なりますからあまりお勧めしません。encodeURIやencodeURIComponentなどは、ともにutf-8としてエンコード
しますが、前者が、予約語(,や:や?など)をエンコードしないという違いだけですので、
必要に応じて使えば良いと思います。(
ECMA-262 3rd Edition 和訳 : 15.1.3 URI 処理関数のプロパティ )
ちなみに、この4つのメソッド(encodeURI、decodeURI、encodeURIComponent、decodeURIComponent)はECMAScriptに準拠したもので、UTF-8を使って
"%xx" のように変換します(xx は16進数)。
もちろん、もし、サーバー側でJavaScriptのエンコードをエミュレートできるなら、それを使えばOK
だと思います。
2:単体のPCとサーバーで送受信する場合
PCから日本語をサーバーへ送り、その後それを逆にPCがサーバーから受け取る
というケースです。つまり、PCが最初に日本語を発信をします。
PCからサーバーへのデータ入力時などにありうるケースでしょう。
この場合は、PCとサーバー間のエンコーディングが同じなら良いわけですから
「escpe()」「encodeURI()」「encodeURIComponent()」どれでも構わなさそうです
が、たとえば、Safariでは、どれでも、化けてしまいます。
調べてみたら、send()でサーバーまでは化けずに届いていても、サーバー
からPCがresponseTextで受け取ってみると化けているという感じです
(responseXMLですとSafariはOKですが、Konquerorが化けます)。
しかし、前項目のようにサーバーからエンコード済みのデータを受け取る
ときには文字化けしないのです。ようは、PCから受け取ったデータは、サーバー
がURIエンコードをデコードするので、次にPCへ渡す時には生の日本語データに
なっているという感じです。そりゃ、Safariにゃ無理です(^^;。
そこで、私が今試している方法は、PCから手製エンコードしたデータを送り、
サーバーを騙してしまうというやり方です。つまり、%xxのようないかにも
2バイトコードのような文字列ではなくしてしまうことで、サーバー側の文字
コード設定が何であろうと素通りしてくれるように、変換してしまうという
わけです。
たとえば、こんな感じ、変換方法は何でも良いんですけれど、たぶん、
「%xx」の「%」さえなくなれば大丈夫なのではないかと、、、。
//送信前エンコード
var senddata = '高橋としろ'
var s = encodeURIComponent( senddata )
s = s.split('%').join('/')
s = s.split('/E3').join(':')
s = s.split('/A').join(';')
s = s.split('/8').join(',')
s = s.split('/E').join('?')
s = s.split(':,1').join('@')
oj.open( 'GET' , url+'?test='+ s , true )
// 上記の送信前エンコードの結果、
// 文字列「高橋としろ」は、次のように変換されます
高橋としろ
↓
%E9%AB%98%E6%A9%8B%E3%81%A8%E3%81%97%E3%82%8D
↓
/E9/AB/98/E6/A9/8B/E3/81/A8/E3/81/97/E3/82/8D
↓
/E9/AB/98/E6/A9/8B:/81/A8:/81/97:/82/8D
↓
/E9;B/98/E6;9/8B:/81;8:/81/97:/82/8D
↓
/E9;B/98/E6;9,B:,1;8:,1/97:,2,D
↓
?9;B/98?6;9,B:,1;8:,1/97:,2,D
↓
?9;B/98?6;9,B@;8@/97:,2,D
//下記デコードは、この変換を逆に辿ります。
//受信後デコード
var r = res.GET
r = r.split('@').join(':,1')
r = r.split('?').join('/E')
r = r.split(',').join('/8')
r = r.split(';').join('/A')
r = r.split(':').join('/E3')
r = r.split('/').join('%')
var resdata = decodeURIComponent( r )
変換の塩加減をランダムに生成して、セッション毎に同一のenc/decするように
できれば、JavaScript内にも証拠が残りませんし、ましてTCPをモニタするだけでは、
そう簡単には解読できなくなくなると思います。多少はデータも小さくできますしね。
ま、日本語そのものが暗号な欧米人にはわからない話かもしれませんけど、、、(^^;。あ、太平洋戦争のときの暗号部隊として、アメリカである少数言語部族が活躍したって話を思い出しました、、、関係ないですけど。
追記
2005.5.23
この自家製符号化による文字化け回避の件については、
ここ で実験しました。
3:..つづく、、、
( 2006年11月09日 11:25 )
ああああああああああああああ
( 2007年01月24日 20:56 )
てしと
僕 ( 2007年03月02日 22:17 )
すごい
テストさせてください ( 2007年06月06日 16:05 )
蚊がおる!!!
( 2007年06月14日 15:39 )
33333
( 2007年07月04日 11:59 )
[]{}:;
\n
( 2007年07月04日 17:13 )
111
( 2007年08月24日 09:19 )
][]
( 2007年09月26日 10:48 )
〜
てst ( 2007年10月10日 16:47 )
あああ
( 2008年02月08日 12:51 )
a
(←clickで入力欄open)