CGI.pmを使わずにCookieを利用する方法

CGIテクニック集トップへ





概要

CGI.pmを使わずにCookie(クッキー)の設定、読み込みをする方法です。 Apache1.3では正常に動いていた日本語のCookieがApache2では文字化けしてしまいますのでそれを文字化けしないように処理します。 CGI.pmを使う方法は、CGI.pmを使ってCookieを利用する方法を参照してください。

必用な処理

  1. Cookieに入れる文字列をエンコードする
  2. 有効期限の日時をフォーマットに合うように作成する
  3. クッキーを発行する
  4. httpヘッダを出力する
  5. 読み込む際には$ENV{HTTP_COOKIE}でクッキーを読み込む
  6. 取り込んだデータをデコードする

サンプルコード

 my $text = '日本語文字列';
 
 #Cookie設定
 my $cook = &cookie_encode($text);
 my $date_gmt = &cookdate(1);
 
 print "Set-Cookie: mycookie=$cook; expires=$date_gmt\n";
 print "Content-Type: text/html\n\n";
 
 #Cookie読み込み
 my $readcookie = $ENV{'HTTP_COOKIE'};
 $readcookie = &cookie_decode($readcookie);
 
 sub cookie_encode {
     my $a = shift;
     $a =~ s/([\W])/sprintf("%%%02X", ord($1))/eg;
     return $a;
 }
 
 sub cookdate {
     my $expire = shift;
 
     my ($secg,$ming,$hourg,$mdayg,$mong,$yearg,$wdayg,$ydayg,$isdstg) = 
        gmtime(time + $expire * 86400);
    
     $yearg = $yearg + 1900;
     
     if ($yearg < 10)  { $yearg = "0$yearg"; }
     if ($secg < 10)   { $secg  = "0$secg";  }
     if ($ming < 10)   { $ming  = "0$ming";  }
     if ($hourg < 10)  { $hourg = "0$hourg"; }
     if ($mdayg < 10)  { $mdayg = "0$mdayg"; }
     
     my $youbi = ('Sunday', 'Monday', 'Tuesday', 'Wednesday',
                 'Thursday', 'Friday', 'Saturday') [$wdayg];
     
     my $month = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
                 'Aug', 'Sep', 'Oct', 'Nov', 'Dec') [$mong];
     
     my $date_gmt = "$youbi, $mdayg\-$month\-$yearg $hourg:$ming:$secg GMT";
     
     return($date_gmt);
 }
 
 sub cookie_decode {
     my $a = shift;
     $a =~ s/%([A-Fa-f0-9][A-Fa-f0-9])/pack("C", hex($1))/eg;
     return $a;
 }

コードの解説

 my $text = '日本語文字列';

この例でクッキーに入力する文字列です。

 #Cookie設定
 my $cook = &cookie_encode($text);

文字列をURIエンコードします。これがないとApache2で日本語が文字化けします。Apache1.3ではこの部分が無くても正常に動作します。

 my $date_gmt = &cookdate(1);

クッキーに入力する有効期限の日時のフォーマットを作成します。このルーチンは後に記述されています。

 print "Set-Cookie: mycookie=$cook; expires=$date_gmt\n";

クッキーを発行します。この例ではクッキー名をmycookieとしています。 この時点でクッキーは設定されていますがhttpヘッダを出力しないと処理は完了しません。

 print "Content-Type: text/html\n\n";

httpヘッダを出力します。Set-CookieからContent-Typeまでの間に他のヘッダが入ってもかまいません。

 #Cookie読み込み
 my $readcookie = $ENV{'HTTP_COOKIE'};

クッキーを読み込む。

 $readcookie = &cookie_decode($readcookie);

読み込んだ文字列をデコードする。登録したクッキーは$read_cookieに入っています。この例では「日本語文字列」という文字列が入っています。

 sub cookie_encode {
     my $a = shift;
     $a =~ s/([\W])/sprintf("%%%02X", ord($1))/eg;
     return $a;
 }

URIエンコードルーチンです。クッキー発行前に利用されます。

 sub cookdate {
     my $expire = shift;
 
     my ($secg,$ming,$hourg,$mdayg,$mong,$yearg,$wdayg,$ydayg,$isdstg) = 
        gmtime(time + $expire * 86400);
    
     $yearg = $yearg + 1900;
     
     if ($yearg < 10)  { $yearg = "0$yearg"; }
     if ($secg < 10)   { $secg  = "0$secg";  }
     if ($ming < 10)   { $ming  = "0$ming";  }
     if ($hourg < 10)  { $hourg = "0$hourg"; }
     if ($mdayg < 10)  { $mdayg = "0$mdayg"; }
     
     my $youbi = ('Sunday', 'Monday', 'Tuesday', 'Wednesday',
                 'Thursday', 'Friday', 'Saturday') [$wdayg];
     
     my $month = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
                 'Aug', 'Sep', 'Oct', 'Nov', 'Dec') [$mong];
     
     my $date_gmt = "$youbi, $mdayg\-$month\-$yearg $hourg:$ming:$secg GMT";
     
     return($date_gmt);
 }

有効期限の時間フォーム作成ルーチンになります。

 Thursday, 18-Jan-2007 06:53:17 GMT

のような記述になります。時間はGMTです。

 sub cookie_decode {
     my $a = shift;
     $a =~ s/%([A-Fa-f0-9][A-Fa-f0-9])/pack("C", hex($1))/eg;
     return $a;
 }

デコードルーチンになります。クッキーを読み込んだ後に利用されます。

関連するCGIテクニック

CGI.pmを使ってCookieを利用する方法