Home » May 2004 » Movable Type 3.0のCookie

Movable Type 3.0のCookie

TypeKeyの、というよりMT3の、Cookieハンドリングがどうも怪しいようです。

TypeKeyにサインインするとTypeKeyで設定しているニックネームまたはフルネームがCommenter Nameとして使われますが、それをCookieに格納する際のエンコーディング方法がMovableTypeのAuthor Nameとは異なります。この相違は、MovableTypeに含まれるJavaScriptでescape/unescapeメソッドを使用しているために生じます。

具体的には、Microsoft Internet Explorer 6 (SP1)の場合には次のようなことが起きるはずです(念のため、発生する現象はブラウザによって異なる可能性があります)。「(お)」という名前を設定すると、MovableTypeのAuther Nameでは%uFF08%u304A%uFF09という文字列がCookie (mtcmtauth)に格納されますが、TypeKey経由で設定されるCommenter Nameでは%EF%BC%88%E3%81%8A%EF%BC%89という文字列がCookie (commenter_name)に格納されます。前者はescapeメソッドでデコードできますが後者はできませんから、Comment PreviewなどでTypeKeyのCommenter Nameを表示しようとすると文字化けが生じます。


そもそもCookieに格納する文字列は、UTF-8に変換された上でURIエンコーディングされることになっています。これをエンコード、デコードするJavaScriptのメソッドはencodeURI(またはencodeURIComponent)、decodeURI(またはdecodeURIComponent)です。歴史的な経緯もあり、escape、unescapeメソッドがURI文字列をハンドリングするために使われてきましたが、その動作はブラウザごとに異なるため現在は推奨されていません。事実、MSIE6では、文字列をUCS2の16進表示にした上で「%u」をプレフィクスとして付けた文字列が生成され、これはunescapeではデコードできるが、decodeURI(decodeURIComponent)ではデコードできません。逆にencodeURI(encodeURIComponent)を使って正しくURIエンコーディングされた文字列は、unescapeではデコードできません。要するにescape、unescapeメソッドは使うべきでないのです。

ちなみにencodeURIとencodeURIComponent、decodeURIとdecodeURIComponentの違いはそれぞれ前者が「:/」などの予約文字を変換しないのに対して後者は変換するという違いです。したがって、URLや「:/」を含むCommenter Nameをクッキーに格納する際は後者を使う必要があります。

ここにテスト用のHTML(escapeTest.html)を置いておきます。

この問題の対策として、MovableTypeに含まれているJavaScriptでescape、unescapeメソッドをencodeURIComponent、decodeURIComponentメソッドに置き換えるべきだと思います。

function setCookie (name, value, expires, path, domain, secure) {
    var curCookie = name + "=" +
	(window.encodeURIComponent ?
	 encodeURIComponent(value) : escape(value)) +
	(expires ? "; expires=" + expires.toGMTString() : "") +
	(path ? "; path=" + path : "") +
	(domain ? "; domain=" + domain : "") +
	(secure ? "secure" : "");
    document.cookie = curCookie;
}
function getCookie (name) {
    var prefix = name + '=';
    var c = document.cookie;
    var nullstring = '';
    var cookieStartIndex = c.indexOf(prefix);
    if (cookieStartIndex == -1)
        return nullstring;
    var cookieEndIndex = c.indexOf(";", cookieStartIndex + prefix.length);
    if (cookieEndIndex == -1)
        cookieEndIndex = c.length;
    var value = c.substring(cookieStartIndex + prefix.length, cookieEndIndex);
    return window.decodeURIComponent ?
        decodeURIComponent(value) : unescape(value);
}

上記は、Ogawa::Memoranda: Movable Type 3.0DEのバグフィックスで説明しているdefault-templates.zipで修正できます。

このエントリーのトラックバックURL: http://as-is.net/mt/mt-tb.cgi/134

Links referred to this entry

Comments (1)

  1. 小粋空間さまでは 何度も ありがとうございました。
    encodeURIComponent/decodeURIComponent のほうにすると、
    「デコードするURIは有効なエンコーダではありません」 とエラーになってしまったので、
    結局、escape/unescape に統一しました。
    パッチが効いて、ちゃんと文字化けしないでいます。

Post a comment

Remember me?