漢字クッキーをPerlでSetし、JavaScriptでGetする!
まずは、以下の引用(質問と回答)をご覧ください。
質問
ieのjavascriptでescapeすると
http://oshiete1.goo.ne.jp/kotaeru.php3?q=1257793
おはよう ⇒ %u304A%u306F%u3088%u3046
となりますが、これをperlなどで同じように
エンコードする方法はありませんでしょうか?
回答
使い方は
$escaped_str = js_escape($str, $icode);
となります。
$icode には $str のエンコーディング("sjis" や "euc-jp" など)を指定して下さい。
# print js_escape("おはよう", "sjis"); などsub js_escape { use Encode; my $str = join "", map sprintf("%%u%04X", $_), unpack "n*", encode("utf16be", decode($_[1], $_[0])); my ($ch, $hex); $str =~ s<%u00(..)>{ ($ch = pack("H2", $hex = $1)) =~ m<[^\w\@.*/+-]> ? "%$hex" : $ch }eg; $str; }http://oshiete1.goo.ne.jp/kotaeru.php3?q=1257793
js_escapeの解説
- join...のソースのdecode($_[1], $_[0])は、$_[0]の文字列を$_[1]で指定された漢字コードからUTF-8にデコードしています。
- encode("utf16be", decode($_[1], $_[0]))は、1でデコードしたものをutf16beにエンコードしています。
- unpack "n*", encode("utf16be", decode($_[1], $_[0]))は、2でエンコードしたものをリストにアンパックしています。
- map sprintf("%%u%04X", $_)は、3を%uXXXXの形式にフォーマットし、それらのリストを返します。
- join ""は、4のリストを連結して一つの文字列にします。
- s<%u00(..)>...のソースは、1バイト文字(%u00(..))を、[^\w\@.*/+-]で弾いたものは%$hexとし、それ以外は$chとして置換します。
- 留意点としては、置換や検索の区切り文字に<>や{}を使用しています。
- つまり、join...のソースは、2バイト系(漢字)をデコードし、 s<%u00(..)>...のソースは1バイト系をデコードしています。
以下にjs_escapeを使ったサンプルをアップしときます。
CGI(Perl)ソース(漢字クッキーをPerlでSetする)
#!/usr/local/bin/perl use strict; &set_cooKie('test_javascript_cookie1', 'ID:111,X X:あ,YY:1あ1,ZZ:あ1あ', 1,'','/'); &set_cooKie('test_javascript_cookie2', 'ID:111,XXX:い,YY:1あ1,ZZ:あ1あ', 1,'','/'); print <<"HERE1"; Content-type: text/html; charset=Shift_JIS <html> <body> <p>漢字クッキーをPerlでSetし、JavaScriptでGetする!</p> </body> </html> HERE1 sub set_cooKie { my ($CookieName, $cookie, $daycount, $domain, $path) = @_; my ($secg,$ming,$hourg,$mdayg,$mong,$yearg,$wdayg) = gmtime(time + $daycount*24*60*60); my @week = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat'); my @mons = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'); my $date_g = sprintf("%s, %02d\-%s\-%04d %02d:%02d:%02d GMT", $week[$wdayg],$mdayg,$mons[$mong],$yearg+1900,$hourg,$ming,$secg); $cookie = js_escape($cookie, "sjis"); if ($domain eq '' && $path eq '') { print "Set-Cookie: $CookieName=$cookie; expires=$date_g; \n"; } elsif ($domain eq '') { print "Set-Cookie: $CookieName=$cookie; expires=$date_g; path=$path; \n"; } elsif ($path eq '') { print "Set-Cookie: $CookieName=$cookie; expires=$date_g; domain=$domain; \n"; } else{ print "Set-Cookie: $CookieName=$cookie; expires=$date_g; domain=$domain; path=$path \n"; } } sub js_escape { use Encode; my $str = join "", map sprintf("%%u%04X", $_), unpack "n*", encode("utf16be", decode($_[1], $_[0])); my ($ch, $hex); $str =~ s<%u00(..)>{ ($ch = pack("H2", $hex = $1)) =~ m<[^\w\@.*/+-]> ? "%$hex" : $ch }eg; $str; }
HTML(JavaScript)ソース(漢字クッキーをJavaScriptでGetする)
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> <title>漢字クッキーをPerlでSetし、JavaScriptでGetする!</title> </head> <body> <script type="text/javascript"> function getCookie(){ this.data = new Array(); this.string = (document.cookie) ? document.cookie.split(';') : new Array(); for (var i = 0; i != this.string.length; i++) { this.data[this.string[i].split('=')[0].match(/[^ ].*/)] = unescape(this.string[i].split('=')[1]); } } getCookie = new getCookie(); document.write(getCookie.data.test_javascript_cookie1, "<br>"); document.write(getCookie.data.test_javascript_cookie2, "<br>"); </script> </body> </html>