小池啓仁 ヒロヒト応援ブログ By はてな

小池啓仁(コイケヒロヒト)の動画など。

小池啓仁 ヒロヒト応援ブログ By はてな

漢字クッキーをJavaScriptでSetしPerlでGetする!

クッキー出力で、IEJavaScriptで漢字コードをescapeすると%uのあとにutf16be(4文字でビックエンディアン)になります。
尚、このURLエンコードですが、これは標準仕様でなく、MSの独自仕様です。

このクッキーをCGI(Perl)でデコードしてSJISにするサブルーチン(GetCookieForJavaScript)を作ってみました。

JavaScriptクッキー書き込みHTMLサンプル

<html>
<script type="text/javascript">
function SetCookie(){
         SetCookie.put = function(name ,data ,limit, domain, path) {
             var date = ''; 
             var wkdomain = ''; 
             var wkpath = ''; 
             if (limit) {
                 today = new Date();
                 today.setTime(today.getTime()+1000*60*60*24*limit);
                 date = ';expires='+today.toGMTString();
             }
             if (domain != '') {
                wkdomain='domain=' + domain + ';';
             }
             if(path != '') {
                wkpath='path=' + path + ';';
             }
             document.cookie = name + '=' + escape(data) + date + wkdomain + wkpath;
        }
}
new SetCookie();
//SetCookie.put:クッキー設定メソッド
//第1引数:クッキー名
//第2引数:データ(漢字OK)
//第3引数:有効期限(日にち単位で指定)
//第4引数:ドメインの値
//第5引数:パスの値
SetCookie.put("TEST_COOKIE","DATA1:1111あ,DATA2:やaaaす",1, "localhost", "/cgi-bin/");
</script>
<body>
<p><a href="../cgi-bin/cookie.cgi">クッキーテスト</a></p>
</body>
</html>

JavaScriptクッキー読み込みCGIプログラムサンプル

#!/usr/bin/perl -w
use strict;

my %COOKIE = &GetCookieForJavaScript("TEST_COOKIE");

print "Content-type: text/html; charset=Shift_JIS", "\n\n";
print <<"EOH";
<html>
<body>
<p>DATA1:$COOKIE{"DATA1"},DATA2:$COOKIE{"DATA2"}</p>
</body>
</html>
EOH

# クッキー取得サブ
sub GetCookieForJavaScript {
    my ($CookieName) = @_;
    my (%DUMMY, %COOKIE, $name, $value);
    my $cookies = $ENV{'HTTP_COOKIE'};
    my @pairs = split(/;/, $cookies);
    foreach my $pairs (@pairs) {
        $pairs =~ tr/+/ /; # URLでコード
        $pairs =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack('H2', $1)/eg; # URLでコード
       ($name, $value) = split(/=/, $pairs);
        $name =~ s/ //g;
        $DUMMY{$name} = $value;
        #debug($value);
    }
    @pairs = split(/,/, $DUMMY{"$CookieName"});
    foreach my $pairs (@pairs) {
        ($name, $value) = split(/:/, $pairs);
        $COOKIE{chgU2S($name)} = chgU2S($value);
    }
    return %COOKIE;
}

# ユニコード(utf16be)からシフトJIS(shiftjis)への変換サブ
sub chgU2S {
use Encode qw(from_to);
    my ($value) = @_;
    my $offset = 0;
    my $chgvalue = "";
    for (my $i = 0; $i < length($value); $i++) {
        my $wk = substr($value, $offset, 1);
        if (($wk eq "%") && (substr($value, $offset+1, 1) eq "u")) {
           $wk = pack('H4', substr($value, $offset+2, 4));
           from_to($wk, 'utf16be', 'shiftjis');
           $chgvalue  = $chgvalue . $wk;
           $offset = $offset + 6;
        }
        else {
           $chgvalue  = $chgvalue . $wk;
           $offset++;
        }
    }
    return $chgvalue;
}

補足:
クッキーは、セットしたドメイン&パスのところでしか、ゲットできません。
つまり、セットしたドメイン&パスとCGIが動くドメイン&パスが一致していなければなりません。