au 端末で XHTML なページが文字化けする件の考察

具体的には imoTwitau 端末で見ると文字化けしてしまう、と云う話。
ようやく理由が判ったので、ちょっとパターン検証してみました。(簡易的な CGI を作成してチェックしました)

ページの文字コード Content Type 文字化けの有無
UTF-8 application/xhtml+xml あり
UTF-8 text/html なし
Shift JIS application/xhtml+xml なし
Shift JIS text/html なし

いい感じで XHTML + UTF-8 の場合だけ文字化けしています。。。
ちなみに、 imoTwit のレスポンスヘッダを確認したところ、 Cookieless でセッションを扱う場合のみ、 application/xhtml+xml になっている模様。(なんだそれ。。。)
一方、 Cookieを利用する場合は text/html で返ってきている様です。…… ASP.NET の仕様?
うーむ。この設定を変更できれば解決な気はするけど、調べるの面倒そう。(ぉ
もし変更出来ないとなると、 UA チェックして文字コードを変える、とかになってしまいそうですね。(確か、それは初音さんのポリシーに反するはず)
……結局、 au は dis られる、で F/A なのかなぁ。。。
※ちなみに、チェックに使用した CGI は以下な感じ。(途中で面倒になっていい加減な書き方をしています ^^; )

#!/usr/bin/perl

use strict;
use warnings;
use utf8;

binmode STDIN, ":utf8";
binmode STDOUT, ":utf8";

use CGI;

&main();

sub main() {
    my $cgi = new CGI;
    my $param = &check_param($cgi);
    binmode STDOUT, sprintf(':encoding(%s)', $param->{'charset'});
    printf 'Content-Type: %s' . "\n", &get_contentype($param);
    print "\n";
    &print_content($param);
}

sub check_param($) {
    my $_cgi = shift;
    my $param = { charset => 'utf8', type => 'xhtml' , cgi => $_cgi };
    my $value = $_cgi->param('charset');
    unless (defined $value) {
        $value = '';
    }
    if ($value eq 'shiftjis' || $value eq 'shift_jis' || $value eq 'Shift_JIS' || $value eq 'SJIS') {
        $param->{'charset'} = 'shiftjis';
    }
    $value = $_cgi->param('type');
    unless (defined $value) {
        $value = '';
    }
    if ($value eq 'html') {
        $param->{'type'} = 'html';
    }
    return $param;
}

sub get_contentype($) {
    my $_param = shift;
    my $contenttype = '';
    if ($_param->{'type'} eq 'xhtml') {
        $contenttype = 'application/xhtml+xml';
    } else {
        $contenttype = 'text/html';
    }
    $contenttype .= sprintf '; charset=%s', &get_htmlencoding($_param->{'charset'});
    return $contenttype;
}

sub get_htmlencoding($) {
    my $_encoding = shift;
    my $htmlencoding = 'utf-8';
    if ($_encoding eq 'shiftjis') {
        $htmlencoding = 'Shift_JIS';
    }
    return $htmlencoding;
}

sub print_content($) {
    my $_param = shift;
    printf '<?xml version="1.0" encoding="%s" ?>' . "\n", &get_htmlencoding($_param->{'charset'});
    print '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">' . "\n";
    print '<head>' . "\n";
    printf '<meta http-equiv="Content-Type" content="%s" />' . "\n", &get_contentype($_param);
    print '<title>Test Page</title>' . "\n";
    print '</head>' . "\n";
    print '<body>' . "\n";
    print '<h1>■Test Page■</h1>' . "\n";
    print '<p>■ログイン</p>' . "\n";
    print '<p>▼パスワード:</p>' . "\n";
    print '<dl>' . "\n";
    print '<dt>query</dt>' . "\n";
    printf '<dd>%s</dd>' . "\n", ($ENV{QUERY_STRING} or '');
    print '<dt>charset</dt>' . "\n";
    printf '<dd>%s</dd>' . "\n", $_param->{'charset'};
    print '<dt>type</dt>' . "\n";
    printf '<dd>%s</dd>' . "\n", $_param->{'type'};
    print '</dl>' . "\n";
    print '</body>' . "\n";
    print '</html>' . "\n";
}

( 2008-12-03T15:50 追記)
一番大事なことを書き損ねました。
この情報は、 id:gifnksm さんの記事で知りました。
貴重な情報、ありがとうございます♪