【PR】 Bフレッツ・プロバイダ別料金比較(ファミリータイプ)
【PR】 JavaScript開発者必見! 「プランセスJS Encoder」
【PR】 中国語の学習に役立つサイト
【PR】 Bフレッツ・プロバイダ別料金比較(マンションタイプ)
 

・Javascriptのprompt関数でユーザー入力を受け付けるとゴミがつく問題

左のようなユーザープロンプトを表示させて、ユーザー入力を受けて、


日本語を入力すると、なぜか入力値以降のメッセージが消えます。(Windows版IE5.5で。6.0では起こりません)


それを、左のように表示させる例が見られます。実用度はともかく、Javascriptの参考書籍などにもたいていサンプルコードが紹介されています。下記のような感じになります。
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<title>プロンプト</title>
</head>
<body bgcolor=#FFFFFF>
<script language="Javascript">
<!--
   res = prompt("名前を入力してください。","");
   if(res == null){
      res = "guest";
   }
   document.write("私のホームページへ" + res + "様 ようこそ<p>");
//-->
</script>
本文スタート。
</body>
</html>

この極めて簡単なスクリプトがなぜか、特定のブラウザで動かない。しかも、優等生であるはずのWindows版IEにおいてです。IE6.0ではこの不具合は解消されていますが、5.5や5.01では発生します。

なぜ、このような不具合が発生するのかを見るために、スクリプトを少し変更してみます。「あいうえお」と入力すると「正解です。」と表示し、それ以外の言葉を入力すると、「残念。不正解です。」と表示するスクリプトを考えてみます。

<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<title>プロンプト</title>
</head>
<body bgcolor=#FFFFFF>
<script language="Javascript">
<!--
   res = prompt("名前を入力してください。","");
   if(res == "あいうえお"){
      alert("正解です。");
   } else {
      alert("残念。不正解です。");
      location.href = "about:blank";
   }
//-->
</script>
本文スタート。
</body>
</html>

左のようなスクリプトを実行し、「あいうえお」と入力すると、Windows版IE6.0では「正解です。」と表示されますが、Windows版IE5.5や5.01では「残念。不正解です。」と表示されます。Windows版IE5.5や5.01では、何らかの文字化けが発生していることになります。

では、どのように文字化けしているのでしょうか? 実際の入力値を見るために16進ダンプを取ってみます。ここでは、Javascriptのescape関数を利用します。下記のようなサンプルコードをIE5.5や5.01で実行してみます。

<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<title>プロンプト</title>
</head>
<body bgcolor=#FFFFFF>
<script language="Javascript">
<!--
   res = prompt("名前を入力してください。","");
   document.write(escape(res));
//-->
</script>
</body>
</html>

Windows版IEではescape関数はunicodeでエンコードされますから、「あいうえお」は「%u3042%u3044%u3046%u3048%u304A」となるはずですが、実際にテストしみますと、「%u3042%u3044%u3046%u3048%u304A%00%uBA00%u0296%uFFFF%uFFFF」だったり「%u3042%u3044%u3046%u3048%u304A%00%01%00%00%00」、「%u3042%u3044%u3046%u3048%u304A%00%u0150%u029D%u1B9A%00」、「%u3042%u3044%u3046%u3048%u304A%00%00%00%00%00」だったりします。明らかに、入力した文字列以上の何かがついてきています。しかも、実行するたびに違う結果になりますが、共通点があり、本来表示されるはずの「%u3042%u3044%u3046%u3048%u304A」が先頭にあり、その直後に「%00 = null」がついていることは共通しています。



月額961円からの格安サーバ。でも高機能です!!

このnull値がついているために、そこでJavascriptの実行がストップしてしまい、冒頭で紹介した「ユーザー入力に基づき名前を表示するというスクリプト」が日本語入力の際、正しく動作せず、その日本語の後の文字列が全部、消えてしまっていたのです。

<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<title>プロンプト</title>
</head>
<body bgcolor=#FFFFFF>
<script language="Javascript">
<!--
   res = prompt("名前を入力してください。","");
   if(res == null){
      res = "guest";
   }
   if(document.all){
      res_b = escape(res);
      pos = res_b.indexOf("%00"); //nullが現れる位置を求める。見つからなければ「-1」が返ってくる。
      if(pos != -1){
         res_b = res_b.substr(0,pos); //nullが現れる直前の文字列までをイキとする。
      }
      res = unescape(res_b); //再びunescape関数でデコード
   }
   document.write("私のホームページへ" + res + "様 ようこそ<p>");
//-->
</script>
本文スタート。
</body>
</html>

対策としては、「%00 = null」が現れたら、その直前までの文字列をイキとして、それ以降の文字列は捨てるという処理で大丈夫ということになります。

左のようなコードになります。indexOf関数やsubstr関数はJavascriptでよく使う関数の一つですね。

文字が『消える』現象には、「ユーザー入力値にゴミがついて文字化けする」という現象が背後で起こっていたのでした。なお、この現象はIE6.0では修正されています。

この対策をしておかないと、例えば、CGIを使わずに簡単なパスワード認証を行う際に、「開けゴマ」を合言葉にしていた場合に、IE6.0ユーザーは入出できても、IE5.5や5.01ユーザーはいつまで経っても入出できないことになります。ただし、いずれにしても、Javascriptでこのような認証を行うと、HTMLソースを見ることにより簡単にパスワードが漏れてしまう可能性がありますので、ソースを暗号化したり、単純な文字列の比較ではなく、入力された文字列の値から導き出される値で、比較認証するという作業が必要になってきます。


次のページは、「EUCのページでmailtoのサブジェクトを指定するには?」です。<a href="mailto:info@shtml.jp?subject=文字化けについて">メールはこちら</a>とすることにより、ユーザーからの意見などのメールを、予めセットしておいたサブジェクト(件名)でもらうことができます。ただ、このままだとShift_JISのページでは動きますが、EUC-JPのページでは動きません。次のページでは、この対応策を考えます。