読者です 読者をやめる 読者になる 読者になる

Corredor

ウェブ、プログラミングの勉強メモ。

IE で日本語を含むパスにあるローカル HTML からクッキーを保存すると保存されたクッキーを取得できない件

なんのこっちゃという感じだろうから順に説明する。

  • 対象ブラウザは IE11。クッキーはデフォルトなら「インターネットオプション」から辿れる、C:\Users\(ユーザ名)\AppData\Local\Microsoft\Windows\INetCache\ に保存される。
  • ローカルにある HTML ファイルから JavaScript でクッキーを登録したい。
  • 当該 HTML ファイルまでのパスに日本語がなければ、問題なくクッキーを登録でき、ブラウザを閉じて再度開いてからも、そのクッキーを取得できる。
    例えば、C:\Hoge\Fuga\Test.html といったフルパスになる HTML ファイルからなら、クッキーの読み書きが正しくできる。
  • しかし、HTML ファイルまでのパスに日本語が交じると、クッキーは保存でき、ブラウザを閉じるまでは有効なのだが、ブラウザを開き直した時にそのクッキーが取得できない。
    例えば、C:\クッキー\取得\Test.html といったフルパスだと、クッキーの読み込みに失敗する。

原因を探ったところ、C:\Users\(ユーザ名)\AppData\Local\Microsoft\Windows\INetCache\ に保存されているクッキーファイルで、パスの日本語が文字化けしていた。「名前」列と「インターネットアドレス」の列に現れるパスの日本語部分が、文字化けしていたのだ。

なかなか良い方法が見つからなかったのだが、暫定的に、一旦、とりあえず、解決する方法を見つけたので紹介する。

クッキーの path 属性にドライブレターだけを指定する

解決方法は、path 属性に日本語を含まないように、その HTML ファイルがあるドライブのドライブレターだけを指定する

/* この JavaScript を実行する HTML は C:\クッキー\取得\Test.html (C ドライブ内) であると仮定する */

// 登録する値。エスケープ処理などは適宜行っておく
var value = $("#msg").val();

// msg という名前で value を登録する。
// 「path=/C:/」 とし、パスに日本語のフォルダ名を含めない。
// expires 属性は有効期限。2030年1月まで有効とする (第2引数の 0 は1月を表す)。
document.cookie = "msg=" + value + "; path=/C:/; expires=" + new Date(2030, 0).toUTCString();

こうすると、保存されるクッキーファイルの「名前」が file:///C:/ になり、「インターネットアドレス」列も Cookie:(ユーザ名)@~~local~~/C:/ となり、文字化けする箇所がなくなるので、ブラウザを一度閉じたあとでもクッキーを読み取ることができた。

当然、副作用がある。C ドライブ直下の HTML ファイル全てで有効なクッキー情報になってしまうので、同じドライブの他の HTML ファイルからも、同じクッキー情報を読み取ることができてしまう。名前が重複すれば意図しない上書きも発生しうるので、あまりそのドライブ内でクッキーを多用するローカル HTML ファイルがない場合にのみ、なんとか有効な方法といえる。

試したけどうまくいかなかった方法

色々な文献を漁ったが、IE で、ローカルファイルからクッキーを発行して、かつ日本語を含むパスで文字化けが発生して…、といったニッチな環境でのトラブルシューティングは見つからず。

  • HTML 文書のエンコードは Shift-JIS や UTF-8 など関係なし。
    ただ、登録されるクッキーの「インターネットアドレス」列で文字化けしている様子は、UTF-8 エンコードされた日本語を Shift-JIS 解釈したときの文字列に似ている (UTF-8 のページのエンコードを Shift-JIS に変えた時に似ている)。だが、HTML 文書の、ファイル自体のエンコード、および meta 要素の charset 指定は影響しなかった。
  • domain 属性を指定してみる … どういう値でも関係なし。
  • path 属性に、Punycode 変換したパスを指定してみる … 日本語は Punycode 変換されたが、異なるアドレスとみなされて読み取れなかった。

他に良い解決策をご存じの方がいましたら教えてください。