COOKIEを正しくセットするには?

[上に] [前に] [次に]
あみ 1999/06/08(火) 09:02:06
フォームで送られてくるデータをクッキーに取り込むということをしたいんですけど、私が作ったプログラムではCOOKIEにセットされずに終わってしまうのです。
どなたか良いアドバイスをください。
ここのCOOKIEの説明も読んだんですけどいまいち理解できなくて…。よろしくお願いします。

〜*〜*〜*〜*以下プログラムです*〜*〜*〜
#!/usr/local/bin/perl

require 'jcode.pl';

if($ENV{"REQUEST_METHOD"} EQ 'GET'){
$INPUT = $ENV{"QUERY_STRING"};
}
else{
read(STDIN,$INPUT,$ENV{"CONTENT_LENGTH"});
}

print "Set-Cookie: ";
print "$form{$name}; ";
print "CookieData=$name; ";
print "expires=Sat, 1-Jan-2000 00:00:00 GMT; ";
print "path=/~fuji/futaba/cgi; ";
print "domain=172.21.8.26\n";
print "\n";

@DATA = split(/&/,$INPUT);
foreach $ABC(@DATA){
($name,$value) = split(/=/,$ABC);
$value =~tr/+/ /;
$value =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
&jcode'h2z_sjis(*value);
&jcode'convert(*value,'sjis');
$form{$name} = $value;


print "Content-type: text/html\n";
print "<HTML><TITLE>例題2</TITLE>";
print "<BODY>";
print "<CENTER>";
print "<H3>あなたのいれたデータは:</H3><BR>";
print "<CENTER>";
print "<FONT SIZE=5 COLOR=#ff0000><B>変数名=$name</B></FONT><BR>";
print "<FONT SIZE=5 COLOR=#ff0000><B>値=$ENV{'HTTP_COOKIE'}</B></FONT><BR>";
print "</CENTER>";
}
print "</BODY></HTML>";

Aurai [E-Mail] 1999/06/09(水) 01:27:18
まずクッキーの使い方をかなり間違えているように見受けられます
>@DATA = split(/&/,$INPUT);
以下のルーチンで%formを取り出す前に$form{$name}を参照しているのも気になります
SetCookieの部分の$nameがどこからくるのかも理解できません
>print "<HTML><TITLE>例題2</TITLE>";
<HEAD>が抜けています
とりあえずリファレンスをもう一度よく見て、サンプルスクリプトをいじってみてください

羽崎 1999/06/09(水) 12:50:25
私なりに解析しました。(^^)

#ここから
jcode.plをrequire

クエリストリングや標準入力からの入力を$INPUTに代入

クッキーをブラウザにセット
(しようとしているが$form{$name}に値が入っていないため代入
しようとしていると思われるデータはセットされない)

$INPUTのデータを分解しデコードして%form($form{〜})にセットし
HTTPヘッダを出力してHTML文を出力。奇妙な動きです。
なぜなら、$INPUTを&で区切ったもの各々を@DATAにいれているが、
そのあとのforeachループでループ一回するたびにHTTPヘッダ
(Content-type〜の行)を出力しているので、HTTPの仕組みをあまり
知らないように見うけられます。
この場合はヘッダの出力は一度でよいと思われます。

#ここまで

井かに私が書いた例を・・・
(とても完璧なものとは言えませんが参考にしてください)

#ここから

#!/usr/local/bin/perl

require 'jcode.pl';

if($ENV{"REQUEST_METHOD"} eq 'GET'){ # EQをeqに変更
$INPUT = $ENV{"QUERY_STRING"};
}
else{
read(STDIN,$INPUT,$ENV{"CONTENT_LENGTH"});
}

if ($INPUT eq ""){
# $INPUT入力が無い時のページ
print "Content-type: text/html\n\n";
print "<HTML><HEAD><TITLE>入力</TITLE></HEAD>";
print "<BODY>";
print "<FORM ACTION=$ENV{'SCRIPT_NAME'} METHOD=GET>";
print "<INPUT TYPE='text' NAME='data1'>";
print "<INPUT TYPE='text' NAME='data2'>";
print "<INPUT TYPE='submit'>";
print "</FORM>";
print "</BODY></HTML>";
exit;
}
elsif($INPUT eq "view"){
# クッキーを見るモード
&view; # サブルーチンviewへ
exit;
}
# クエリストリング(標準入力)からフォームのデータに分解
@DATA = split(/&/,$INPUT);
foreach $ABC(@DATA){
($name,$value) = split(/=/,$ABC);
$value =~tr/+/ /;
$value =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
&jcode'h2z_sjis(*value);
&jcode'convert(*value,'sjis');
$form{$name} = $value;
}

