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

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

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

クッキーCGIサンプル

クッキーは、Webサイトのセッション管理や前回入力値の再入力不要を実現するのに使います。
以下のようなサンプルを作ってみました。URLエンコードデコードにも対応しています。

# セットクッキー:第一引数はクッキー名、第二引数は格納データ、第三引数はクッキー有効期間(日単位)
&SetCookie("CookieName", "aaa:111,bbb:あいう", 1);


# ゲットクッキー:第一引数はクッキー名
my %COOKIE = &GetCookie("CookieName");
print "Content-type: text/html; charset=Shift_JIS", "\n\n";
print <<"EOH";
<html>
<body>
<p>aaa:$COOKIE{"aaa"},bbb:$COOKIE{"bbb"}</a>
</body>
</html>
EOH


sub SetCookie {
    my ($CookieName, $cookies, $daycount) = @_;
    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);
    $cookies =~ s/([^\w .-~])/'%'.unpack('H2', $1)/eg;  # URLエンコード
    $cookies =~ tr/ /+/;  # URLエンコード
    print "Set-Cookie: $CookieName=$cookies; expires=$date_g\n";
}
sub GetCookie {
    my ($CookieName) = @_;
    my (%DUMMY, %COOKIE, $name, $value);
    my $cookies = $ENV{'HTTP_COOKIE'};
    my @pairs = split(/;/, $cookies);
    foreach my $pairs (@pairs) {
        ($name, $value) = split(/=/, $pairs);
        $name =~ s/ //g;
        $DUMMY{$name} = $value;
    }
    @pairs = split(/,/, $DUMMY{"$CookieName"});
    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);
        $COOKIE{$name} = $value;
    }
    return %COOKIE;
}

(尚、本サンプルは、KENT-WEBのfantasy.cgiをベースにしています)

プログラムの制限として

  • 格納データ($cookies)は、項目と値のデリミタが『:』のデータで、そのリストのデリミタが『,』です(aaa:111,bbb:222)。

クッキーの制限として

  • クッキーの数は、最大で300個
  • 1つのクッキーは、NAME($CookieName)とVALUE($cookies)を合わせて、最大で4キロバイト
  • 1つのサーバー、あるいはドメインにつき、クッキーの数は最大で20個

参考:http://www.studyinghttp.net/cookies

クッキーの補足として

サンプルでは使っていませんが、path属性とdomain属性を指定すると別サーバーや複数サーバーへクッキーを送信することが出来ます。
逆にこれを指定しない場合は、PCクライアントとCGIサーバー間でのクッキー送受信になります。

URLエンコードの補足として

インターネット初期ではアスキー文字(7bit)が標準で、それ意外は文字化けする可能性があったので、以下のようにエンコードするようになった。

A〜Z a〜z 0〜9 - . _ はそのまま。
半角スペースは + に変換。
その他はすべて % に16進の2桁の文字コード
たとえば、「あ」0x2422なら %24%22になる。

ちなみに、URLデコードは、URLエンコードしたものから元にもどすこと。