# クッキーデータのセット

# このへんの動きは、クッキーはひとつのページひとつの名前と値のセット
#「名前=値」しか呼び出せないので、値に複数の「名前:値」を&でくっつけて
# 保存しているので、ちょっと複雑になっています。(クッキーの仕様参照)

foreach $key (keys %form){
# エンコード(URLにはアスキーコードしか送らないようにする)
$key        =~ s/(\W)/sprintf("%%%02X", unpack("C", $1))/eg;
$form{$key} =~ s/(\W)/sprintf("%%%02X", unpack("C", $1))/eg;
# クッキーデータをバッファリング(ためこむ)
$cbuf{$key} = "$key:$form{$key}";
}
$COOKIE = join("&",values(%cbuf));

print "Set-Cookie: ";
print "$ENV{'SCRIPT_NAME'}_CookieData=$COOKIE; "; # 変更可能
# ↑「スクリプト名_CookieData=名前1:値1&名前2:値2&名前3:値3&名前4:値4」となる
print "expires=Sat, 1-Jan-2000 00:00:00 GMT; ";
print "path=/~fuji/futaba/cgi; ";
print "domain=172.21.8.26\n";
# print "\n"; # あとに「Content-typeのヘッダ」が来るので改行してはいけない
print "Content-type: text/html\n\n"; # 改行は2回
print "<HTML><HEAD><TITLE>例題2</TITLE></HEAD>";
print "<BODY>";
print "入力したときには見れないので";
print "<a href='$ENV{SCRIPT_NAME}?view'>リロードしてクッキーを見る</a>";
print "</BODY></HTML>";

# クッキーを見るためのサブルーチン
sub view{
# クッキーデータの取り出し。
# クッキーをセットしているときの動きがわかれば
# このへんの動きも理解できるはず。
$cookies = $ENV{'HTTP_COOKIE'};
@pairs = split(/;/,$cookies);
foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair);
$name =~ s/ //g;
$DUMMY{$name} = $value;
}
$dummy = $DUMMY{"$ENV{'SCRIPT_NAME'}_CookieData"};
@cookies = split(/&/,$dummy);
foreach $key (@cookies){
($name,$value) = split(/:/,$key);
# クッキーデータをデコード
$name  =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
$value =~s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
$cookies{$name} = $value;
}

# HTTPヘッダ及びHTML出力
print "Content-type: text/html\n\n"; # 改行は2回
print "<HTML><HEAD><TITLE>例題2</TITLE></HEAD>";
print "<BODY>";
print "<CENTER>";
print "<H3>あなたのいれたデータは:</H3><BR>";
print "<CENTER>";
foreach $key (keys(%cookies)){
print "<FONT SIZE=5 COLOR=#ff0000><B>変数名=$key</B></FONT><BR>";
print "<FONT SIZE=5 COLOR=#ff0000><B>値=$cookies{$key}</B></FONT><BR>";
}
print "</CENTER>";
print "</BODY></HTML>";
}

#ここまで
#長文失礼しました

あみ 1999/06/09(水) 15:25:39
Auraiさん、羽崎さん、ありがとうございます。
私のプログラムがとんでもなく間違えていたんですね。
羽崎さんのプログラムを頂こうとおもったのですがちょっと難しくて…。
動かしたんですけど、COOKIEにセットはされるものの表示が上手くいかないんです。
何かつけたさないといけないのでしょうか??
こんなに有難いレスを頂いたのにすみません。
表示の部分を教えて頂けないでしょうか?
それとこのプログラムはHTMLからデータを送ってもいいですか?データの数に制限があるのでしょうか?
知識が足りなくてすみません。よろしくお願いします。

羽崎 1999/06/09(水) 16:33:21
>羽崎さんのプログラムを頂こうとおもったのですがちょっと難しくて…。
具体的にどこらへんが難しいのか(全部というのはナシ、必ずわからない
ところは特定されているはずですから)教えてください。

>動かしたんですけど、COOKIEにセットはされるものの表示が上手くいかないんです。

表示がうまく行かない、とは具体的にどういうことですか?
1、画面が変わらない。
2、サーバエラーの画面になる
3、なにかをダウンロードしようとする。
4、ページは表示されるが、クッキーが表示されない。
5、ブラウザがタイムアウトする。

>それとこのプログラムはHTMLからデータを送ってもいいですか?データの数に制限があるのでしょうか?
ありません。他のHTMLからPOST(GET)しても問題ありません。

>知識が足りなくてすみません。よろしくお願いします。
できれば、CGIかPerlの解説書(解説しているwebサイト)を片手に
わからないところを”具体的”に質問していただけると答えやすいです。

[上に] [前に] [次に]